Repository navigation
perf(ci): log api-budget from the demotion alert and dependabot-fragments jobs - #11172
Conversation
…ents jobs The demotion alert job's gh calls now run through api-budget.bash's wrapper under API_BUDGET_TOKEN=github-token, and the job ends with the log-api-budget step. dependabot-fragments' write job ends with the same step, as release-publish-plugins does. Refs: #9497 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
claude-security-review reviewed No security issues found in this pull request. What I read: all four changed files, the pull request context, the demotion alert workflow's checkout steps, and the
|
|
claude-review reviewed No findings. I read the full diff, the PR context and closing issue #9497, and the files the change depends on. I did not run any tests, so the PR's pass counts are author-claimed and unverified.
No cost hold applies. The change adds a job-end step and a |
Closes #9497
Summary
Issue #9497 asks every token-spending job in its workflow list to log an api-budget line, so
GITHUB_TOKEN spend can be attributed per job. Most of the list already logs, through #10141,
#10710 and the jobs added since. This PR covers the one real gap left: the demotion
alertjob,which sends about 20
gh apicalls (reads,--paginate, GraphQL, issue writes and dispatches)and logged nothing. It also adds the job-end step to
dependabot-fragments, matchingrelease-publish-plugins. The PR only measures: each job sends the same requests and writes thesame outputs.
Fix
.github/workflows/post-merge-demotion-alert.yml, jobalert:API_BUDGET_TOKEN: github-token. With it set,babysit_gh.pyrecords its readingsunder the judge (
babysit_postmerge.py --judge-run). Without it set, babysit_gh.py alreadyplans to
github-token's limits in Actions, so the limits it uses do not change.api_budget_wrap_gh github-tokenline, verbatim from pr-feedback-dispatch.yml.Log the API budget at the endstep. The step runsfrom the job's existing
.basecheckout of main..github/workflows/dependabot-fragments.yml, jobwrite: ends with the same step, run fromthe root checkout, as
release-publish-pluginsdoes (ci: log GITHUB_TOKEN api-calls from the jobs that logged none #10710). Itsghcalls use the releaseApp token, not GITHUB_TOKEN. They are left unwrapped so App spend is never booked under
github-token, and the line readsgithub-token=0.alertjob's gh calls now honor the job'srate-guard stop file (
$RUNNER_TEMP/api-budget/stop). A call the guard refuses fails throughthe step's existing error path; it is not sent. Before this PR it would have reached a pool
GitHub had already reported as exhausted.
and api-budget.bash. Node-step attribution through
API_BUDGET_SCRIPT(perf(pr-merge): attribute enable-auto-merge's API calls per step #11151) does not apply,because neither job has a Node step that calls GitHub through rate-guard.mjs.
Coverage of the issue's list
post-merge-demotion-alertalertdependabot-fragmentswritepr-verify:check-intent,check-intent-subscription,check-intent-fallbackpr-test-windows: all 9 jobsintake-triage:born-triaged,apply-verdict,refine-select,apply-refinementintake-reenterreenterwork-unblock:wip-state,label-unblockedpost-merge-demotion-alertreport-red-mainpost-merge-detect-silent-revertdetect-silent-revertrelease-publish-plugins:merge,buildpr-mergeenable-auto-mergeLeft out, and why
intake-triagekill-switchintake-triagerefine-issue,refine-issue-subscriptioncontents: read: checkout, download-artifact, model run). Model tokens are out of scope (issue decision 5).intake-triageintake-label-needs-triage,intake-triagemelodic-software/ci-workflows, where a caller cannot add a step.intake-triageredispatch-refinedcontents: readto count one known call. This follows #10710'smark-lanesrow.intake-triagetriage-split-childrenchildrenoutput), with no checkout, for the same reason.Known uncounted calls
failing-checks.mjs(demotionalert),.github/scripts/pr-merge/rotation.mjs:65-78(
gh run download) andlast-report.mjsrunghthroughexecFileSync. That runs the ghbinary, not the shell wrapper function, and these calls never reach
countRequests, so thereadings file never sees them. Counting them would need new Node code in rate-guard.mjs. That
file is perf(pr-merge): attribute enable-auto-merge's API calls per step #11151's and on the hold list, so these stay listed and are not patched here.
release-publish-pluginsanddependabot-fragmentsstay unattributed.The token names were settled as
github-tokenandlanes-app(issue decision 4).Metrics
alertjob log:::notice title=api-calls::github-token=N not-modified=M graphql=K, theapi-budgetcostnotice, and the content-creation line for its issue and comment writes. N covers the two shell
steps and the judge's
babysit_gh.pycalls; failing-checks.mjs is not included.dependabot-fragmentswrite:api-calls::github-token=0 .... The line confirms the jobspends no GITHUB_TOKEN REST budget.
Verification
node --test .github/actions/log-api-budget/*.test.mjs: 143 of 143 pass. The three new orextended tests failed before the workflow edits:
alertandreport-red-mainadded to the API_BUDGET_TOKEN table (alert names github-tokenfailed);
dependabot-fragmentswriteadded to the no-guarded-client table (failed);alertstep callinggh apiwraps gh first. To prove it canfail, the File step's wrap line was removed: the test failed with "File or comment on the
demotion issue wraps gh before its first call", then passed once the line was restored.
bash scripts/post-merge-demotion-alert.test.sh: 173 of 173 pass. Its shape check allowed onlythe checkout action in
alert, and it now also allows the.baselog-api-budget action fromthat checkout of main.
bash scripts/dependabot-fragments.test.sh: 8 of 8 pass..github/scripts/post-merge-demotion-alertsuites (58),label-unblocked.test.mjs(226) andcheck-trusted-trigger(370): all pass.actionlinton both workflows: clean.zizmor --offline: no findings.scripts/check-changelog-fragments.sh --check-required origin/main: no plugin changed, so nofragment is required.
Related
🤖 Generated with Claude Code