Skip to content

ci: skip compile admission when an earlier run compiled the same build inputs - #13139

Merged
teamleaderleo merged 7 commits into
mainfrom
ci-skip-unchanged-compiles
Sep 20, 2026
Merged

teamleaderleo merged 7 commits into
mainfrom
ci-skip-unchanged-compiles

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Sep 20, 2026 •

Copy link
Copy Markdown
Collaborator

Stacked on #13117 (it needs that pull request's full_suite switch). Replaces #13128.

Summary

  • Under the compile-only pull request policy from 13117, compile admission is the only Mac job a push pays for. This skips it when the push changed nothing the Xcode build reads: a guard test, another workflow, docs, or a merge of main that only moved web.
  • scripts/ci/build_input_fingerprint.py hashes the git tree entries (mode, object id, path) of every path that can reach the build, plus the selected Xcode. It starts from the router's own macOS classification and additionally ignores tests/, tests_v2/, .github/ other than ci.yml, and Markdown. Unknown paths count as inputs.
  • Every pull request run publishes that fingerprint as an artifact name (build-inputs-<hash>, a few bytes, 7 days). scripts/ci/find_admitted_build.py checks the last six CI runs of the same branch for that artifact together with a successful macOS compile admission job.
  • Trust: only runs whose head repository is this repository count, since a fork's run can rewrite its workflow and report anything. Any API error means compile. The tests gate accepts a skipped admission only when the run is compile-only and the lookup said yes.
  • Full-suite runs always compile, because the shards need this revision's product. Merge groups are full-suite, so what lands is always compiled.
  • Nothing changes until CI_PULL_REQUEST_SUITE=compile-only is set.

Why this and not 13128

13128 keeps the compiler's CAS on the runner's disk. Every macOS runner here exists for one job (two consecutive admissions tonight ran on warp-6x-arm64-w6xi4lr7… and …wv2ennr1…), so the next run never sees that disk. Saving the CAS per pull request instead would push the main seed out of the cache budget with multi-GB snapshots, for little gain: Swift recompiles a whole module when any file in it changes.

Expected effect

Sample of 44 recent pull requests with 687 later commits: 15% of later commits touched no build input, and another 18% were merges of main, some of which qualify too. Each hit saves one 16 to 21 minute Mac job; on the paid runners that is the whole per-push Mac cost under the compile-only policy.

Testing

  • tests/test_ci_change_areas.py on Python 3.9 and 3.12: PASS. New tests run the real tests gate for every combination (skipped admission passes only when compile-only and admitted; a failed admission never passes; full-suite never reuses a verdict), check the fingerprint ignores exactly the non-inputs and reacts to each input class and to the Xcode pin, and check the lookup against a fake API: current run excluded, different inputs, failed or skipped admission, fork run, API failure.
  • The lookup script was run against the live API (no match, exit 0). actionlint clean; runner and permission guards pass.
  • Not yet exercised end to end, because the compile-only policy is off.

Issues

🤖 Generated with Claude Code


Summary by cubic

Skips macOS compile admission when an earlier run of the same branch already compiled identical build inputs, so pushes that touch only tests, docs, other workflows, or web-only merges of main no longer pay for a 16–21 minute Mac compile. Nothing changes until CI_PULL_REQUEST_SUITE=compile-only is set.

How it works

  • Each PR run attempt publishes a build-inputs-<fingerprint>-<attempt> artifact; the fingerprint covers every git tree path the Xcode build reads plus the selected Xcode pin.
  • A compile-only run skips admission when one of the last six branch runs has the matching artifact and a successful macOS compile admission job in that artifact's attempt; the tests gate accepts that skip only when the admission result is skipped.
  • Only runs whose head repository is this repository count, since a fork can rewrite its workflow; any API error falls back to compiling.
  • The fingerprint, publish, and lookup steps continue on error, so a broken optimization compiles instead of failing routing.
  • Full-suite runs always compile, because the shards need this revision's product.

Related to #13095.

Written for commit 6a81a25. Summary will update on new commits.

Review in cubic

teamleaderleo and others added 4 commits September 19, 2026 20:56
…ps at the first failure

A new changes output, full_suite, decides whether a run gets the whole macOS
suite (app-host shards, package tests, the lag build, the Release build) or
only compile admission. Merge groups and dispatches always get the suite.
Pull requests get it too unless the repository variable
CI_PULL_REQUEST_SUITE is "compile-only"; under that policy the full-ci label
opts one pull request back in. Nothing changes until the variable is set, and
it should be set together with enabling the merge queue, which then runs the
suite on the commit that will land.

The tests gate accepts a skipped suite only when full_suite is explicitly
false, so a missing output cannot relax it.

On merge groups the shard matrix fails fast, and a small job with
actions: write and no checkout cancels the run at the first failed job.
ci-status runs on cancellation and reports it, so the queue drops the entry
without waiting for the remaining macOS jobs.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The watcher holds actions: write. As a job in ci.yml it ran on merge_group
from the queue's merge commit, so a queued pull request could edit the code
holding that token. It is now its own workflow triggered by workflow_run,
which always runs the default branch's copy, and ci.yml grants no write
permission at all.

It also stops when the CI run completes instead of inferring that from the
job list, counts startup failures, and gives up visibly after ten
consecutive Actions API errors instead of polling until its timeout.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…d inputs

Under the compile-only pull request policy, a push that changes nothing the
Xcode build reads (a guard test, another workflow, docs, a merge of main that
only moved web) still paid for a full compile. Each pull request run now
publishes a fingerprint of its build inputs as an artifact name: the git tree
entries of every path that can reach the build, plus the selected Xcode. A
compile-only run whose fingerprint an earlier run of the same in-org branch
already compiled successfully skips compile admission, and the tests gate
accepts that skip only in that case.

Runs with the full suite always compile, because the shards need this
revision's product, so merge groups are unaffected. Fork runs are never
trusted as the earlier run, and any API error means compile.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 20, 2026 •

Copy link
Copy Markdown

Warning

Review limit reached

Next included review available in 14 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Learn how review limits work.

Review configuration:

⚙️ Run configuration

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

Review profile: ASSERTIVE

Plan: Advanced

Run ID: ee169568-0e69-4845-9dd6-9b8f3b7c5241

📥 Commits

Reviewing files that changed from the base of the PR and between bd65a8a and 6a81a25.

📒 Files selected for processing (4)
  • .github/workflows/ci.yml
  • scripts/ci/build_input_fingerprint.py
  • scripts/ci/find_admitted_build.py
  • tests/test_ci_change_areas.py

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.

@greptile-apps

greptile-apps Bot commented Sep 20, 2026 •

Copy link
Copy Markdown
Contributor

RetriggerConfidence Score: 5/5

The PR appears safe to merge, with the previous findings addressed and no new blocking issue identified.

Summary

Adds reuse of successful macOS compile admission for compile-only pull requests with identical build inputs, while retaining compilation for full-suite runs.

  • Fingerprints tracked build inputs and the selected Xcode configuration.
  • Matches fingerprint artifacts to successful admission jobs from the same run attempt.
  • Makes reuse steps best-effort and URL-encodes branch queries.
  • Adds regression coverage for attempt isolation, fallback behavior, and artifact naming.
  • No new actionable findings were identified.

Diagram

%%{init: {'theme': 'neutral'}}%%
flowchart TD
  A[Route CI suite] --> B{Full suite?}
  B -->|Yes| C[Compile admission]
  B -->|No| D[Fingerprint build inputs]
  D --> E{Trusted earlier run has matching receipt and successful admission in the same attempt?}
  E -->|Yes| F[Skip compile admission]
  E -->|No or lookup failure| C
  C --> G[Tests gate checks required results]
  F --> G
Loading

Reviews (3) · Last reviewed commit: "ci: bind compile admission evidence to o..."

Comment thread scripts/ci/find_admitted_build.py Outdated
Comment thread .github/workflows/ci.yml
Comment thread scripts/ci/find_admitted_build.py Outdated
The two-tier change landed on main as a squash. Keeps this branch's
compile_admitted output, fingerprint steps and gate tests on top of it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

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

teamleaderleo and others added 2 commits September 20, 2026 02:51
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The fingerprint artifact name now carries the run attempt, and the lookup
accepts a passed admission job only with the artifact from its own attempt.
Query parameters are URL-encoded, and the fingerprint, publish, and lookup
steps continue on error so a broken optimization compiles instead of
failing routing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@teamleaderleo
teamleaderleo enabled auto-merge (squash) September 20, 2026 10:03
@teamleaderleo
teamleaderleo merged commit a348064 into main Sep 20, 2026
43 of 44 checks passed
rustybret pushed a commit to rustybret/bmux that referenced this pull request Sep 20, 2026
4b18fc9 ci: track package test helper inputs (manaflow-ai#13188)
b210493 Merge pull request manaflow-ai#13181 from manaflow-ai/ci-focused-app-host-tests
ced163c Merge pull request manaflow-ai#13180 from manaflow-ai/ci/remote-tmux-crash-diagnostics
9faf726 Merge pull request manaflow-ai#13178 from manaflow-ai/ci-reject-incomplete-test-runs
14c3ca1 Merge pull request manaflow-ai#13166 from manaflow-ai/ci-reuse-build-for-runtime-regressions
7c3574a ci: let the pre-merge Release check compile arm64 only (manaflow-ai#13195)
887839a ci: drop a stalled GhosttyKit download and resume it (manaflow-ai#13197)
70a244d Merge pull request manaflow-ai#13177 from manaflow-ai/ci-fast-static-preflight
fcad43f build: read Xcode projects with Foundation and drop XcodeProj and PathKit (manaflow-ai#13111)
76d80b1 ci: skip Release and its helper for test-only pull requests (manaflow-ai#13122)
fdc63e9 Merge pull request manaflow-ai#13176 from manaflow-ai/ci-reuse-queue-build-products
3162fee test: split an expression Xcode 27 cannot type-check (manaflow-ai#13126)
d10aa64 test: use consistent XCTest imports to stop compiler diagnostic flood (manaflow-ai#13163)
1b69bf9 test: stop real-Git reftable tests depending on a 2s wall clock (manaflow-ai#13186)
cad333b Merge origin/main into ci-fast-static-preflight
7522486 Merge origin/main into ci-reuse-build-for-runtime-regressions
43210e1 Bound automatic terminal titles before session persistence (manaflow-ai#13009)
674a0db ci: retire Depot macOS runners (manaflow-ai#13162)
f48ef36 Merge pull request manaflow-ai#13183 from manaflow-ai/ci-early-cli-smoke
ebbb17f ci: skip app-host teardown when setup never started (manaflow-ai#13179)
5fb6d8c Merge pull request manaflow-ai#13168 from manaflow-ai/ci-cache-r2-store
a348064 ci: skip compile admission when an earlier run compiled the same build inputs (manaflow-ai#13139)
88e102c reload: let a reused checkout keep one warm DerivedData across tags (manaflow-ai#13131)
7a049e9 Merge origin/main into ci-reuse-build-for-runtime-regressions
cd05c6e Merge origin/main into ci-fast-static-preflight
5cf41fa Merge origin/main into ci-reuse-queue-build-products
5a6322e test: guard early CLI smoke ordering
0438552 fix: pass R2 public URL through workflow environment
0716c59 test: bound app-host replay subprocesses
2e0b9b5 ci: terminate cancelled focused discovery
14bbad4 ci: keep R2 public URL configuration inside the cache actions
e342c67 ci: make focused run discovery cancellable
cf3984b test: avoid hard timeout in app-host classifier replay
251b050 ci: allow privileged crash report collection
7d9a7f2 Merge main after landing cache backend and suite policy
b6853ee ci: allow manual cache-only seeding for R2 rollout
81d3026 test: require manual cache seeding to skip app publication
6980f8e ci: harden remote tmux diagnostics collection
c24d77f ci: publish R2 cache pointers conditionally and repair failed writes
2432805 test: cover R2 pointer repair and out-of-order saves
4779d01 ci: continue past unusable build artifact candidates
9dd1579 test: reproduce corrupt candidate blocking product reuse
bfb43f5 ci: check CLI version and help before app-host fan-out
f2b0fae docs: use an existing suite in focused launcher example
2c04b6a ci: drain tar streams portably with BSD tar
c5e1d59 ci: pin focused tests to a commit and track the requested run
1a44bde ci: consume tar padding when restoring zstd caches
31d4fd9 test: cover padded R2 archives on macOS
a46567a ci: isolate R2 cache writes from release credentials
ce26a8e test: require early CLI smoke gate to propagate probe failures
18a67fb test: reproduce focused launcher revision and run attribution bugs
4dd543e test: require cache-only R2 credentials for cache saves
2c8412c ci: make product reuse attempt-safe and bound archive expansion
59fb526 ci: preserve remote tmux mirror crash diagnostics
d8107e4 test: cover artifact reruns, expansion limits and producer source checks
28a03e3 ci: reject interrupted app-host runs despite later passing summaries
302551d test: reproduce false-green app-host timeout and restart runs
bc3a63a ci: reject invalid static inputs before expensive validation
baf65d9 test: require successful static preflight before macOS admission
6cea5f0 ci: fall back when build identity cannot be established
7632c7e ci: reuse compatible compiled products in merge groups
8be0c54 ci: add an R2 bucket as a cache store every runner can read
25f50c3 test: behaviour of an R2-backed cache store script
17c2498 ci: reuse compiled app and UI products for runtime regressions
6ed96f4 test: require UI products in the shared CI build artifact
230ad52 ci: drop a timeout note about a DerivedData cache that no longer exists
b5ec5cc ci: stop restoring DerivedData in pull request jobs
a42ad38 Merge remote-tracking branch 'origin/main' into ci-cache-backend-switch
477fb0f ci: choose the cache store per dispatched run, and cover the nightly app build
03363d7 ci: let a repository variable move the seeded caches to the Warp store
f791f87 ci: pull request jobs restore caches and never save them
5b65bb1 test: pull request jobs must restore caches read-only
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