Skip to content

ci: stop admitting macOS after a run has already failed - #13969

Merged
teamleaderleo merged 1 commit into
mainfrom
ci/macos-admission-skips-red-runs
Sep 23, 2026
Merged

teamleaderleo merged 1 commit into
mainfrom
ci/macos-admission-skips-red-runs

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 23, 2026 •

Copy link
Copy Markdown
Collaborator

A pull request that trips a fast Linux guard is red about a minute in. Its
macOS compile admission is queued anyway and starts on a Mac half an hour
later, compiling a revision nobody will look at. In one 2.3-hour window,
25 of the 27 failing CI runs that reached macOS admission were already red
when the debounce checkpoint finished
, and 416 of their 656 macOS
job-minutes went to shards that had not started yet.

After this change those shards are never queued. The lane is untouched on
green pull requests, and blacksmith-6vcpu-macos-15 is a shared pool, so the
reclaimed capacity comes back as shorter macOS waits for everyone else — one
sampled run sat 33 minutes between its debounce finishing and its compile
starting.

Mechanism

macos-debounce already waits on a cheap Linux runner, re-reads the pull
request head, and fails the run rather than admitting macOS when the head
moved. It now fails the same way when a job in this run has concluded
failure.

Declining by failing is load-bearing rather than incidental. A job output
would read better — the debounce job would stay green and the run would carry
one red job instead of two — but macos is skipped either way, and only a
failed dependency makes "Re-run failed jobs" re-run it. An output would
strand that run red until someone re-ran everything, which is worse than the
cosmetic cost. This was caught in review; the first revision of this PR had
exactly that bug.

macos needs no new condition and tests needs no change: a failed
macos-debounce already skips the lane through the existing
result == 'success' || result == 'skipped' clause.

Tradeoffs

A red run no longer reports whether macOS would also have failed, so a pull
request broken on both platforms needs a second round trip. Re-run attempts
and CI_MACOS_ADMISSION_DEBOUNCE_SECONDS=0 skip the wait and with it this
check — which is how you ask for those results anyway.

macOS admission gains no dependency edge on the Linux suites, which
test_ci_change_areas.py forbids, but it now depends on their results in
substance, and racily: whether a run collects macOS results depends on whether
a Linux guard fails before or after the debounce window closes. Flagging that
rather than letting the guard imply otherwise.

If vars.CI_PERSISTENT_MAC_COMPILE is ever set to pilot or all, a
persistent Mac compile is dispatched at T≈0, before this checkpoint; a decline
would then leave its product built and unconsumed. docs/ci/workflow-inventory.md
records that the pilot has never run, so this is latent, not live.

Validation

  • python3 tests/test_ci_change_areas.py passes, including three new tests.
  • The new run_macos_debounce helper drives the real step script from
    ci.yml against a fake gh that serves a JSON payload and then runs the
    step's own --jq program over it with real jq. A pre-digested answer would
    have let a wrong accessor pass; this does not.
  • Mutation-tested, 5 of 5 killed: breaking the .jobs[] accessor, counting
    cancelled as a failure, removing the check entirely, dropping
    actions: read, and moving the check ahead of the debounce wait.
  • Verified fail-open on every unreadable path: broken gh, empty jobs, an
    error body, and a cancelled-only run all admit; a moved head still fails
    first.
  • actionlint .github/workflows/ci.yml clean.
  • Full ci-guards.yml sweep: three failures, all environmental and unrelated
    (catalog-diff needs workflow-set variables, test_ghostty_zig_version_sync.sh
    needs the ghostty submodule, lint-stored-dispatch-work-items.py needs
    vendor/bonsplit).

Not established here: the reclaimed minutes are measured over one 2.3-hour
window on 2026-09-23, not a daily average, and the queue-wait improvement is a
single observation rather than a distribution.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Chores
    • Updated automated macOS checks to skip runs when an earlier check has failed or a newer change has superseded the run.
    • Checks still proceed when the run status cannot be confirmed, and failed runs can be retried.

@coderabbitai

coderabbitai Bot commented Sep 23, 2026 •

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository: manaflow-ai/cmux/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 5bf0d6f9-b931-45ab-a9d2-24f3b6035dd2

📥 Commits

Reviewing files that changed from the base of the PR and between 46402d2 and 93eccb7.

📒 Files selected for processing (2)
  • .github/workflows/ci.yml
  • tests/test_ci_change_areas.py

Included review availability: Your plan provides up to 10 included reviews per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

The macOS debounce job now checks for failed jobs after its wait and declines admission when it finds one. Tests cover failure, fail-open conditions, and a moved pull-request head.

Changes

macOS CI admission

Layer / File(s) Summary
Debounce admission check
.github/workflows/ci.yml, tests/test_ci_change_areas.py
The debounce job requires actions: read and checks the current run's jobs after the wait. It declines when a job has a failure conclusion, while cancelled jobs and unreadable or error responses do not trigger that check. Tests cover these cases, re-runs, a zero debounce window, and a moved pull-request head.

Priority: ⬇️ Low

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Other

Merge Risk: ⚪ Minimal · up to 93ecc

Failed runs decline macOS admission while still producing a failed CI result. No issue identified here needs resolution before merge.

🚥 Pre-merge checks | ✅ 24 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 1 files. (1 skipped: 1… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (24 passed)
Check name Status Explanation
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 .github/workflows/ci.yml and tests/test_ci_change_areas.py. The changes implement macOS CI admission checks and tests. They do not modify Cloud terminal creatio…
Cmux Swift Actor Isolation ✅ Passed PASS: The pull request changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. The diff contains no Swift source or Swift interface changes, so it does not introduce or worsen Swi…
Cmux Swift Blocking Runtime ✅ Passed PASS: The authoritative pull-request diff changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. It introduces CI shell commands and Python test scaffolding, but no production Sw…
Cmux Browser Automation Off-Main ✅ Passed The PR changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. The rule applies to browser socket automation in Sources/TerminalController.swift and `ControlCommandExecutionPoli…
Cmux Expensive Synchronous Load ✅ Passed PASS: The authoritative PR diff changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. It adds no production Swift code or agent-history load call sites, so the expensive synchro…
Cmux Cache Substitution Correctness ✅ Passed PASS: The authoritative PR diff changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. It introduces no production Swift, TypeScript, or JavaScript changes, so the cache-substitu…
Cmux No Hacky Sleeps ✅ Passed PASS. The only runtime wait is the existing sleep "$DEBOUNCE_SECONDS" in .github/workflows/ci.yml; the PR does not add or expand it. The rule explicitly excludes GitHub Actions workflow YAML, and …
Cmux Algorithmic Complexity ✅ Passed The production change adds one jq scan over the jobs page at .github/workflows/ci.yml:912-914. It filters and counts failures in one linear pass, with no nested scan, per-target rescan, sorting, o…
Cmux Swift Concurrency ✅ Passed The pull request changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. The diff contains no cmux-owned Swift code, so it introduces no legacy Swift concurrency pattern covered b…
Cmux Swift @Concurrent ✅ Passed The pull request changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py; it introduces no Swift source, Swift declarations, or Swift call sites. The `swift-concurrent-annotation.m…
Cmux Swift Package Boundaries ✅ Passed PASS: The authoritative diff changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. It contains no production Swift changes, so the Swift package-boundary rule does not apply.
Cmux Swiftpm Lockfiles ✅ Passed PASS. The PR changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. The diff contains no Package.swift, Package.resolved, .gitignore, Xcode project package-reference, or Sw…
Cmux Swift Logging ✅ Passed PASS: The pull request changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py; it adds no Swift or Objective-C files. The added echo statements are CI shell diagnostics, and the…
Cmux User-Facing Error Privacy ✅ Passed PASS. The diff changes only .github/workflows/ci.yml and CI tests. The new messages and gh api handling run in the internal GitHub Actions macos-debounce job and appear in CI/operator logs, not …
Cmux Full Internationalization ✅ Passed PASS: The PR changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. The added text is CI control logic, comments, and operational job output; the tests and fixtures are explicitl…
Cmux Swiftui State Layout ✅ Passed PASS: The authoritative PR diff changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. It adds GitHub Actions shell logic and Python tests, with no Swift or SwiftUI files or Swif…
Cmux Architecture Rethink ✅ Passed PASS: The PR changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py; it introduces no Swift files or Swift architecture changes. The added debounce sleep and GitHub Actions job po…
Cmux Swift Auxiliary Window Close Shortcuts ✅ Passed The pull request changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. The authoritative diff contains no Swift, window, or window-controller changes, so the auxiliary-window cl…
Cmux Source Artifacts ✅ Passed The PR changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. These are intentional workflow configuration and hand-written test source, including test fixtures. No generated out…
Cmux No Test Or Debug Seam In Production Source ✅ Passed PASS: The authoritative pull-request diff changes only .github/workflows/ci.yml and tests/test_ci_change_areas.py. It contains no Swift file under a production Sources/ path, so this check is no…
Title check ✅ Passed The title clearly and concisely describes the main CI behavior change: macOS admission stops after a run has already failed.
Description check ✅ Passed The description explains the problem, mechanism, tradeoffs, testing, and known limitations. It does not reproduce the template headings, review-trigger block, or checklist, but it provides the require…
Full details: Docstring Coverage

Explanation

Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 6 functions across 1 files. (1 skipped: 1 unsupported.)

  • Fix all pre-merge checks with AI
✨ 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

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.

@github-actions

Copy link
Copy Markdown
Contributor

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

A pull request that trips a fast Linux guard is red about a minute in, but
its macOS compile admission is queued anyway and starts on a Mac half an
hour later. Over 40 failing CI runs in one 2.3-hour window, 25 of the 27
that reached macOS admission were already red when the debounce checkpoint
finished, and 416 of their 656 macOS job-minutes went to shards that had
not started yet.

The debounce job already waits on a cheap Linux runner, re-reads the pull
request head, and fails the run rather than admitting macOS when the head
moved. It now fails the same way when a job in this run has concluded
`failure`: the verdict is settled on this head, and the fix push opens a
new run.

Declining by failing is load-bearing rather than incidental. A job output
would read better -- the debounce job would stay green and the run would
carry one red job instead of two -- but `macos` is skipped either way, and
only a *failed* dependency makes "Re-run failed jobs" re-run it. An output
would strand that run red until someone re-ran everything.

Tradeoffs: a red run no longer reports whether macOS would also have
failed, so a pull request broken on both platforms needs a second round
trip. Re-run attempts and CI_MACOS_ADMISSION_DEBOUNCE_SECONDS=0 skip the
wait and with it this check, which is how you ask for those results anyway.
Every unreadable case admits -- a failed call, an empty reply, an error
body, or a first page that misses a later job.

macOS admission gains no dependency edge on the Linux suites, which
`test_ci_change_areas.py` forbids, but it does now depend on their results
in substance, and racily: whether a run collects macOS results depends on
whether a Linux guard fails before or after the debounce window closes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo force-pushed the ci/macos-admission-skips-red-runs branch from ffe5c53 to 93eccb7 Compare September 23, 2026 11:23
@cursor

cursor Bot commented Sep 23, 2026

Copy link
Copy Markdown

Bugbot is paused — on-demand spend limit reached

Bugbot uses usage-based billing for this team and has hit its on-demand spend limit.

A team admin can raise the spend limit in the Cursor dashboard, or wait for the next billing cycle to continue.

@teamleaderleo teamleaderleo left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review before merge. I took this over from NightPetrel.

  • The verdict can't flip. Every job in ci.yml is in ci-status's needs, and ci-status accepts only success or skipped. No job in ci.yml or its reusable workflows has job-level continue-on-error. So once the jobs API reports a failure, the run is already red. Declining macOS changes what it costs, not whether it passes.
  • Declining by failing is correct. An output would leave macos skipped under a successful dependency, and "Re-run failed jobs" would never pick it up. The comment in the step says so. Keep it.
  • It admits when in doubt. If the step can't read the jobs, gets an error body, sees only cancelled jobs, or is on a re-run attempt, it admits, and the table-driven test covers each of those cases.
  • Tested on the merged tree. Merged onto the current origin/main: python3 tests/test_ci_change_areas.py passes on the merged tree. The four macos_admission tests also pass on the PR head.

— KeyboardCat g1 ⚙️
Run: run_cmux_ci_efficiency_land_13969_and_13990_20260923_c1f522ea

@teamleaderleo
teamleaderleo enabled auto-merge (squash) September 23, 2026 14:59
@teamleaderleo
teamleaderleo merged commit 9963f3f into main Sep 23, 2026
44 of 45 checks passed
rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 23, 2026
9963f3f ci: stop admitting macOS after a run has already failed (manaflow-ai#13969)
c7fb3b1 ci: put the switch for paid macOS capacity in the repository (manaflow-ai#13973)
0044d5a ci: mirror app-host batch output without racing a tail (manaflow-ai#13990)
a0b1dea fix(ci): unquote replayed argv so post-manaflow-ai#13831 selectors resolve (manaflow-ai#13974)
c14b142 test: target local Undo at the editable responder (manaflow-ai#13989)
5985cf5 Mirror terminal focus before the runtime surface exists (manaflow-ai#13968)
afd5c47 ci: let E2E dispatches adopt a compiled product instead of rebuilding (manaflow-ai#13958)

# Conflicts:
#	.github/workflows/ci-guards.yml
#	.github/workflows/ci-macos-compat.yml
#	.github/workflows/ci-macos.yml
#	.github/workflows/ci.yml
#	.github/workflows/cli-pipe-regressions.yml
#	.github/workflows/cloud-command-deadlines.yml
#	.github/workflows/cloud-machine-tests.yml
#	.github/workflows/cmux-tui-build-package.yml
#	.github/workflows/iroh-release-gate.yml
#	.github/workflows/nightly.yml
#	.github/workflows/perf-activation.yml
#	.github/workflows/plain-paste-worker.yml
#	.github/workflows/relay-tls.yml
#	.github/workflows/release.yml
#	.github/workflows/terminal-hang-diagnostics.yml
#	.github/workflows/test-e2e.yml
#	.github/workflows/tmux-corpus.yml
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