Skip to content

ci(rescue): move every nightly.yml sign, verify and DMG job off a stalled Blacksmith macOS label - #26534

Merged
teamleaderleo merged 1 commit into
mainfrom
ci/rescue-nightly-signer-jobs
Oct 28, 2026
Merged

teamleaderleo merged 1 commit into
mainfrom
ci/rescue-nightly-signer-jobs

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 28, 2026 •

Copy link
Copy Markdown
Collaborator

sr2's order: "Rescue gap on nightly-next: ci-owned-pool-rescue's include_blacksmith_macos covers cmux-next.yml only, so a nightly.yml job stalled on a Blacksmith macOS label is never moved. Today run 40585960129 had signer-verify queued on blacksmith-6vcpu-macos-26 for 3 h+, and 40610802228's sign job has been queued since 01:16Z. Please extend include_blacksmith_macos (or the equivalent) to nightly.yml's sign, verify and dmg-image jobs. That's the queue bound for the Linux signing path, since GitHub has no queue timeout."

Leo, 2026-10-27: "a waiting nightly, promote or nightly sign/verify job is admitted on a mini ahead of every PR, DEV and side job"; the routing order ends at Blacksmith macOS ("IT WAS ALWAYS FUCKING LAST RESORT"), and no job waits on one reserved machine.

Problem

For nightly.yml, the code that does what include_blacksmith_macos does for cmux-next.yml is the signing-stall rescue (NIGHTLY_SIGN_ALTERNATES, signing_stall()). It had three gaps:

  1. signer-dmg-image and signer-verify were not in the table. In run 40585960129 (attempt 2), signer-verify sat queued on blacksmith-6vcpu-macos-26 from 00:34 to 01:52Z. Because it was not in the table it counted as unfinished work, so the run's stalled Verify final nightly DMG (arm64) was not moved either.
  2. Main's classic nightly was not covered at all. Only nightly-next was. Main's runs-on uses its own alternate-label expression (pick-classic-sign-runner, which also checks the attempt that made the pick).
  3. No test tied the table to nightly.yml. A job added or renamed in nightly.yml silently dropped out of the rescue.

The coordinator added a fourth item for this file, a blocking finding on #26494: main's prepare-nightly-variant legs will be pinned to the trusted mini right after the build. Main's push nightlies run in parallel, so a newer push's build can take that mini first. The rescue never moved a job waiting on a reserved runner, so the legs would sit behind a full build with no fallback.

Change (scripts/ci/owned_pool_rescue.py, scripts/ci/owned_pool_sources.py)

  • NIGHTLY_SIGN_ALTERNATES gains signer-dmg-image and signer-verify. Each entry now takes a tuple of alternate-label expressions, so main's classic expression counts too.
  • Target.signs_late: main's nightly attempt 1 gets the same signing-stall watch as nightly-next. Main's later attempts are unchanged, because a full re-run there builds the app again.
  • A job pinned to a nightly's reserved runner that is not the app build (reserved_follower()) now waits at most RESERVED_FOLLOWER_SECONDS (5 min). After that it moves like a stuck job: the run is cancelled, then its failed jobs are re-run, and the re-run takes the Blacksmith fallback. The build's own wait stays untimed. A started job is still never cancelled: if any job of the run is running, the follower keeps waiting.
  • pull_moved(): a main nightly whose app build succeeded (app_built()) is no longer treated as moot when main moves on. It used to be cancelled without a re-run, which threw away the build. Now its failed jobs are re-run. A newer run pending behind it in a shared group still wins, as before.
  • Cancelling a started nightly still goes only through the rescue's existing path: signing_stall() acts only when every other job of the run has finished, and started_nightly_work() / nightly_cancel() re-check right before the cancel.

Test: derived from nightly.yml, not hard-coded

tests/test_ci_owned_pool_sources.py::test_every_nightly_sign_verify_and_dmg_job_on_blacksmith_macos_is_rescued reads main's rescue table (AST, sign_table()) and checks it against both branches' nightly.yml (the working tree plus origin/feat-cmux-next, fetched under Actions as the file already does). It finds every job whose id matches sign, verify or dmg and whose runs-on can name a Blacksmith macOS label (a literal or vars.MACOS_RUNNER_26; the CI_CLOUD_OVERFLOW_SAVED outage literal is ignored). It fails when such a job is missing from the table, or when its runs-on has none of the table's alternate-label expressions. Mutation check: removing signer-dmg-image from the table fails the test for origin/feat-cmux-next. The test already runs in ci-guards ("Validate that the persistent-pool rescue watches every owned-pool workflow"), so it is blocking on main.

#26491 (merged) removed signer-verify from feat-cmux-next. The derived list follows that change automatically; the table entry stays for runs still in flight.

Proof (replay of run 40585960129's real jobs at 01:44Z, head efc7808's nightly.yml)

  • main: watch | Verify final nightly DMG (arm64) queued on blacksmith-6vcpu-macos-26 ... but signer-verify not finished; cancelling the run would lose that work, so it is not rescued on this look
  • this branch: stalled | Verify final nightly DMG (arm64), signer-verify queued on blacksmith-6vcpu-macos-26 with no runner past the 600s Blacksmith stall time, and every other job of the run has finished

Tests

  • tests/test_ci_owned_pool_rescue.py: 335 pass. New cases: signer jobs are rescued; main's attempt 1 with the classic alternate is rescued; main moving on no longer drops a built run; a pinned follower moves at 5 min while the build never does; a follower never moves while a leg is running.
  • tests/test_ci_owned_pool_sources.py: 11 pass, against the live origin/feat-cmux-next.

Deploy: the rescue checks out main, and a running sweeper hands over within CODE_CHECK_TICKS once main's copy changes, so merging deploys it.

Risk: medium. A main nightly whose sign or verify jobs stall now gets cancelled-then-re-run once nothing else in it runs. A main nightly's pinned follower moves to Blacksmith after 5 min.

Agent session: agent session

🤖 Generated with Claude Code


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need.


Summary by cubic

Extends the nightly signing-stall rescue so every sign, verify, and DMG job in nightly.yml can be moved off a stalled Blacksmith macOS label, and covers main's classic nightly for the first time.

  • NIGHTLY_SIGN_ALTERNATES gains signer-dmg-image and signer-verify; each entry now holds several alternate-label expressions, including main's classic one.
  • Main's nightly attempt 1 gets the same signing-stall watch that nightly-next had.
  • A job pinned to a nightly's reserved runner other than the app build waits at most 5 minutes before it moves like a stuck job (run cancelled, failed jobs re-run). The build's own wait stays untimed, and a started job is never cancelled.
  • A main nightly whose app build succeeded is no longer dropped when main moves on: its failed jobs are re-run instead. A newer run pending behind it in a shared group still wins.
  • A new test derives the covered jobs from both branches' nightly.yml, so a job added or renamed there fails until the rescue covers it.

Written for commit df59e0d. Summary will update on new commits.

View guided diff Turn on auto-fix

Summary by CodeRabbit

  • Bug Fixes
    • Nightly build monitoring now continues to watch queued app builds while identifying reserved-runner jobs that remain stuck for more than five minutes.
    • Signing-stall detection now covers additional signing, verification, and disk image jobs across both nightly branches, including supported alternate runner labels.
    • Nightly runs can continue checking later attempts, and a successful app build is no longer treated as a reason to skip further monitoring.

…lled Blacksmith macOS label

The signing-stall rescue's table missed nightly-next's signer-dmg-image and
signer-verify, so run 40585960129's signer-verify sat on
blacksmith-6vcpu-macos-26 for 78 minutes and, counted as unfinished work, kept
the run's stalled final-DMG verify where it was too. Main's classic nightly
was not covered at all.

- NIGHTLY_SIGN_ALTERNATES gains signer-dmg-image and signer-verify, and takes
  several alternate-label expressions per job (main's classic one checks the
  pick's own attempt). Main's nightly attempt 1 gets the same signing watch.
- A job pinned to a nightly's reserved runner other than the app build (main's
  prepare-nightly-variant legs, #26494) waits RESERVED_FOLLOWER_SECONDS (5 min)
  at most, then moves like a stuck job; the build's own wait stays untimed.
- A main nightly whose app build succeeded is not made moot by main moving on
  (pull_moved()): its failed jobs are re-run instead of the run being left
  cancelled. A newer run pending behind it still wins.
- owned_pool_sources.uncovered_sign_jobs(): tests/test_ci_owned_pool_sources.py
  derives the sign, verify and DMG jobs that can sit on a Blacksmith macOS
  label from both branches' nightly.yml and fails when main's rescue cannot
  move one.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?id=aid-85ca59f74f02d81734c3
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by an agent session · session

@github-actions

Copy link
Copy Markdown
Contributor

All contributors have signed the CLA ✍️ ✅
Posted by the CLA Assistant Lite bot.

@coderabbitai

coderabbitai Bot commented Oct 28, 2026

Copy link
Copy Markdown

Review in Change Stack →

No actionable comments were generated in the recent review.

Recent review info
Run configuration
Commits

Reviewing files that changed from the base of the PR and between 41d7a68 and df59e0d.

Files selected for processing: 4
  • scripts/ci/owned_pool_rescue.py
  • scripts/ci/owned_pool_sources.py
  • tests/test_ci_owned_pool_rescue.py
  • tests/test_ci_owned_pool_sources.py

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 5 remain after this review.

Walkthrough

Nightly rescue handling now distinguishes the reserved app-build job from other jobs pinned to its runner. Signing-stall checks cover qualifying nightly runs on both branches. Source checks detect signing jobs in nightly workflows and compare them with the rescue table.

Changes: Nightly rescue

Layer / File(s) Summary
Reserved-runner follower handling
scripts/ci/owned_pool_rescue.py, tests/test_ci_owned_pool_rescue.py
The reserved build remains untimed. Other jobs pinned to its runner become stuck after five minutes in the queue. Main nightly runs with a successful app build are not treated as moot solely because main moved. Tests cover follower rescue, build watching, and main nightly reruns.
Cross-branch signing-stall rescue
scripts/ci/owned_pool_rescue.py, scripts/ci/owned_pool_sources.py, tests/test_ci_owned_pool_rescue.py, tests/test_ci_owned_pool_sources.py
Signing-stall checks now apply to qualifying nightly runs on both branches and accept any configured alternate-label expression. Source checks detect signing, verification, and DMG jobs and report missing rescue-table coverage. Tests cover alternate routes and source detection.

Priority: Normal

Estimated code review effort: 3 (Moderate) | ~25 minutes

Change: Bug fix

Sequence Diagram(s)

sequenceDiagram
  participant NightlyWorkflow
  participant RescueWatch
  participant NIGHTLY_SIGN_ALTERNATES
  participant SigningJobs
  NightlyWorkflow->>RescueWatch: Starts a qualifying nightly watch
  RescueWatch->>NIGHTLY_SIGN_ALTERNATES: Checks configured alternate label expressions
  RescueWatch->>SigningJobs: Retries stalled jobs with alternate labels
Loading

Possibly related issues

  • manaflow-ai/cmux#25921 — The PR adds a nightly workflow-to-rescue-table coverage test for signing, verification, and DMG jobs.
  • manaflow-ai/cmux#26038 — The PR keeps the nightly app build untimed while adding a timeout for reserved-runner followers.
  • manaflow-ai/cmux#26172 — The PR changes reserved-runner rescue behavior and preserves the app build as the untimed exception.
  • manaflow-ai/cmux#26190 — The PR changes reserved-runner rescue behavior and preserves the app build as the untimed exception.
  • manaflow-ai/cmux#13807 — The PR detects nightly signing jobs and checks that the rescue table covers them.

Suggested reviewers: lawrencecchen, austinywang

Merge Risk: Minimal · up to df59e

The supplied evidence identifies no issue that prevents merging after normal checks.

Pre-merge checks: Passed 24 · Failed 1

Failed Failed checks: 1 warning

Check name Status Explanation Resolution
Docstring Coverage Warning Docstring coverage is 70.59% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documenta… Write docstrings for the functions missing them to satisfy the coverage threshold.
Passed Passed checks: 24 passed
Check name Status Explanation
Title check Passed The title clearly and concisely identifies the primary change: moving nightly sign, verify, and DMG jobs off stalled Blacksmith macOS labels.
Description check Passed The description clearly explains the problem, behavior changes, implementation, tests, proof, deployment, and risk. It omits the template's Changelog and Checklist sections, but the remaining content …
Linked Issues check Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check Passed Check skipped because no linked issues were found for this pull request.
Cmux Cloud Persistent Session And Early Input Passed PASS: The pull request changes only nightly CI rescue logic and its tests in four files. The diff introduces no Cloud terminal creation, cmux-tui transport, manual renderer, Ghostty runtime, input rou…
Cmux Swift Actor Isolation Passed PASS: The pull request changes only Python CI scripts and Python tests. The authoritative diff contains no Swift, Objective-C, or Objective-C++ files, so it introduces no Swift actor-isolation change.
Cmux Swift Blocking Runtime Passed PASS: The pull request changes only Python CI scripts and Python tests. It introduces no production Swift changes, so the Swift blocking-runtime check is not applicable.
Cmux Browser Automation Off-Main Passed PASS: The pull request changes only CI Python scripts and their Python tests. It does not change Sources/TerminalController.swift, ControlCommandExecutionPolicy.swift, or any Swift browser automat…
Cmux Expensive Synchronous Load Passed PASS: The pull request changes only Python CI scripts and Python tests. It adds no production Swift code and does not add or move any synchronous agent-history load onto a main-actor or interactive pa…
Cmux Cache Substitution Correctness Passed PASS: The pull request changes only Python files under scripts/ci and tests. It introduces no production Swift, TypeScript, or JavaScript change, so the cache-substitution correctness check does not a…
Cmux No Hacky Sleeps Passed PASS. The diff adds no sleep, timer, delayed dispatch, or new polling loop. RESERVED_FOLLOWER_SECONDS is an explicit queue-rescue timeout in the existing assess() state machine. It triggers cancel…
Cmux Algorithmic Complexity Passed No algorithmic-complexity violation is introduced. The new scans operate on bounded GitHub Actions workflow data, not user-owned records: nightly variants are explicitly limited to one or three values…
Cmux Swift Concurrency Passed The pull request changes only Python CI scripts and Python tests. The reviewed diff contains no Swift files, so it introduces no cmux-owned Swift concurrency pattern covered by the check.
Cmux Swift @Concurrent Passed The pull request changes only Python CI scripts and Python tests. The reviewed diff contains no Swift files or Swift declarations, so the @concurrent rule is not applicable.
Cmux Swift Package Boundaries Passed The pull request changes only four Python files under scripts/ci and tests/. The authoritative diff contains no Swift files or Swift package targets, so the Swift package-boundaries rule is not applic…
Cmux Swiftpm Lockfiles Passed PASS: The pull request changes only Python rescue logic and Python tests (scripts/ci/*.py and tests/*.py). It does not change a SwiftPM package, Xcode project, .gitignore, workflow, dependency d…
Cmux Swift Logging Passed The pull request changes only Python CI scripts and Python tests. It changes no Swift, Objective-C, or runtime application files, and adds no prohibited logging calls or diagnostics. The Swift logging…
Cmux User-Facing Error Privacy Passed PASS. The diff changes only CI rescue logic, CI source inspection, and tests. The production path is .github/workflows/ci-owned-pool-rescue.yml running python3 scripts/ci/owned_pool_rescue.py; its…
Cmux Full Internationalization Passed The PR changes only CI rescue scripts and their tests: scripts/ci/owned_pool_rescue.py, scripts/ci/owned_pool_sources.py, and two test files. It adds operational Python logic, comments, and test m…
Cmux Swiftui State Layout Passed PASS: The pull request changes only four Python files: scripts/ci/owned_pool_rescue.py, scripts/ci/owned_pool_sources.py, and two Python test files. No Swift or SwiftUI code changed, so the SwiftUI st…
Cmux Architecture Rethink Passed PASS: The pull request changes only Python CI scripts and Python tests. It adds no Swift files or Swift architecture changes, so the Swift architectural rethink failure conditions do not apply.
Cmux Swift Auxiliary Window Close Shortcuts Passed PASS: The pull request changes only Python CI scripts and Python tests. The authoritative diff contains no Swift changes and no standalone cmux-owned window code, so the auxiliary-window close-shortcu…
Cmux Source Artifacts Passed The pull request changes only two hand-written CI source files and two test files. The diff adds rescue logic, source inspection helpers, and focused test fixtures. No logs, screenshots, recordings, t…
Cmux No Test Or Debug Seam In Production Source Passed The pull request changes only Python files under scripts/ci and tests. It changes no Swift file under a production Sources/ path, so the specified production-source test/debug seam condition does not …
Full details: Description check

Explanation

The description clearly explains the problem, behavior changes, implementation, tests, proof, deployment, and risk. It omits the template's Changelog and Checklist sections, but the remaining content is sufficiently complete for this CI-only change.

Full details: Cmux Cloud Persistent Session And Early Input

Explanation

PASS: The pull request changes only nightly CI rescue logic and its tests in four files. The diff introduces no Cloud terminal creation, cmux-tui transport, manual renderer, Ghostty runtime, input routing, snapshot, authentication, revision, or lease behavior covered by the rule.

Full details: Cmux Browser Automation Off-Main

Explanation

PASS: The pull request changes only CI Python scripts and their Python tests. It does not change Sources/TerminalController.swift, ControlCommandExecutionPolicy.swift, or any Swift browser automation routing. The diff contains no browser.*, WebKit, AppKit, socket-worker, or main-actor automation changes.

Full details: Cmux Expensive Synchronous Load

Explanation

PASS: The pull request changes only Python CI scripts and Python tests. It adds no production Swift code and does not add or move any synchronous agent-history load onto a main-actor or interactive path.

Full details: Cmux Cache Substitution Correctness

Explanation

PASS: The pull request changes only Python files under scripts/ci and tests. It introduces no production Swift, TypeScript, or JavaScript change, so the cache-substitution correctness check does not apply.

Full details: Cmux No Hacky Sleeps

Explanation

PASS. The diff adds no sleep, timer, delayed dispatch, or new polling loop. RESERVED_FOLLOWER_SECONDS is an explicit queue-rescue timeout in the existing assess() state machine. It triggers cancellation and rerun only for queued reserved-runner followers, while started jobs and the app build remain protected. Tests cover the threshold and these exceptions.

Full details: Cmux Algorithmic Complexity

Explanation

No algorithmic-complexity violation is introduced. The new scans operate on bounded GitHub Actions workflow data, not user-owned records: nightly variants are explicitly limited to one or three values, and the rescue table has ten static entries. app_built() is a single pass over jobs. The small nested checks in assess() and uncovered_sign_jobs() compare bounded workflow/job collections. The new source-inspection helpers are used only by tests in this repository and are not hot UI, socket, search, or persistence paths.

Full details: Cmux Swift Package Boundaries

Explanation

The pull request changes only four Python files under scripts/ci and tests/. The authoritative diff contains no Swift files or Swift package targets, so the Swift package-boundaries rule is not applicable.

Full details: Cmux Swiftpm Lockfiles

Explanation

PASS: The pull request changes only Python rescue logic and Python tests (scripts/ci/*.py and tests/*.py). It does not change a SwiftPM package, Xcode project, .gitignore, workflow, dependency declaration, or Package.resolved file. The SwiftPM lockfile policy is therefore not applicable.

Full details: Cmux Swift Logging

Explanation

The pull request changes only Python CI scripts and Python tests. It changes no Swift, Objective-C, or runtime application files, and adds no prohibited logging calls or diagnostics. The Swift logging check therefore has no applicable failure.

Full details: Cmux User-Facing Error Privacy

Explanation

PASS. The diff changes only CI rescue logic, CI source inspection, and tests. The production path is .github/workflows/ci-owned-pool-rescue.yml running python3 scripts/ci/owned_pool_rescue.py; its output is an operator CI log and step summary, not a cmux product UI, CLI, or API response. The added diagnostics name CI jobs, Blacksmith runners, labels, and workflow expressions, which the rule explicitly allows for internal CI and operator diagnostics. No changed text exposes secrets, credentials, tokens, private data, raw upstream errors, or unredacted payloads.

Full details: Cmux Full Internationalization

Explanation

The PR changes only CI rescue scripts and their tests: scripts/ci/owned_pool_rescue.py, scripts/ci/owned_pool_sources.py, and two test files. It adds operational Python logic, comments, and test messages. It does not change Swift text, string catalogs, Info.plist files, web UI, locale data, API responses, rendered markdown, or changelogs.

Full details: Cmux Swiftui State Layout

Explanation

PASS: The pull request changes only four Python files: scripts/ci/owned_pool_rescue.py, scripts/ci/owned_pool_sources.py, and two Python test files. No Swift or SwiftUI code changed, so the SwiftUI state and layout failure conditions do not apply.

Full details: Cmux Swift Auxiliary Window Close Shortcuts

Explanation

PASS: The pull request changes only Python CI scripts and Python tests. The authoritative diff contains no Swift changes and no standalone cmux-owned window code, so the auxiliary-window close-shortcut rule does not apply.

Full details: Cmux Source Artifacts

Explanation

The pull request changes only two hand-written CI source files and two test files. The diff adds rescue logic, source inspection helpers, and focused test fixtures. No logs, screenshots, recordings, temporary folders, caches, dependency checkouts, build output, or broad artifact directories appear in the changed-path inventory.

Full details: Cmux No Test Or Debug Seam In Production Source

Explanation

The pull request changes only Python files under scripts/ci and tests. It changes no Swift file under a production Sources/ path, so the specified production-source test/debug seam condition does not apply.

Full details: Docstring Coverage

Explanation

Docstring coverage is 70.59% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff with cyclomatic complexity of at least 2. Documentation-only edits and deletions within surviving functions are included; unchanged diff context and fully deleted functions are excluded. Analyzed 17 functions across 4 files.

Resolution

Write docstrings for the functions missing them to satisfy the coverage threshold.

Finishing Touches: 💡 1
📝 Generate docstrings: 💡
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@teamleaderleo
teamleaderleo merged commit 5fe2505 into main Oct 28, 2026
55 checks passed
@teamleaderleo
teamleaderleo deleted the ci/rescue-nightly-signer-jobs branch October 28, 2026 02:50
@github-actions

Copy link
Copy Markdown
Contributor

cmux status (one comment, edited in place; each line is updated by the job that owns it)

Merge receipt for df59e0de72: every check was green at merge (10 verified; 16 skipped by policy). Full suite runs on main after merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant