Fix commitment discount eligibility fetch (Retail Prices API pagination)#2164
Fix commitment discount eligibility fetch (Retail Prices API pagination)#2164RolandKrummenacher wants to merge 3 commits into
Conversation
The weekly Update Commitment Discount Eligibility workflow has been failing. Two independent problems: 1. The Azure Retail Prices API now rejects the multi-field $orderby the script sent (HTTP 400), and its NextPageLink generator decrements $top per page into negative values (also 400). $orderby/$top are undocumented anyway. Rewrote the fetch to follow NextPageLink verbatim, shard by serviceFamily, and repeat each shard unioning by meterId until the set is stable -- which makes a full run reproducible (was ~24% run-to-run drift) and complete (captures meters the old single $skip walk silently dropped). Added a completeness guard that aborts before writing if the run is materially incomplete, and switched to writing the freshly-fetched set (retired meters age out instead of accumulating forever). 2. GitHub Actions cannot open pull requests in this org, so the gh pr create step always failed. The workflow now pushes a branch and surfaces a one-click create-PR link in the job summary for a maintainer to open. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Regenerated with the corrected fetch. Net change vs the previously published file: +6,630 meters the old broken pagination missed, -35,768 retired meters no longer returned by the API (the old preserve-forever cache had hoarded them), and 166 corrected flags. 121,301 -> 92,163 rows. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR aims to make the weekly “Update Commitment Discount Eligibility” automation reliable again by fixing Azure Retail Prices API pagination handling in Update-CommitmentDiscountEligibility.ps1 and updating the GitHub Actions workflow to push an update branch + provide a manual PR creation link (since Actions cannot open PRs in this org).
Changes:
- Reworks the Retail Prices API fetch to follow
NextPageLinkverbatim, shard queries byserviceFamily, and repeat/union results until stable; adds a completeness guard to prevent overwriting open data with incomplete results. - Updates the workflow to push a uniquely named branch and write a “Create pull request” compare-link to the job summary instead of calling
gh pr create. - Regenerates the open-data dataset (per PR description).
Reviewed changes
Copilot reviewed 2 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
src/scripts/Update-CommitmentDiscountEligibility.ps1 |
Implements sharded/repeated API traversal with convergence + completeness guards and writes a fresh (non-cached) dataset. |
.github/workflows/opendata-commitment-eligibility.yml |
Removes PR-creation permissions/step; pushes a branch and surfaces a PR link in the job summary. |
src/open-data/CommitmentDiscountEligibility.csv |
Regenerated eligibility data output (not shown in diff snippet, but described in PR). |
On network/DNS/timeout errors Invoke-RestMethod's exception has no .Response, so reading .Headers['Retry-After'] indexed $null and threw "Cannot index into a null array" inside the catch -- bypassing retry/backoff and aborting the run. Guard against a null .Response; treat it as a retryable "Network error". Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Thanks @copilot-pull-request-reviewer. Addressed: Retry/backoff null
$r = @{ Keys = @{ a=1; b=2; c=3 }; NonConverged = @('x') }
$r.Keys.GetType().Name # Hashtable
$r.Keys.Count # 3 (not 2)
$r.Keys.ContainsKey('a') # TrueThis also matches the end-to-end runs: |
Summary
The weekly Update Commitment Discount Eligibility workflow has been failing on every run. This fixes two independent root causes and regenerates the open-data file.
1. The fetch was broken and non-reproducible
Update-CommitmentDiscountEligibility.ps1paged the Azure Retail Prices API with an undocumented multi-field$orderbyand an explicit$top:$orderbywith HTTP 400 (fails on page 1 — the recent ~30s failures).NextPageLinkwhile sending$topis also broken: the API'sNextPageLinkdecrements$topper page into negatives (1000 → 0 → -1000), returning HTTP 400.NextPageLink/$skippagination has no stable total order across page requests — a single long traversal silently drops a scattered ~2–24% of rows, so two identical runs disagreed (~76% Jaccard).Fix: follow
NextPageLinkverbatim (no$orderby, no$top), shard each query byserviceFamilyso traversals stay short, and repeat each shard unioning bymeterIduntil the set is stable. A full run is now reproducible (two runs byte-identical) and more complete (captures meters the old walk dropped). Added a completeness guard (-MaxShrinkFraction, default 0.15) that aborts before writing if a run is materially incomplete, and switched to writing the freshly-fetched set so retired meters age out instead of accumulating forever.2. The workflow tried to open a PR, which Actions can't do here
gh pr createfailed every run (Actions aren't permitted to open PRs in this org — confirmed via run history: theCreate PRstep failed while the fetch succeeded). The workflow now pushes a dated branch and surfaces a one-click "create PR" link in the job summary for a maintainer to open (which then triggers Open Data CI and normal review).Data change
Regenerated
CommitmentDiscountEligibility.csv: 121,301 → 92,163 rowsTest plan
MeterId, correct columns🤖 Generated with Claude Code