ci(nightly-next): canary the signed app before and after publication
Merged
TE
19d ago+547+547+012345678901234567890123456789-7-7-0123456789
Stacked on #21887 (the rollback). Review only the second commit.
Leo dogfoods cmux NEXT through its nightly auto-update, so the nightly needs a check that goes past "the process stays up". This adds a canary that launches the exact signed app on a CI Mac, never on a person's Mac, and checks:
- It opens a visible window.
cmux tab new-pageadds a tab tosnapshot.get.- The app's own acpmux starts a session of acpmux's test agent (
fake_agent.py), and the agent answers a prompt. No account or network is needed. - The app is still up 60 s after launch, with no
cmux*oracpmux*crash report.
Reuse, not a new harness:
- It is
scripts/smoke-signed-app-cli.sh <app> --canary, an extension of the signed-app CLI smoke the nightly already runs. That smoke supplies the private socket launch,app ping/identify, and the cleanup. - The checks in
scripts/cmux-next/signed-app-canary-checks.pyreuse the readiness soak's control and acpmux clients and its fake-agent recipe. - Release builds serve no
debug.*methods, so the checks use onlysnapshot.get, the bundled CLI and acpmux RPC. There's no pixel capture: "renders" means the app's model has the New Tab.
Two places it runs:
- Before publication,
verify-signed-nightlyruns it on the app it then publishes. That covers the Mac writer. - After publication,
nightly-next-canary.ymldownloads the DMG the feed names. It checks the length, the notary tickets, Gatekeeper and the build number, then runs the canary from the build's own commit (CMUXCommit).- It covers the Linux writer and recovered builds too.
- A build fails only after two failed attempts, and each build gets one verdict (a cache key per build).
- The schedule runs only from main, so a main PR adds this file there. Here, the
pull_requesttrigger runs it on the newest feed build with this PR's harness, and that run never pulls anything.
Switch: repository variable NIGHTLY_NEXT_CANARY. Unset means report-only.
| Value | Effect |
|---|---|
unset / report | Both canaries run. A failure is an annotation plus one nightly-next canary failed issue. The build still publishes and stays on the feed. |
enforce | A pre-publication failure fails verify-signed-nightly, so nothing is published. A post-publication failure dispatches nightly-next-rollback.yml -f bad_build=<build>. |
off | Skips both. |
Turning it on is one line: gh variable set NIGHTLY_NEXT_CANARY -R manaflow-ai/cmux --body enforce.
Testing:
bash -nand shellcheck are clean onsmoke-signed-app-cli.sh. actionlint is clean onnightly.ymland the new workflow.- These pass:
tests/test_ci_signing_keychain_is_deleted_before_bundle_code.py,test_ci_production_secrets_protected_env.py,test_nightly_next_recovery.py,test_nightly_trusted_routing.py. - Live run on the current feed build 3917159104301, from this PR's harness (run 39195075343): window
win_80c1…is visible, a New Tab appears (kindconversation), a fake-agent session starts and answersend_turn, and the app stays up 60 s with no crash report. The first run (39194420604) failed on a wrongsnapshot.getkey. That run is how the bug was caught, and 5cad150 fixes it. - In this run the New Tab's id is
pending_tab_…, so the check proves the app created the tab, not that it painted it. - Not run: the pre-publication step inside a real nightly. That happens on the first nightly-next run after this merges, in report mode.
Changelog
none
🤖 Generated with Claude Code