Repository navigation
ci: keep main's Rust caches resident, and size the test job for a cold one - #418
Merged
Merged
Conversation
…d one Two pushes to main on 2026-10-18 (39156748556, 39158205693) were cancelled at 40.0 and 40.2 minutes in test (ubuntu-latest) with every step green. The cache key was unchanged (v0-rust-ubuntu-latest-test-Linux-x64-edf29d0d- c299e55f, hit at 17:39 by the release PR), yet both runs logged "No cache found". GitHub had evicted the entry: at 18:16-18:18 the release branch's GUI package workflows saved two cross caches (1.2 + 1.4 GB, readable by that branch alone and never read again), the repository passed its 10 GB cache limit, and the least recently used entry was the ubuntu test cache, last read at 17:39:11. A cold ubuntu run takes 30.5-40.2 minutes (n=10). A second, recurring cause: rust-cache hashes every installed toolchain into its key, including the runner image's own stable that nothing here builds with. Image 20261002 moved it 1.98.1 -> 1.99.0 and every ubuntu run built cold from 2026-10-10 until main next saved on 10-12. - test: timeout 40 -> 60, with the measured warm/cold table per OS. - test, serve, frontend api-contract, apps-smoke: remove every toolchain but the pinned one before rust-cache, so image updates stop changing keys. - serve, frontend api-contract, apps-smoke: save-if main, as test already did. During the 10-11/12 eviction every PR's serve job wrote its own 1.9 GB copy. - linux/windows GUI packages: no persisted cross cache. Branch saves were never reused, and main saves would not fit beside main's ~8.3 GB of test caches, because rust.yml's cross-check reads the same key prefix on every run. Cold builds take 30.8-39.1 minutes against a 100 minute limit.
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why main went red with every step green
Two pushes to main on 2026-10-18 had
test (ubuntu-latest)cancelled at the 40-minute limit: 39156748556 (40.0 min) and 39158205693 (40.2 min). Every step succeeded, "Complete job" included. Both had a cold Rust cache.It was not a key change, and PR and main runs share the cache already. I read the rust-cache lines from the jobs API for six runs that day. All six computed the same key,
v0-rust-ubuntu-latest-test-Linux-x64-edf29d0d-c299e55f, on the same runner image:The entry existed at 17:39 and was gone by 19:00. GitHub evicted it.
Linux GUI packages/Windows GUI packagesdispatches saved two cross caches: 1.2 + 1.4 GB, scoped torelease/1.93.2and readable by nothing else./actions/cache/usagereads 12.35 GB right now).serve's, and six seconds before the others.Racing made it worse but did not cause it. The two main runs started 19 minutes apart, both before either had saved. So both paid the cold price.
A second, recurring cause. Swatinem/rust-cache hashes every installed toolchain into its key:
rustup toolchain list, thenrustc -vVof each (getRustVersionsin itssrc/config.ts). That includes the runner image's ownstable, which nothing here builds with, becauserust-toolchain.tomlpins 1.92.stablefrom 1.98.1 to 1.99.0.…-15238ee1-c299e55fto…-edf29d0d-c299e55f.Why a cold cache turns into a red X. The 40-minute budget was set on 2026-08-27, when this job took 15 minutes warm. Since then the integration-binary step and the socket gate have doubled it, and the budget stayed. Measured over the completed runs of 2026-10-10..18, classified by each job's own rust-cache restore line:
cargo testwhen 40 hit (39057096529)Main's first run after any key change is cold by design: a dependency in
Cargo.lock, the toolchain, or aCARGO_*variable. So the budget has to hold a cold run.What changes
rust.ymltest:timeout-minutes40 → 60. That is 1.5× the measured cold maximum, which is the margin theguardscomment says these budgets keep. A hang still costs an hour, not six. The comment carries the table above.test,serve,frontend.ymlapi-contract,apps-smoke.yml). A small step removes every toolchain exceptrustup show active-toolchain. Runner image updates no longer change the keys.save-if: mainon the rust caches that lacked it (serve, api-contract, apps-smoke), astestalready did. During the 10-11/12 eviction, each PR's firstserverun wrote its own 1.9 GB copy that no other branch could read (38176616426, 38204107268, 38235367922, 38240320573). That compounded the eviction.rust.yml'scross-checkrestores the samecross-<triple>-prefix on every run, so the pair would stay resident and push a test cache out instead.release.shalready does.Nothing under
tests/orsrc/changes. The integration-binary step, its exclusion table and the network namespace are untouched.Expected one-time cost. Pruning the toolchain changes every rust-cache key once. This PR's own runs and the first push to main after merging build cold, under the new limit. Main then saves the new keys.
Measured result
This PR's own run (39371819622) was cold on every OS by design. The new keys hash one toolchain. Each job's log shows
info: uninstalling toolchain stable-<host>, thenRust Versions: 1.92.0alone andNo cache found:...-ed8f1928-c299e55f...-4276b576-c299e55f...-a733e789-c299e55f...-4bbc99e1-c299e55fThe prune step itself took under 0.1 min on all three OSes.
The two pushes to main after merging ran back to back and were both cold. That is the same situation as the 2026-10-18 pair, where the second push starts before the first has saved. Both passed:
2291a0254(this PR)06ca6bd24(#419)All four ubuntu and macOS times are above the old 40-minute limit, so the old budget would have cancelled every one of them. They used 68–70% of the new limit.
v0-rust-ubuntu-latest-test-Linux-x64-ed8f1928-c299e55fat 07:50.Main's caches are now the six new rust entries plus npm, about 8.3 GB. The old-key entries still counted in
/actions/cache/usage(11.3 GB) are the least recently used, so they are what GitHub evicts first.The next push to main is the first warm run on the new keys.
Not changed, noted
rust.ymlcross-check's cache save fails on every run:"/usr/bin/tar" failed with exit code 2on the container's root-owned files. So it never persists anything; it builds cold, max 8.6 / 18.5 min of 30. If that save is ever fixed, it needsmain-only saving first, or every PR writes 2.6 GB.computer-use-package-acceptance.yml(dispatch-only, last run 2026-09-24) still saves its caches on whatever ref it is dispatched on.setup-node's npm caches (about 0.16 GB per OS) are still written per PR whenpackage-lock.jsonchanges.🤖 Generated with Claude Code