ci(nightly): shorten the release-pool signing chain (about 18 to 15 min to publish)
Summary
Leo, 2026-11-03: "the signing/publishing don't require 30 cores". The NEXT nightly's release-pool signing chain is mostly waiting, not work. In run 41570134320 it took 18.2 min from the end of build-nightly-app (03:25:28) to publish-nightly's end (03:43:38). The step times show where the waiting is:
signer-buildneededpick-nightly-sign-runner, so its hosted pickup and cache restore (43 s) sat between the pick andsigner-app. Nothing in it reads the pick's outputs since #30081 put it back on the signer route. It now needs onlydecideand builds while the app does.signer-appspent 37 s on a full checkout of the build tree, though it reads onlyscripts/and the top-level entitlements. It now checks out sparse (sparse-checkout: scripts; cone mode keeps the root files).- Apple's clock started only once
signer-apphad uploaded its artifact andsigner-app-notaryhad been picked up, checked out, and had downloaded and unpacked the app (≈50 s after signing).signer-appnow starts the upload to Apple itself (release-signer/submit-app.sh start) right after packing. It runs in the background beside the artifact uploads, andsubmit-app.sh finishhands the submission id on as an output.signer-app-notaryis gone. signer-dmgdownloaded the whole 355 MB signed app (50 s) only to read its Info.plist for the appcast.signer-appnow hands that Info.plist on as its own small artifact, with its digest as an output, andsigner-dmgchecks it against the digest.launch-smoke-nightlyread the unsigned DMG in one download-artifact stream (205 s). Withsigner-dmgshorter, that would have put it on publish's path. It now reads in parallel ranges first (fetch_run_artifact.py), assigner-dmg-imageand the final-DMG verify already do, with download-artifact as the fallback.
The DMG image step stays on a Mac (hdiutil). Verify DMG and the launch smoke already run side by side (#32378).
What stays
- Both notarizations, in order. The Mac still staples the app's ticket before it builds the DMG (
signer-staple-app.shpolls Apple for the ticket, which exists only for an accepted submission).signer-dmgadds an explicit Accepted check,release-signer/wait-app-notary.sh, before it signs the DMG:notary-wait, then the notary log'sstatusmust beAccepted. The DMG's own sign, notarize and staple is unchanged. - The Computer Use helper's notarization (
sign-app.sh, helper-first) is untouched. - The cmux NIGHTLY-identity (legacy) chain.
legacy-signer-*jobs are unchanged. They still needsigner-build, which now finishes earlier, so the change can only bring them forward. notary_submit(#33028).submit-app.shsubmits through it, so a 429 rate limit is still waited out and retried.- The overtaken gate (#33109).
signer-appstill needspick-nightly-sign-runnerwithovertaken != 'true'. - Keys still live only in a per-job
mktemp -d(umask 077) that the script's EXIT trap removes. The background upload owns its own key directory and removes it when the upload ends. No secret, environment or permission changes. Runners are unchanged: GitHub-hosted Ubuntu first, Blacksmith 4 vCPU on a re-run, sotests/test_ci_self_hosted_guard.shneeds no new allowlist line. - If Apple rejects the app, the staple still fails at its deadline and
signer-dmgnever signs, as before.signer-dmg's wait now fails on any answer other than Accepted.
nightly.yml goes from 487,267 to 489,623 bytes (cap 490,000).
Performance
Before: run 41570134320's job and step times. After: projected from those same step times; the first NEXT nightly after merge gives the measured number (follow-up comment).
| metric | before | after (projected) | delta | harness or run link |
|---|---|---|---|---|
| end of build-nightly-app → publish-nightly done | 18.2 min | ≈15.3 min | ≈−2.9 min | run 41570134320 job/step times |
| pick done → signer-app start (signer-build hop) | 79 s | ≈36 s | −43 s | same |
| signer-app build checkout | 37 s | ≈5 s (sparse, as the tools checkout) | −32 s | same |
| app signed → Apple submission starts | ≈50 s | ≈2 s | −48 s | same |
| signer-dmg-image end | 03:34:41 | ≈03:32:40 | ≈−2.0 min | same |
| signer-dmg signed-app download | 50 s | ≈2 s (Info.plist only) | −48 s | same |
| launch-smoke unsigned-DMG download | 205 s | ranged read (signer-dmg-image's took 64 s on the same mini for 355 MB) | off publish's path | same |
| signer jobs per run | 5 | 4 | −1 hosted job | — |
Testing
Run locally with system python3, all passing:
tests/test_nightly_signer_jobs.py(updated:signer-app-notarygone; submit and wait order; Info.plist digest;signer-buildneeds onlydecide; launch smoke's ranged read)tests/test_release_signer_*.py(newAppNotarizationTests: background submit hands on the id; failed upload or missing id failsfinish; wait passes only Accepted; key never on argv or in the signer's env; key dirs removed)tests/test_nightly_sign_runner.py,tests/test_nightly_step_coverage.py,tests/test_workflow_file_size.py,tests/test_ci_signing_keychain_is_deleted_before_bundle_code.py,tests/test_ci_nightly_off_blacksmith.py,tests/test_supplychain_security.py,tests/test_ci_self_hosted_guard.sh, plustests/test_nightly_trusted_routing.py,tests/test_fetch_run_artifact.pyand the other tests that read the signer jobs.tests/test_nightly_universal_build.shfails ("nightly preparation must run on Blacksmith Linux…") identically on baseorigin/feat-cmux-next; it is not from this change.
Observed / Not run
- Observed: the step timings above (run 41570134320 via the jobs API), and Apple's ≈35 s upload and 113 s processing in its
signer-app-notarylog. - Not run: a real nightly with these jobs. Only
nightly-nextwith the release environment can sign and notarize. The first nightly after merge is the end-to-end check. If the pool path fails,build-sign-notarize-nightly(the macOS signer) still signs that build, as today.
Changelog
none
risk: high (release signing, CI)
🤖 Generated with Claude Code
Agent session: agent session
![Autofix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/autofix-with-codesmith-dark-3x.png)
Open in [code]smith · Need help on this PR? Tag @codesmith-bot with what you need.
Summary by cubic
Shortens the release-pool signing chain in the nightly workflow, cutting the time from the end of build-nightly-app to publish from about 18 minutes to about 15 minutes.
signer-buildnow needs onlydecide;signer-appchecks out the build tree sparse and starts Apple's notarization upload in the background, so thesigner-app-notaryjob is gone.signer-dmgwaits for Apple'sAcceptedanswer before signing the DMG and reads only the app's Info.plist for the appcast.launch-smoke-nightlydownloads the unsigned DMG in parallel ranges first.
Both notarizations stay in order: the Mac still staples the app's ticket before the DMG, and signer-dmg checks the Accepted answer before signing. The legacy NIGHTLY-identity chain, the Computer Use helper notarization, notary_submit retries, and the overtaken gate are unchanged.
Risk: high (release signing, CI).