Skip to content

The gate owns its build directories - #76

Merged
lann merged 1 commit into
mainfrom
ci-cache-target-dirs
Aug 13, 2026
Merged

The gate owns its build directories#76
lann merged 1 commit into
mainfrom
ci-cache-target-dirs

Conversation

@lannbot

@lannbot lannbot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

What

Swatinem/rust-cache keeps the cargo home (cache-targets: false); actions/cache keeps target and .deps/iroh/target whole, restored before the gate and saved after it on main.

Why #75 did not deliver

#75 landed the mtime half correctly — probe run 31730990571 shows sources dated by their commits (iroh-relay/src/lib.rs at 2026-06-11) and restored artifacts newer (18:12 the same day) — but the gate still compiled 27 crates and stayed at 7m28. The fingerprint log gives the reason, and it is not staleness:

dirty: FsStatusOutdated(StaleItem(FailedToReadMetadata {
  path: ".deps/iroh/target/release/deps/libiroh_relay.rlib" }))
dirty: FsStatusOutdated(StaleItem(FailedToReadMetadata {
  path: "target/host/deps/endpoint_demo-9a6a98352a1e04f4" }))
dirty: FsStatusOutdated(StaleDepFingerprint { unit: ... })     ← everything above them

Missing outputs, not old ones. Three ways the action's target caching removes them:

  1. It keeps only packages whose manifest is outside the workspace root. Every crate the gate builds lives inside one: target/host/.fingerprint held our two members and nothing from .deps — no iroh, no iroh-relay, no sibling host crates.
  2. cache-workspace-crates (from In-repo build artifacts survive the CI cache #75) adds back the members, but they sit on top of those path dependencies, so they rebuilt anyway — the StaleDepFingerprint cascade.
  3. Its keep-list matches file names by stripping a trailing -<hash>, so artifacts cargo emits without one are dropped regardless (deps/libiroh_relay.rlib), as are bin artifacts whose target name differs from the package name (endpoint_demo-…; the metadata filter drops bin kinds).

None of these is configurable, so the gate keeps its own build directories.

Measured, on this branch, before asking for a merge

A seeding run and then a re-run against it (31731856587, then 31733485940):

before (#75, run 31729951445) this branch (run 31733485940)
gate step 7 m 28 s 3 m 12 s
whole job 9 m 12 s 4 m 34 s
crates compiled 27 0
cache entries 1.78 GB 0.30 GB (cargo home) + 1.55 GB (build dirs)
restore 25 s 26 s

The gate is now its tests: matrix (13 rows), the deltic exam (7 pass), and bench, all green in that run with nothing to build.

The verification used a temporary branch allowlist on both save conditions, removed before this PR (the commit here is main-only). Removing it changes ci.yml, which is in both keys, so this PR's run and the first run on main are cold and re-seed; the run after that is the steady state above.

Notes

  • Saving is gated on a green gate and on main, and skipped when the restore already held the key. On a miss, restore-keys: build-dirs- still restores the newest entry, so a key rotation costs an incremental rebuild rather than a cold one.
  • The key covers the toolchain, both root manifests, both lockfiles, both justfiles, and the workflow — everything that invalidates artifacts wholesale.

rust-cache keeps the cargo home; `actions/cache` keeps `target` and
`.deps/iroh/target` whole. The action's own target caching cannot serve
this gate: it saves a build directory only after deleting every package
whose manifest lives inside the workspace root, which is every crate the
gate spends its time on — ours and the pinned checkouts'. Keeping the
workspace members (#75) did not help, because they sit on top of the
path dependencies it still deleted, and a missing dependency output
rebuilds everything above it. Even among the packages it keeps, artifacts
whose file name carries no build hash are dropped: cargo's own
`deps/libiroh_relay.rlib` was the reason the relay rebuilt every run.

A green gate is what justifies saving, so the save runs after it, on main
only, and only when the restore did not already hold the key. A key that
misses still restores the newest entry under the `build-dirs-` prefix, so
cargo rebuilds what changed rather than everything.

Measured on this branch, seeded and then re-run: the gate compiles
nothing and takes 3m12, against 7m28 before; the two cache entries
together are 1.85 GB where the single one was 1.78 GB, and restoring them
costs 26s.
@lann
lann merged commit f796a5a into main Aug 13, 2026
1 check passed
@lann
lann deleted the ci-cache-target-dirs branch August 13, 2026 19:47
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.

2 participants