Skip to content

feat(price_validate): add price validation tool and automated pricing CI#231

Draft
dm3ch wants to merge 14 commits intocloudpilot-ai:mainfrom
dm3ch:feat/price-validator
Draft

feat(price_validate): add price validation tool and automated pricing CI#231
dm3ch wants to merge 14 commits intocloudpilot-ai:mainfrom
dm3ch:feat/price-validator

Conversation

@dm3ch
Copy link
Copy Markdown
Collaborator

@dm3ch dm3ch commented Mar 28, 2026

What type of PR is this?

/kind feature
/kind cleanup

What this PR does / why we need it:

This PR refactors current pricing logic and updates initial pricing logic. It's split from #218 and needed to introduce our own instance price calculation (based on GCP SKUs) later, which that PR would bring.

Three things in one PR (they're tightly coupled):

  1. instanceprice package and pricing.go changes to use this package - extracts Cyclenerd CSV pricing into pkg/providers/pricing/instanceprice/ with a stable interface, ready for the SKU-based rewrite in PR DRAFT: Calculate machine type prices based on CloudBilling SKUs instead of relying on 3rd party data source  #218.
  2. price_validate tool - This tool would be used for update of the initial-prices file and validating our instanceprice results over data from Cyclenerd and GCP website sources, to help to catch price mismatches.
  3. .github/workflows/update-pricing.yaml CI job - to automatically create PRs with updated initial prices if they changed according to instanceprice package.

Which issue(s) this PR fixes:

Related #33

Special notes for your reviewer:

  • Most of removal lines is the result of updating initial-prices.json as part of this PR.
  • Running price_validate now will report a high number of mismatches. It's expected and fine. That happens because during validation we treat pricing info from GCP website as more trustworthy compared to Cyclenerd pricing info. These mismatches would be fixed by new instanceprice implementation that exists in DRAFT: Calculate machine type prices based on CloudBilling SKUs instead of relying on 3rd party data source  #218.
  • hack/tools/price_validate/gcpweb.go is a little bit messy, as we parse data from JS blocks of HTML pages. I don't know how to make it easier to read. But I assume that's fine, cause it's isolated code in a supplementary tool.
  • We need @jwcesign to create CI secrets for a new job. Details about needed permissions and format can be found in the comments in .github/workflows/update-pricing.yaml file.
  • Separate mutexes for OnDemand and Spot prices data were dropped as now we retrieve prices out of mutex (cause in DRAFT: Calculate machine type prices based on CloudBilling SKUs instead of relying on 3rd party data source  #218 price calculation can take few minutes) and only use a common mutex to guard change of retrieved prices in pricing provider.
  • This PR was prepared with AI assistance (Claude Code). All changes have been reviewed and verified by the author.

Does this PR introduce a user-facing change?

NONE

@gitautomator
Copy link
Copy Markdown
Contributor

gitautomator bot commented Mar 28, 2026

Thanks to your contribution, the maintainers will review it as soon as they can!

@gitautomator gitautomator bot added enhancement New feature or request cleanup General maintenance or restructuring of code go Pull requests that update go code labels Mar 28, 2026
@dm3ch dm3ch marked this pull request as draft March 28, 2026 23:19
@dm3ch dm3ch marked this pull request as ready for review March 30, 2026 02:07
@dm3ch dm3ch marked this pull request as draft March 30, 2026 02:12
@dm3ch dm3ch force-pushed the feat/price-validator branch from 83f598b to c5d3c6e Compare April 6, 2026 12:32
@dm3ch dm3ch marked this pull request as ready for review April 6, 2026 12:33
@dm3ch dm3ch marked this pull request as draft April 6, 2026 12:39
@dm3ch dm3ch force-pushed the feat/price-validator branch from 8b0d4c7 to f225b34 Compare April 8, 2026 23:23
…ased implementation

Extract GCP instance pricing into pkg/providers/pricing/instanceprice/ with a
clean interface (New, Close, FetchPrices, IsBlacklisted) shaped for the
upcoming SKU-based rewrite. The Cyclenerd CSV implementation satisfies the
interface now; the rewrite will swap internals without changing the surface.

pricing.go is updated to use instanceprice.Client and adopts cleaner patterns:
- Single sync.RWMutex (was separate muOnDemand/muSpot)
- All JSON parsing / map building outside the lock; only the final pointer
  swap is guarded
- LivenessProbe returns an error when no prices are loaded (was a no-op)
- pricesStorage is a defined type, not an alias

initial-prices.json replaces initial-on-demand-prices.json with the
{saved_at, prices:{region:{machine:{on_demand,spot}}}} format that
price_validate and the update-pricing CI workflow produce, so make
update-pricing becomes a plain file copy with no conversion step.

pricing/controller.go names the refresh interval constant and drops the
unnecessary multierr wrapper around a single UpdatePrices call.

Signed-off-by: Dmitry Chepurovskiy <[email protected]>
@dm3ch dm3ch force-pushed the feat/price-validator branch 14 times, most recently from ad9ddbf to e5a31f0 Compare April 13, 2026 22:42
Introduces the price_validate tool that compares computed instance prices
against two independent reference sources (Cyclenerd CSV and GCP web pricing).

Also adds update-pricing.yaml GitHub Actions workflow that runs weekly and
opens a PR when initial-prices.json needs updating.

Key design decisions:
- Use *time.Time with omitempty for saved_at so computed.json omits the
  timestamp entirely — only cache files carry it. This prevents spurious
  weekly PRs when prices have not actually changed.
- price_validate exits 0 always; non-zero exit for mismatches is deferred
  to the upcoming SKU-based pricing rewrite (tracked in cloudpilot-ai#218).
- Only roles/compute.viewer is required for the CI service account;
  the Billing Catalog API is public and needs no IAM grant.

Signed-off-by: Dmitry Chepurovskiy <[email protected]>
@dm3ch dm3ch force-pushed the feat/price-validator branch from 9a20369 to 89fd8b5 Compare April 13, 2026 23:08
@dm3ch
Copy link
Copy Markdown
Collaborator Author

dm3ch commented Apr 14, 2026

E2E Test Results

Branch: feat/price-validator
Status: ✅ Test Suite Passed
Duration: 11m 17.497s
Cluster: karpenter-e2e-cluster (us-central1-f)

Suite Specs Result
Consolidation 1/1 ✅ PASS (131s)
Drift 1/1 ✅ PASS (172s)
Expiration 1/1 ✅ PASS (260s)
GC 0/1 ⏭ skipped (no specs ran)
Networking 0/1 ⏭ skipped (no specs ran)
Provisioning 4/4 ✅ PASS (103s)

All executed specs passed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cleanup General maintenance or restructuring of code enhancement New feature or request go Pull requests that update go code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant