Repository navigation
perf(pr-merge): carry completed run attempts across post-merge-dispatch ticks - #10834
Conversation
…ch ticks Every post-merge check re-read the earlier attempts of each re-run full run in its window (8 attempt reads per tick on the 2026-10-28 runs). A completed attempt never changes, so the check now answers one from a file pr-merge.yml's post-merge-dispatch carries in its kept report, for the same run, attempt and head SHA, and writes back the completed attempts it used. Any unusable file is no file, and every attempt is read as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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. critical-findings: 0 I read the whole diff,
manifest fields: none touched. |
|
claude-review reviewed No findings. I read the full diff and PR context. I also read
Minor, not counted: Spend: The change removes GITHUB_TOKEN API calls and adds no spend. It changes no permissions or billing, and I returned no hold. |
Post-merge mutation testingKilled 0, survived 0, timeout 0, no coverage 0, invalid 0, not run 7.
The run's summary has the full report. |
No related issue: an API-budget cut found in the 2026-10-28 GITHUB_TOKEN breaker trips on pr-merge's post-merge-dispatch job; no issue tracks it.
Hold paths: this changes
babysit_postmerge.pyand.github/workflows/pr-merge.yml, both hold paths, so the owner approves the merge. No permission, secret or token change.Summary
The post-merge check in pr-merge's
post-merge-dispatchjob re-read the earlier attempts of every re-run full run in its window on each 15-minute tick: 8GET .../actions/runs/{id}/attempts/{n}calls per tick on all five full checks measured on 2026-10-28. A completed attempt cannot change, so the check now carries those attempts from one tick to the next in the report artifact the job already keeps.Calls per run: 50-57 → about 42-49, measured from each job's
babysit-gh-callsline. That is 8 × 4 ticks/h ≈ 32 of the job's ≈ 200 GITHUB_TOKEN calls/h (≈ 16%). A run that is newly re-run still costs its one read, on the first tick that sees it.Fix
babysit_postmerge.py:_Context._attempttakes an attempt from the file named inBABYSIT_POSTMERGE_ATTEMPTSwhen the entry has the same run id, attempt number and head SHA as the listed run. Otherwise it reads the attempt as before.save_attemptswrites back only the completed attempts this check used.mergejob's check behaves as before.pr-merge.yml,post-merge-dispatchonly: the check step copiesattempts.jsonfrom the last run's kept report (last-report.mjsdownloads it only from a trusted pr-merge run on main, the same boundary as the lane records) to the path it names. It keeps the file in the report whether the check runs or an idle tick reuses the report.Not done, and why. The brief proposed indexing
dispatch_runs_atby head SHA in one dated listing. That finding did not reproduce:repos/{}/{}/commitscall, sodispatch_runs_through, the per-SHA loop, never ran. The six runs are 40783844800, 40786123150, 40787501102, 40789255688, 40790836092 and 40795766929.Three other cuts were rejected because each would change what the check decides:
--branch mainremoves the report'ssharedblock, so the output changes._lane_rerunsopens a race for a run created between the two reads.failing_checksjobs and annotations is unsafe: the jobs API can list a completed job's steps short, so a cached answer can differ from a later live read.Verification
tests/test_babysit_postmerge_attempts.py(new) is a pin. The source of truth is the check with no attempts file, which is the code before this change.report()identical to it, in 2 fewer attempt reads (2 → 0).3401 passed, 4523 subtests passed.node --test .github/scripts/pr-merge/merge-job.test.mjs: 82 pass, with a new test that the step hands the file to the check and keeps it on both the check path and the reuse path.scripts/run-ruff.sh checkandformat --checkare clean.pr-require-checks.ymlon main atrun_attempt2 sit in the check's window, which starts at 2026-10-27T16:01Z. The newest finished at 2026-10-28T22:37Z, before the first measured tick (22:57Z), so the same attempts recur and each tick after the first reads none of them.Related
settle --idle-tick, from perf(pr-merge): reuse the last tick's post-merge report on an idle tick #10475) did not fire on any measured tick: run 40795766929 logged{"reuse": false, "reason": "post-merge answer stale"}. The reuse window is shorter than the 15-minute cadence, and lengthening it is an owner decision about how fresh the post-merge answer must be. Not changed here..github/actions/log-api-budget/**.🤖 Generated with Claude Code