ci(nightly-next): the app build takes the dedicated builder first, then owned, then Blacksmith
Leo, 2026-10-27: "but what if we just dedicatd one, only, always, and it just incrementally... did the thing? clear its stuff, etc". And: "i meant skipping compiles broke main". An incremental build is a real compile; this PR adds no comparison builds.
This is the first of two PRs. It routes the NEXT app build to the one dedicated builder. The second PR makes that builder build incrementally on its warm DerivedData.
Why nothing ran on the dedicated builder
On 2026-10-24, #24987 removed the dedicated-runner tuple ([TRUSTED_POOL, TRUSTED_RUNNER, glaeda-trusted-next-nightly]) from build-nightly-app. On 2026-10-25, the builder moved to a new mini when the M6 minis were reserved, and CI_NIGHTLY_NEXT_TRUSTED_RUNNER was pointed at it. Because of #24987, no job asked for glaeda-trusted-next-nightly any more. The runner has been online ever since and has never run a job.
Change
pick-nightly-build-runner(scripts/ci/nightly_build_runner.py) now tries the dedicated builder first, while its runner is online and idle.- The label comes from
vars.CI_NIGHTLY_NEXT_DEDICATED_LABEL. Leaving it unset switches this off, and the only label it accepts ispr_runner_pool.NIGHTLY_DEDICATED_LABEL(glaeda-trusted-next-nightly). - While the builder is busy, the picker waits up to 5 minutes for it (the build of the previous tip, or a verify), reading the runners every 30 s.
- If the builder is offline, can't be read, is still busy after the wait, or this is a re-run, the build goes to the idle owned pool and then Blacksmith, exactly as #26017 left it.
- The label comes from
ownedcarries the dedicated label when it is picked, sobuild-nightly-app's runs-on is unchanged.owned_pool_rescue.job_pool()now recognizes the label, here and on main (#26110, merged), sinceci-owned-pool-rescue.ymlruns main's copy. Two runs can both see the builder idle. When that happens, the second one's queued build is moved after the rescue budget (CI_OWNED_POOL_RESCUE_SECONDS, 30 s; nightly.yml gets no queue-round allowance) to attempt 2, which runs on Blacksmith. A refusal at job start is moved the same way.- After the wait, the Blacksmith pick reads queue ages at the current time, not the job's start.
- The step budgets grow to fit the wait: the pick step goes from 2 to 8 min and the job from 6 to 12 min. The coverage registry entry is renamed with the step.
Not changed:
- The keyless verify jobs stay on their owned or Blacksmith pick. They check out into the runner's one shared workspace with a depth-1
actions/checkout. On the builder that would make its warm clone shallow, clear the kept cargo targets, and move the tree back to an older build SHA, which defeats the incremental build. - Signing, notarization and publication stay on Blacksmith in the release environment. No keys go to the mini.
Numbers (baseline, for the follow-up)
Commit-to-published time for nightly-next runs created since 2026-10-26 18:00Z, measured from the head commit's time to publish-nightly succeeding. 7 of 29 runs published. Times in minutes: 84.8, 95.2, 96.8, 157.7, 160.6, 177.4, 202.7. p50 157.7 min.
Tests
tests/test_nightly_build_runner.py: 22 OK. New tests cover:- an idle builder is taken at once, and a busy one is waited on with the wait capped at 5 min;
- offline, unread, off, a wrong label or a retry is skipped with no wait;
- the dedicated builder comes first, falling back to owned and then Blacksmith;
- the
dedicatedmode (used by verifies) never waits; - the rescue watches the label;
- the step and job budgets fit the wait.
- Also OK on this branch, run one file at a time:
test_nightly_trusted_routing.py(18),test_ci_runs_on_fallback.py(8),test_ci_nightly_off_blacksmith.py(11),test_ci_owned_pool_rescue.py(138),test_ci_side_lane_placement.py(58),test_nightly_step_coverage.py(5).
Risk: low until CI_NIGHTLY_NEXT_DEDICATED_LABEL is set. Once it is set, the app build runs on the dedicated builder whenever it is free. Any other state falls back to the routes as they are today.
Agent session: agent session
š¤ Generated with Claude Code
![View with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/view-with-codesmith-dark-v3-3x.png)
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Need help on this PR? Tag @codesmith-bot with what you need.