Repository navigation
ci(nightly-next): an older build hands its sign slot to a newer build whose sign job is queued - #35752
Conversation
… whose sign job is queued GitHub gives a free runner the oldest queued job on its label, so the newest nightly-next tip's sign job waited about 20 minutes per slot behind older builds that latest-wins publication replaced within minutes (2026-11-04, runs 41866781601 to 41873130397). A new step right after the signing claim, before any secret, reads whether a newer nightly-next push run already has its own sign job queued, running or signed; if so this job yields (exit 1, yielded=true) and report-nightly-failure skips it. The newest sign job never yields, so the newest finished build always signs. Nothing is cancelled. Narrows #33109's "only a published newer build counts": a newer push alone still never counts; a newer run whose sign job exists does. Tests: tests/test_nightly_sign_yield.py (9) and test_nightly_step_coverage pass; the wiring tests fail on 4d20a29. The other nightly.yml-related test files fail the same tests here as on base. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-90f71867d2222e9eecd0
|
Owned by an agent session · session |
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Shipped in:
|
|
Found 1 test failure on Blacksmith runners: Failure
|
|
Review (goal-nightly-30min, independent of the author): BLOCK at bf25b77
The logic checks out:
Non-blocking notes:
Agent session: agent session |
…y page goal-nightly-30min's BLOCK at bf25b77: tests/test-execution.toml registered tests/test_nightly_sign_yield.py as linux-guard, which no workflow runs, so the registry validator failed. It is manual now with a reason (no new CI tests). Their non-blocking note: a status-filtered run list's total_count can run ahead of its items, so the yield read pages until an empty one, as signing_runner.every_page does; more than MAX_PAGES pages signs as before. Tests: test_nightly_sign_yield, test_nightly_step_coverage, validate_test_execution_registry.py and test_ci_test_execution_registry pass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-90f71867d2222e9eecd0
|
Review (goal-nightly-30min, independent Claude Opus 5.5): SHIP at a35ac85 The BLOCK is fixed: Agent session: agent session |
|
Review (codex, router-review): SHIP at a35ac85 Reviewer: codex gpt-6.1-sol xhigh, fast tier. Follow-ups: 1. They land as checklist items in this PR's one follow-up tracking issue in this repo ( SHIP at a35ac85 Visual verdict: unchanged by this diff
Focused yield, wiring, and nightly routing tests pass. Follow-ups:
|
|
Reds at a35ac85, read from every check suite over GraphQL:
Reviews at this head: SHIP from Codex gpt-6.1-sol and from an independent Claude review. Codex's P2 follow-up F1 (read newer runs in waiting, pending and requested status too) is filed as cmuxterm-hq#7091. |
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
An older nightly-next build hands its sign slot to a newer build whose sign job is already queued, running or signed. Nothing is cancelled, and the newest finished build always signs.
What was wrong
GitHub gives a free runner the oldest queued job on its label, and a runner can't choose another. Publication is latest-wins. So on 2026-11-04 around 17:25Z, the three sign slots were held by the oldest nightly-next builds (runs 41866781601, 41867447845, 41868557041), and the newer builds'
build-sign-notarize-nightlyjobs waited behind them: 15, 19 and 24 minutes for the three that had started, with three more still queued (41869470224, 41870869803, 41873130397). Each older build then published a nightly that the next one replaced within minutes, and the newest tip reached the feed about an hour after its landing.The existing "Leave notarization to a newer published build" check (
sign-pick-overtaken.sh, #33109) runs inpick-nightly-sign-runner, before the sign job joins the queue. With oldest-first order it almost never fires.What this changes
Yield the sign slot to a newer build, runs inbuild-sign-notarize-nightlyright after the claim, before any secret or signing work. It isscripts/ci/nightly_sign_yield.py, run from the trusted signing controls.yielded=true, and the runner takes the next queued job (about a minute instead of a full sign and notarize).NIGHTLY_NEXT_SIGN_YIELD=0turns it off.report-nightly-failuredoes not report a yielded sign whose run had nothing else fail. This is the same pattern as its existing "replaced" build.The rule this narrows (#33109)
sign-pick-overtaken.shsays: "Only a published newer build counts, never a newer push alone: a newer run that then fails must not leave the feed with nothing (#28961)."Decided on cmuxterm-hq#7079. Ordering the slots newest-first was tried first. teamleaderleo/glaeda#1815 found that a runner can't choose which queued job it takes; glaeda can only refuse a job, which fails it.
Tests
tests/test_nightly_sign_yield.py(new, linux-guard):NIGHTLY_NEXT_SIGN_YIELD=0, a bad id): it signs without a read;yielded=falseand exits 0 when the API is unreachable;Red on base: the wiring tests fail on 4d20a29 (no such step or output); the decision tests have no script to load there. Green on this head.
python3 -m unittest tests/test_nightly_sign_yield.py tests/test_nightly_step_coverage.py: 14 OK on this head. Every other test file that reads nightly.yml (106) was run on the head and on 4d20a29: 69 pass on both, and the remaining 37 fail exactly the same tests on both (they need tools this checkout lacks, such as actionlint).Observed / Not run
signing: ...or theSign yieldnotice).Follow-up, not here: a superseded run's
sign-nightly-identity-legacyalso takes the exclusive class on its mini (35 min on run 41799796683); the same yield could apply to it.Changelog
none
Agent session: agent session
🤖 Generated with Claude Code
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
An older nightly-next build now hands its sign slot to a newer build whose sign job is queued, running, or signed, cutting the newest tip's feed delay from roughly 20 minutes per slot to about a minute.
GitHub gives a free runner the oldest queued job on its label, so the newest build's sign job waited behind older builds whose nightlies were replaced within minutes. A new step right after the signing claim, before any secret, checks the in-progress nightly-next runs; if a newer run's sign job already exists (GitHub creates it only once that run's build passes), this job exits 1 and the runner picks the next queued job. Nothing is cancelled, and
report-nightly-failureskips a yielded sign whose run had nothing else fail.total_countcan run ahead; more thanMAX_PAGESpages signs as before. The test is registered as manual, so the registry validator passes.Written for commit a35ac85. Summary will update on new commits.