Skip to content

ci(cmux-next): DEV Release compile builds from one fixed tree and cache per host - #25147

Merged
teamleaderleo merged 4 commits into
feat-cmux-nextfrom
incremental-build-pr5-host-cache
Oct 26, 2026
Merged

teamleaderleo merged 4 commits into
feat-cmux-nextfrom
incremental-build-pr5-host-cache

Conversation

@teamleaderleo

@teamleaderleo teamleaderleo commented Oct 25, 2026 •

Copy link
Copy Markdown
Collaborator

"like how fast can we just have it, like hot and incrementally built?... reusing as much as you can" (Leo)

What

#24994 turned on Xcode's compilation cache (CAS) for the cmux NEXT DEV Release compile, but the cache's keys hold the absolute source and DerivedData paths, and both were per runner instance (RUNNER_NAME + workspace, release-derived-data-path.sh). DEV compiles land on 30+ runner instances (cmuxNN-glaeda-K, several per host), so every compile since has been cold: the compile job's median is still 10.8 min over the last 12 DEV publishes (measure_next_build.py --dev-chain --limit 12).

This gives each mini ONE build root for the DEV Release compile, so the keys match whichever instance builds:

  • scripts/cmux-next/compile-dev-release.sh (the DEV step now calls it): on a glaeda mini with the cache on, it takes the host lock, clones this checkout to ~/Library/Caches/cmux-next-ci/dev-daily-release/host/src with scripts/ci/canonical-build-root.sh (the fixed-root copy that the owned catch-up and compile admission use: the old tree is removed first, then an APFS clone, with an rsync --delete fallback, .git included, plus the cmux-tui tree and web bundles that earlier steps put in the checkout), checks the clone's HEAD is the checked-out commit, and builds there into one DerivedData per host (release-derived-data-path.sh dev-daily-release Release --host → .../host/Release/xcode-<toolchain>, with the same toolchain pruning and 12 GiB bound). The checkout's acpmux path is remapped into the tree.
  • scripts/cmux-next/host_build_lock.py: one build per host, taken without waiting. The lock is flock(2) on host/lock through fd 9, which the wrapper and every child it starts (the clone, xcodebuild, ditto) inherit. The kernel holds the lock until the last of them exits and drops it however they end. So a SIGKILLed wrapper whose xcodebuild still runs keeps the root until that xcodebuild is gone, and no stale lock is ever left behind. There is no pid file to judge (this changed after the first Codex review). The file's content only names the holder, for a busy caller's log.
  • Fallback, never a wait: a busy lock, a lock error or a failed tree setup builds right away the old way (per runner instance from the checkout, still with the cache). No job waits on a host, and no host is reserved.
  • Unchanged: cache keys stay Xcode CAS content hashes (the path is fixed only so they match), the build still starts from an empty DerivedData that keeps only CompilationCache.noindex and SourcePackages (ci(nightly): start the shipped Release build from empty DerivedData #21761), the ci(cmux-next): DEV Release compile reuses a content-keyed compilation cache, not kept build products #24994 cache-failure retry, the 3 GiB limit and the prune after each build. The switch-off is the same: CMUX_NEXT_DEV_COMPILATION_CACHE=0 also turns off the host root.
  • Content-keyed whole-app reuse (ci(cmux-next): key the compiled DEV Release app by its content #24963/ci(cmux-next): reuse the compiled DEV Release app when its inputs did not change #24964/fix(ci): an unset CI_NEXT_DEV_PRODUCT_REUSE leaves DEV product reuse on #25075) runs before this and is untouched. Its key changes once, because this workflow file is part of it. The key stays as it is: the build path is "where", not "what". Before this PR the path already varied per runner and was never part of the key.

Tests

  • New tests/test_cmux_next_dev_release_host_root.py (run in the checks job) runs compile-dev-release.sh against stub compilers. It covers:
    • two runner instances build at one host src and DerivedData;
    • the tree is exactly the new commit (a file from an earlier checkout is gone);
    • a build that starts while another holds the root builds per instance at once and leaves that lock in place;
    • a SIGKILLed wrapper whose compile still runs keeps the root until the compile exits, and the next build then takes it;
    • a lock file left behind is not held;
    • a failed setup builds per instance and releases the lock;
    • with the cache off, or off a mini, nothing touches the host root;
    • a failed compile keeps its status and releases the lock;
    • the lock CLI holds one holder at a time, and a child keeps the lock after its shell is killed.
  • tests/test_cmux_next_release_build_retention.py runs the DEV step through the new script. Its per-instance assertions are unchanged.

Risk

Medium, CI only, and it touches only the DEV Release compile (nightly and stable are untouched).

  • Failure mode: a mis-set-up host tree. It fails closed to the per-instance build, and the step summary says which build root it used and why.
  • Disk: one more CoW tree plus one DerivedData per host, bounded by the existing caps. The old per-instance DerivedData stay, for the fallback.

Signals

  • Success: two DEV compiles on the same host, back to back, where the second's xcodebuild time is well below the cold time. I'll measure after landing with the same harness and report.
  • Failure: the step log or summary shows instance build root (host tree setup failed) on a mini, or a DEV compile on a host that has already built the cache is no faster.

Agent session: cosmic-gray

🤖 Generated with Claude Code

…he per host

#24994 turned on Xcode's compilation cache for the DEV Release compile, but
its keys hold the absolute source and DerivedData paths, and both were per
runner instance (RUNNER_NAME + workspace). DEV compiles land on 30+ instances,
so every compile since stayed cold (compile job median 10.8 min over the last
12 DEV publishes).

scripts/cmux-next/compile-dev-release.sh now builds, on a mini with the cache
on, from one tree per host (~/Library/Caches/cmux-next-ci/dev-daily-release/
host/src, cloned from the checkout by canonical-build-root.sh, the fixed-root
copy the owned catch-up uses: old tree removed first, APFS clone, rsync
fallback) into one DerivedData per host (release-derived-data-path.sh --host).
host_build_lock.py takes the host lock for the build without waiting (pid +
start time, flock-guarded check, stale holders replaced); a busy lock, a lock
error or a failed setup builds per runner instance at once, as before. The
cache-failure retry, the fresh tree around the CAS and the 3 GiB prune are
unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16fa4-6017-7cf0-a801-d0761b36e005&host=cosmic-gray
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Owned by claude-sr2/incremental-build on cosmic-gray · session

@blacksmith-sh

blacksmith-sh Bot commented Oct 25, 2026 •

Copy link
Copy Markdown

Found 9 test failures on Blacksmith runners:

Failures

Test View Logs
/tmp/tmp8_wvvgdq/summary-missing.json (live):/summary-missing.json (live): View Logs
/tmp/tmph06g48hr/summary-fail.json (live):/summary-fail.json (live): View Logs
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows/
[new_workspaces] debug.new_workspace timed 0 of 50 new workspace rows
View Logs
[new_workspaces] the window draws no frames/[new_workspaces] the window draws no frames View Logs
[tabs] debug.tab_switch timed 0 of 40 switches/
[tabs] debug.tab_switch timed 0 of 40 switches
View Logs
[tabs] the window draws no frames/[tabs] the window draws no frames View Logs
bench OTHER_SWIFT_FLAGS is 'OTHER_SWIFT_FLAGS=$(inherited) -DCMUX_BENCH_HOOKS -DCMUX_BL
OCKING_CHECKS'/
bench OTHER_SWIFT_FLAGS is 'OTHER_SWIFT_FLAGS=$(inherited) -DCMUX_BENCH_HOOKS -DCMUX_BL
OCKING_CHECKS'
View Logs
bench OTHER_SWIFT_FLAGS is 'OTHER_SWIFT_FLAGS=$(inherited) -DCMUX_BENCH_HOOKS -DCMUX_BL
OCKING_CHECKS'/
bench OTHER_SWIFT_FLAGS is 'OTHER_SWIFT_FLAGS=$(inherited) -DCMUX_BENCH_HOOKS -DCMUX_BL
OCKING_CHECKS'
View Logs
convention violations found (ERROR lines above)./
convention violations found (ERROR lines above).
View Logs

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

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

cmux-next guards / nightly-guards / workflow-guard-tests / release-notary is red on 17 of 20 fresh feat-cmux-next PR heads in the last 2:00:00, so it is most likely a base red, not this PR's. The base-reds lane has it; a base merge picks up the fix once it lands.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Bead cx-z19nv created for this PR by the cmux coordinator.

…pid record

Review (Codex xhigh): a pid record goes stale when the wrapper is SIGKILLed
while its xcodebuild still runs, and the next build would then share the tree.
The lock is now flock(2) on HOST_ROOT/lock through fd 9, which every child
inherits: the kernel holds it until the last of them exits and drops it however
they end, so there is no stale state to judge and no guard that waits. Tests
cover a concurrent build, a SIGKILLed wrapper whose compile keeps running, and a
leftover lock file. apfs_clone.py joins the workflow path filters.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Agent-Session: https://cmux.com/deeplink/agent?harness=claude&session=01a16fa4-6017-7cf0-a801-d0761b36e005&host=cosmic-gray
@github-actions

github-actions Bot commented Oct 25, 2026 •

Copy link
Copy Markdown
Contributor

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

Review 65ec818: HQ feed card · gallery before/after runs · checks

App of this head (app.zip, kept 1 day)

gh workflow run reload-build.yml -R manaflow-ai/cmux --ref feat-cmux-next -f tag=pr25147 -f ref=incremental-build-pr5-host-cache -f platform=macos -f backend_mode=local

web and size checks: green

@github-actions github-actions Bot added the risk:high Risk tier (docs/ci/risk-tiers.md) label Oct 25, 2026
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

Review (codex gpt-6-astra xhigh): SHIP at 65ec818

@teamleaderleo
teamleaderleo merged commit ebbefce into feat-cmux-next Oct 26, 2026
132 of 142 checks passed
@teamleaderleo
teamleaderleo deleted the incremental-build-pr5-host-cache branch October 26, 2026 01:41
@github-actions

Copy link
Copy Markdown
Contributor

The feat-cmux-next push run https://github.com/manaflow-ai/cmux/actions/runs/40255417638 at ebbefce failed: cmux-next Release compile (fleet fast check).
Those jobs last passed at b14d855. This pull request is one of 3 merged since: #24272, #24289, #25147.
If the failure is in your change, fix forward on feat-cmux-next. Pull requests run only the tiers their paths reach (docs/ci/cmux-next-tiers.md); label a batch PR full-ci to run them all before merging.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

base-red-watch: cmux-next / cmux-next fast tier went red on feat-cmux-next in https://github.com/manaflow-ai/cmux/actions/runs/40256330328 (first red at ab42ace, last green at c7c6530). Suspect: #25147 (commit ebbefce). If it is yours, fix forward on feat-cmux-next.

2 similar comments
@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

base-red-watch: cmux-next / cmux-next fast tier went red on feat-cmux-next in https://github.com/manaflow-ai/cmux/actions/runs/40256330328 (first red at ab42ace, last green at c7c6530). Suspect: #25147 (commit ebbefce). If it is yours, fix forward on feat-cmux-next.

@teamleaderleo

Copy link
Copy Markdown
Collaborator Author

base-red-watch: cmux-next / cmux-next fast tier went red on feat-cmux-next in https://github.com/manaflow-ai/cmux/actions/runs/40256330328 (first red at ab42ace, last green at c7c6530). Suspect: #25147 (commit ebbefce). If it is yours, fix forward on feat-cmux-next.

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

Labels

risk:high Risk tier (docs/ci/risk-tiers.md)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant