Skip to content

ci(cache): key the Windows target archive by dependencies, not commit - #343

Merged
hyperb1iss merged 1 commit into
mainfrom
nova/dependency-keyed-archive
Oct 2, 2026
Merged

hyperb1iss merged 1 commit into
mainfrom
nova/dependency-keyed-archive

Conversation

@hyperb1iss

Copy link
Copy Markdown
Owner

What this changes

The Rust Windows job stops saving a new 19.5 GB target archive on every main commit. Its archive is now keyed by the lockfiles instead of the commit, so a successful main run saves one entry per dependency set, and every later commit restores that entry as an exact hit and skips the save. The workspace crates that changed since the entry was saved recompile, and the shared R2 compiler cache serves each of those compiles that an earlier main run already performed.

The cache action gains an archive-key input for this. revision (the default) keeps today's per-commit key for every other lane; dependencies drops the commit, and only Rust Windows uses it.

Why

On the last measured main runs the Windows job spent about 21 to 24 minutes uploading its archive, which is 19,546,526,845 bytes. Each commit's copy is a new entry, so two of them sit in the Actions cache at once (18.2 GiB each against a 50 GB budget), evicting other lanes' entries; the Windows Cargo registry entry was evicted within hours of being restored. Now that R2 holds compiled workspace crates, a per-commit archive mostly re-uploads dependencies that have not changed.

How it works

Run Restores Saves
First main run after merge Today's newest per-commit entry, by prefix (actions/cache prefix-matches the primary key) The lockfile-set entry
Later main commits, same lockfiles The lockfile-set entry, exact hit Nothing
Lockfile change The newest older entry, by prefix The new lockfile-set entry
Failed main run (the lane saves on failure) As above Its per-commit key, never the lockfile-set key
Pull requests and tags The lockfile-set entry Nothing, as before

The failure row keeps the Windows lane's recovery property. A failed run's archive is saved under its revision key, which the lockfile-set key prefix-matches without being an exact hit. The next successful run restores that partial archive, completes it, and saves the real entry, so a partial archive never becomes the exact hit that later runs stop saving over.

Verification

  • Added or updated tests
  • Added or updated docs (README, AGENTS.md, relevant spec, or guide)
  • just verify passes locally (Rust fmt + lint + test) (not applicable: no Rust changes)
  • just deny passes (required for dependency or license changes)
  • just ui-test and just ui-build pass (required for crates/hypercolor-ui/)
  • just sdk-lint, just sdk-check, and just sdk-build pass (required for sdk/)
  • just python-verify passes (required for python/)
  • just compat-check passes (required for data/drivers/vendors/*.toml)
  • just docs-build passes (required for docs or README changes)
  • cd docs && zola check passes (required for docs link/content changes)
  • Packaging scripts were syntax-checked (required for scripts/ or packaging/)
  • just e2e-build passes with the normal Servo stack (required for daemon/UI/effect integration changes)
  • just e2e-build-cpu passes when validating the CPU smoke fallback
  • just e2e passes against the Servo stack (required for end-to-end behavior changes; starts daemon/browser)
  • Tested on real hardware, simulator, or e2e harness (describe below)

node --test .github/actions/rust-build-cache/*.test.mjs with sccache 0.17.0 (the CI pin): 30 passed. New cases cover the dependency key ignoring the commit and following the lockfiles, the failure key being a non-exact prefix match, the save step choosing the failure key on a failed run, and the Windows job's wiring. An independent review mutated the scope logic, the failure-save rule, and the wiring a dozen ways; every mutation failed a test. The docs change is under docs/development/, outside the Zola site.

The real proof is the first two main runs after merge: the first should save the lockfile-set entry once, and the second should report an exact hit and skip "Save build artifacts and compiler cache".

Notes for reviewers

Pull requests and tags now restore an archive as old as the lockfile set rather than the newest main commit, so they rebuild a little more of the workspace and its uncacheable work (test binaries, build scripts, proc-macro crates, clippy's dependency checks). The current per-commit archive already rebuilds most of the workspace on every run: a CI-only main run still rebuilt 12 workspace packages, including hypercolor-core, and compiled 329 test binaries. Lockfile changes also reset the drift; 18 of the last 122 main commits changed one.

🤖 Generated with Claude Code

Every main run saved a fresh copy of the Rust Windows target archive.
At about 19.5 GB it took about 21 minutes per run to upload, and two
copies at once held a large share of the Actions cache budget, which
pushed other lanes' entries out.

The cache action gains an archive-key input. The default, revision,
keeps the per-commit key. dependencies drops the commit, so a successful
main run saves one entry per lockfile set; later commits restore it as
an exact hit, skip the save, and rebuild the workspace crates that
changed since, which R2 serves whenever an earlier main run compiled the
same inputs. Test binaries, build scripts, proc-macro crates, and clippy
checks still come from the archive, now as fresh as the commit that
saved it, so each crate changed since reruns that work for its
dependents.

A failed run that saves on failure uses its revision key instead. The
dependency key prefix-matches that entry without an exact hit, so the
next successful run restores and completes it, then saves the lockfile
set's entry. A partial archive still seeds recovery but never becomes
the exact hit that later runs stop saving over.

actions/cache prefix-matches the primary key, so the first
dependency-scoped restore still finds today's per-commit entries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Oct 2, 2026

Copy link
Copy Markdown

Warning

Review limit reached

  • Run on-demand review

This review includes 5 billable files and costs up to $1.25.

Or wait 43 minutes for your next included review.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 68144208-b99c-4dc1-8bba-fa307a4bea92
📥 Commits

Reviewing files that changed from the base of the PR and between 874e553 and a0d256f.

📒 Files selected for processing (5)
  • .github/actions/rust-build-cache/action.yml
  • .github/actions/rust-build-cache/configure.mjs
  • .github/actions/rust-build-cache/configure.test.mjs
  • .github/workflows/ci.yml
  • docs/development/SERVO_BUILD_CACHING.md
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Autopilot is currently an internal CodeRabbit preview.


Comment @coderabbitai help to get the list of available commands.

@hyperb1iss
hyperb1iss merged commit 768c572 into main Oct 2, 2026
42 checks passed
@hyperb1iss
hyperb1iss deleted the nova/dependency-keyed-archive branch October 2, 2026 23:54
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