Skip to content

bench.yml: rust-cache deletes the shared registry/src — delete it, and add the lint this repo never had (infra#775) - #21

Merged
noahgift merged 1 commit into
mainfrom
fix/rust-cache-shared-registry
Sep 20, 2026
Merged

noahgift merged 1 commit into
mainfrom
fix/rust-cache-shared-registry

Conversation

@noahgift

Copy link
Copy Markdown
Member

Closes #20. Part of the fleet-wide fix for paiml/infra#775; the infra-side guard is paiml/infra#778 (merged) and these call-site PRs go out alongside it so the nightly shared-cargo-home lane is never unpassable.

What was wrong

bench runs on [self-hosted, intel] and carried Swatinem/rust-cache@v2 with cache-bin: "false" — the paiml/infra#208 mitigation, which guards ${CARGO_HOME}/bin only.

cache-bin: false skips cleanBin and nothing else. The save step also runs cleanRegistry, unconditionally, deleting ${CARGO_HOME}/registry/src — the extracted crate sources every OTHER job on the box is compiling from. All 16 intel-clean-room-* runners share HOME=/home/noah.

Measured on intel 2026-09-19: eight save steps in 100 minutes; every crate directory under the shared registry with a birth time pinned to the second one of them finished; an infra cargo kani build killed mid-crate with could not parse/generate dep info ... No such file or directory. The step that killed it carried cache-bin: "false".

Change

  • bench.yml: step deleted. cache-targets: true was the reason to keep it, but target/release here is a per-run directory on a persistent box and ~/.cargo persists between jobs by itself — the restore bought little and the save deleted other jobs' sources. The old comment block is replaced by the measurement.

  • scripts/lint-rust-cache-guard.sh (new). This repo had no lint, and its own comment says why that mattered: "rmedia hit this four times and fixed it in its own workflows on 2026-08-17. This repo was never re-reviewed in that sweep — its last commit predates it — so the same landmine sat here on main." A rule enforced by review skips whatever nobody re-read.

    The lint refuses Swatinem/rust-cache and actions-rust-lang/setup-rust-toolchain (which wraps it) on any self-hosted job; exonerates only a job-private CARGO_HOME, because --target-dir, cargo install --root and a fresh $HOME do not move the sources out of the shared directory; prints its denominator; and NO-GOes on zero workflows or zero self-hosted jobs.

  • make rust-cache-guard + a ci.yml step, selftest FIRST — once the step it guards is deleted the scan passes trivially, so the instrument has to be shown capable of failing before its green means anything.

Measured

$ make rust-cache-guard
  ok   a self-hosted rust-cache is rejected even with cache-bin: "false"
  ok   a self-hosted workflow with no cache action passes
  ok   no self-hosted job -> NO-GO, never a vacuous pass
  ok   a job-private CARGO_HOME is exonerated
lint-rust-cache-guard --selftest: OK (4 cases)
lint-rust-cache-guard: OK (0 $CARGO_HOME cache use(s) in 1 self-hosted workflow(s) of 3 scanned)

$ bash scripts/lint-rust-cache-guard.sh   # against main
ERROR: ./.github/workflows/bench.yml:103 uses a $CARGO_HOME cache action on a self-hosted job.

bashrs lint scripts/lint-rust-cache-guard.sh: 0 errors (and the script is added to the bashrs-lint target).

ci.yml and release.yml keep their rust-cache steps: both run on ubuntu-latest, where $HOME is ephemeral and the save step can only delete that runner's own copy.

🤖 Generated with Claude Code

…d add the lint this repo never had (#20)

`bench` runs on [self-hosted, intel] and carried Swatinem/rust-cache@v2 with
cache-bin: "false", on the paiml/infra#208 reasoning that the post step prunes
${CARGO_HOME}/bin and that the one input prevents it.

That input skips cleanBin and NOTHING else. The save step also runs
cleanRegistry, unconditionally, deleting ${CARGO_HOME}/registry/src — the crate
sources every other job on the box is compiling from. All 16 intel-clean-room-*
runners share HOME=/home/noah.

Measured on intel 2026-09-19 (paiml/infra#775): eight save steps in 100 minutes,
every crate directory's birth time pinned to the second one of them finished,
and an infra cargo kani build killed mid-crate with `could not parse/generate
dep info … No such file or directory`. The step that killed it carried
cache-bin: "false".

cache-targets: true was the reason to keep the step, but target/release here is
a per-run directory on a persistent box and ~/.cargo persists between jobs by
itself: the restore bought little and the save deleted other jobs' sources.

This repo's own comment recorded why it was a repeat — rmedia fixed the same
shape in August and this repo "was never re-reviewed in that sweep". A rule
enforced by review skips whatever nobody re-read, so this adds
scripts/lint-rust-cache-guard.sh, which did not exist here: no rust-cache and no
actions-rust-lang/setup-rust-toolchain on a self-hosted job unless that job's
CARGO_HOME is private (the only exoneration — --target-dir, --root and a fresh
$HOME do not move the SOURCES). It prints its denominator, NO-GOes on zero
workflows or zero self-hosted jobs, and --selftest proves all four cases. Wired
into `make rust-cache-guard` and ci.yml, selftest FIRST: once the step is gone
the scan passes trivially, so the instrument has to be shown capable of failing.

Measured here: selftest 4/4; this tree OK (0 uses in 1 self-hosted workflow of 3
scanned); against main's bench.yml it ERRORs at line 103. bashrs lint: 0 errors.
@noahgift
noahgift merged commit 66fd6f7 into main Sep 20, 2026
3 checks passed
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.

bench.yml: rust-cache deletes the shared registry/src for every job on the box (paiml/infra#775)

1 participant