Repository navigation
ci(nightly): both nightly-next build slots on a Mac build in one root, with a 10 GiB compile cache - #32514
Conversation
…, with a 10 GiB compile cache Each dedicated runner slot built in its own workspace into its own kept DerivedData and package checkouts. The compile cache keys hold those absolute paths, so one module had a different key on every slot; four key sets shared each Mac's 3 GiB cache, which rotates a generation whenever a build passes half the limit (one build is about 3.3 GB), so the slots pushed each other's entries out; and each slot's incremental check compared against its own last build about four tips back, so nearly every build started clean. The Release build step now takes a fixed per-Mac root (the same path on both nightly Macs) under a never-waited flock: it clones the checkout to ROOT/src, keeps ROOT/DerivedData and ROOT/SourcePackages, applies the same clean rules against the Mac's last build, and hands the products to the workspace while it holds the lock. A held lock builds on the slot's own state as before. The nightly-next compile cache limit is 10 GiB when its volume has 60 GiB free. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Agent-Session: https://cmux.com/deeplink/agent?id=aid-f724bb1ff9295c18fee7
|
cmux status (one comment, edited in place; each line is updated by the job that owns it) Review App of this head (app.zip, kept 1 day)
Shipped in:
|
|
Found 2 test failures on Blacksmith runners: Failures
|
|
Review (codex, router-review): SHIP at 9c61686 Reviewer: codex gpt-6.1-sol xhigh, fast tier. Follow-ups: 2. Each lands as an issue in this repo that links this receipt; the lane that opened the PR fixes it forward. SHIP at 9c61686 Visual verdict: no images; Leo tries the build Focused nightly state and fleet-cache tests pass (39 tests).
Follow-ups:
|
|
Review (codex gpt-6-astra high, sweep, via the review router; full diff from merge base 8db9104 to this head): SHIP at 9c61686 [P2] [follow-up] scripts/ci/nightly_build_state.py:459 - |
|
Review (codex gpt-6.1-sol xhigh, carried): SHIP at b30606e This is a carry of the SHIP at 9c61686 (#32514 (comment)). b30606e is cmux-bot's clean base merge with no hand resolution ( Follow-ups (to be filed): [P1] keep the host lock held through cancellation and detached build descendants; [P2] bound the host root's kept compilation cache. |
|
Performance after merge (first nightly-next builds at the per-host build root):
This was still a clean build, the first on the new root, but nearly every cached task now replays. The second build on the same host should be incremental whenever no Package.swift or import change lands in between. I'll fill in the Mac B row from the next nightly that builds there. 🤖 Generated with Claude Code |
…ot script (release-notary red since #32514) (#32548) tests/test_nightly_next_arm64_only.py runs the real "Build nightly app (Release)" step text in a temp root with recorder executables. Since #32514 that step sources scripts/ci/nightly-steps/app-host-build-root.sh, which the recorder root did not have, so bash stopped before xcodebuild and the release-notary guard group has been red on every feat-cmux-next push since 55c0b5c. The recorder now copies that script, as it already copies compilation-cache.sh. With no BUILD_TRACK the script keeps the slot's own tree, so xcodebuild still runs in the recorder root and the ARCHS assertions are unchanged. Red on base 562235a, green here (Linux, no build): GITHUB_STEP_SUMMARY=/tmp/s.md python3 tests/test_nightly_next_arm64_only.py base: CalledProcessError (app-host-build-root.sh: No such file or directory) head: PASS: nightly-next arm64 only
![Fix with [code]smith](https://pr-comments-assets.blacksmith.sh/codesmith/fix-with-codesmith-light-3x.png)
What
build-nightly-appon nightly-next: both dedicated build slots on each of the nightly Macs now build from one fixed root per Mac instead of each slot's own workspace, and the nightly-next compile cache limit goes from 3 GiB to 10 GiB when its volume has room.All logic is in scripts;
nightly.ymlis unchanged (still under its size cap).Why (measured on 20 nightly-next runs, 41455121554 to 41485637444)
COMPILATION_CACHE_LIMIT_SIZE=3 GiB. The CAS starts a new generation whenever a build ends above half the limit (1.5 GiB), and keeps only one generation behind it. One build is about 3.3 GB, so every build rotates, and two builds by other slots (other keys) empty a slot's entries. Each slot builds only about every 4th tip, so its entries were nearly always gone. Every run compiled all ~138 Swift module tasks (SwiftCompile (138 tasks) | 1600 sCPU in run 41485637444). The cache replayed only about 311 tasks, the same set every run.mode=clean, becausePackage.swiftor an import or#ifline changed since that slot's last build. That build was 3-4 promotions back, soPackage.swift(FFI re-pins, new targets: 12 changes this morning) had nearly always changed.Change
scripts/ci/nightly-steps/app-host-build-root.sh(sourced byapp-build-release.sh): on a slot that keeps build state (the dedicated nightly-next builder), it takesflockon the root'slockand never waits for it (scripts/cmux-next/host_build_lock.py, as the DEV and PR release compiles already do). Then:ROOT/src(canonical-build-root.sh). Before that, it fetches the root's last-built commit into the checkout, so the clean rules can diff against it even when the other slot built it.ROOT/DerivedData, with packages inROOT/SourcePackages(seeded once from the slot's own) andXCBUILD_FILE_SYSTEM_MODE=checksum-only.nightly_build_state.py prepare-host / finish-host: the same clean rules as before (no rule relaxed), judged against the Mac's last build. On success, while the lock is held, it marks the build done and clones the products into the workspace'sbuild-universal. Later steps change the app bundle there, never in the root. The slot's own kept DerivedData is dropped, so there is one DerivedData per Mac instead of two.cold_cache) never takes the root.app-bound-compilation-cache.shbounds a kept (linked) cache at 12 GiB instead of 5, so a full one isn't deleted.Is a full clean needed on a Package.swift or import change?
Yes; I kept that rule. Those are the changes behind the audited stale autolink and force-load objects. A clean build is only slow when the compile cache misses. An empty DerivedData plus a warm cache whose keys match replays every unchanged task: 102 s with 4,192 of 4,192 hits, against 600 s at another path. So the fix is matching keys and a cache big enough to keep them, not relaxing the clean rules. Per Mac (every 2nd tip instead of every 4th), the diff window behind each build is also about half as long, so more builds stay incremental.
Shared compile cache: 0 hits (finding, not fixed here)
The nightly reads the fleet cache node (
COMPILATION_CACHE_REMOTE_SERVICE_PATHis set; the build uploads outputs). It can't hit, because the only trusted writer fills a different build. The writer's catch-up fill compiles the feat-cmux-next tip's Release compile from thenext-releaseroot, with no nightly defines. The nightly builds:nightly-nextroot, the same on both nightly Macs);OTHER_SWIFT_FLAGS=$(inherited) -DCMUX_NO_PASSWORD_IMPORT -DCMUX_NO_BROWSER_DATA_IMPORT -DCMUX_BLOCKING_CHECKS, which apply to every Swift target, packages included;AppIcon-Nightlyand an emptiedbrowser-sources.json.Every Swift key differs from the writer's. Getting hits takes a writer fill of the nightly-next recipe at this PR's root path; that is a follow-up on the fleet side. Separately, other jobs that share a Mac's CAS with a smaller limit can still rotate it early.
Tests
tests/test_nightly_build_state.py: newHostBuildRootcases (two slot checkouts, real scripts, stubbed Xcode):30/30 pass.
tests/test_ci_fleet_compilation_cache.py9/9 andtests/test_ci_fleet_compilation_cache.shpass.tests/test_workflow_file_size.pypasses.shellcheck is clean.
tests/test_nightly_universal_build.shfails the same way on base ("the short nightly decide gate …").Performance
Before: the 20 runs above, Build step (
Build nightly app (Release)) only. After: to be filled in from the first nightly-next runs once this is on nightly-next. Branch dispatches don't reach the nightly Macs, because placement there requiresrefs/heads/nightly-next.note: replay cache hit/local cache missWarm sources: the nightly Mac's kept DerivedData and package checkouts (now one per Mac), and the local compile cache on the Mac (10 GiB). The fleet store is read but can't hit yet (above).
Agent session: agent session
🤖 Generated with Claude Code
Open in [code]smith · Need help on this PR? Tag
@codesmith-botwith what you need.Summary by cubic
Nightly-next builds no longer recompile all ~138 Swift module tasks every run: both dedicated build slots on each Mac now build from one fixed root per Mac with a 10 GiB compile cache, so Xcode's cache keys match across slots and survive between runs.
Details
flockit never waits for, clones the checkout intoROOT/src, and builds into sharedROOT/DerivedDatawith packages inROOT/SourcePackages, applying the same clean rules against the Mac's last build. The root path is identical on both nightly Macs, so keys match across them too.Written for commit b30606e. Summary will update on new commits.