ci: warm the main-scoped CI cache so PRs stop building cold#5326
Merged
Conversation
test.yml runs only on PRs + tags, never on push to main, and GitHub Actions cache scoping means PRs can only restore caches from their own branch or the default branch. With nothing running the cache-producing build on main, no main-scoped cache existed and every PR built cold (~90-103 min). This also silently disabled Swatinem/rust-cache (save-if:main never fired). Add cache-warm.yml: on push to main touching Rust, compile (--no-run) the heavy crates' test binaries and save under the same rust-cache shared-key + sccache key prefix test.yml restores. Best-effort (continue-on-error), prunes between crates for disk, concurrency-cancels superseded warms.
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 (the part #5324 didn't cover)
#5324 moved sccache to a persisted disk cache — necessary, but not sufficient. While verifying it, I found the deeper reason caches were always empty:
test.ymlruns only onpull_request+ version tags — never on push tomain. And GitHub Actions cache scoping lets a run restore caches only from its own branch or the default branch (main) — never another PR's cache. So with nothing running the cache-producing build onmain, no main-scoped cache ever existed, and every fresh PR started cold (~90-103 min, tipping overcargo-test's timeout onperry-runtime/perry-codegenPRs).The same flaw silently disabled
Swatinem/rust-cacheeverywhere in test.yml: itssave-if: refs/heads/mainnever fires because test.yml doesn't run on main, sotarget/was never saved either. (Onlynode-core-subset.yml's weekly scheduled run happened to save aLinux-perrycache.)What this adds
A new
cache-warm.ymlthat runs once permainmerge touching Rust (crates/**,Cargo.toml,Cargo.lock):--no-run— the test binaries of the heaviest crates (perry-runtime,perry-stdlib,perry-codegen,perry), which pull in essentially the whole third-party dependency graph + the big first-party crates (the bulk ofcargo-test's compile time). The cheapext-*crates that follow in cargo-test then reuse those cached units.rust-cacheshared-key (<os>-perry) and same sccache key prefix (sccache-<os>-perry-) that test.yml'scargo-test/api-docs-drift/compiler-output-regressionjobs restore — so the main-scoped caches now exist for every PR to pick up.continue-on-error(a cache warm, never a gate), prunes test binaries between crates to respect the runner disk budget (same reason cargo-test does), and usesconcurrency: cancel-in-progressso only the latest main commit warms.Expected effect
After the first warm run lands on
main, PRcargo-testrestores a warm cache and should run ~50-60 min instead of ~90-103 min cold. Watch the sccache "stats" step on the warm run and the next PR's sccache "Post" stats to confirm hit rates jump, then thecargo-testtimeout (temporarily 180) can come back down.No production code changes.