ci: crane-based Rust checks (clippy/doc/test) via nix flake check#1801
Conversation
The heavy Rust CI (clippy / doc / test, --all-features) ran as plain cargo into a persistent CARGO_TARGET_DIR on the self-hosted runner. That dir grew unbounded (every branch's artifacts, never pruned -- it filled a 200G boot volume) and is unsafe to share across parallel jobs. Express those checks as crane derivations instead, exposed via flake `checks`. `just ci` already runs `nix flake check`, so these now build in CI. Dependencies compile once (cargoArtifacts), land in the binary cache, are shared across machines, and are LRU-evicted by the store's free-space GC; only first-party code recompiles, inside Nix's sandbox -- no target dir to bound. Stage 1 (additive). Stage 2 removes the now-redundant cargo clippy/doc/test from `just rs ci` and drops the persistent CARGO_TARGET_DIR. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
crane concatenates checkCommonArgs.cargoExtraArgs (--workspace --all-features) with each check's command-specific extra args, so repeating the scope there produced 'cargo clippy --workspace ... --workspace ...' -> 'the argument --workspace cannot be used multiple times'. Keep the shared scope only in cargoExtraArgs; per-check args now carry just the command-specific flags (--all-targets, -D warnings, --no-deps). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
cleanCargoSource strips non-Rust files, but --all-targets compiles test targets that include_str!/include_bytes! data fixtures (moq-mux test_data *.ts, moq-json tests/vectors.json). clippy/doc/test failed with 'couldn't read ...'. Take the whole tree minus heavy non-source dirs (node_modules, target, .direnv, .venv, .git) so any fixture is present; dep caching is unaffected (buildDepsOnly keys on Cargo.lock). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning Review limit reached
More reviews will be available in 8 minutes and 37 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe PR integrates Nix-based CI checks for the Rust workspace with updated GitHub Actions configuration and a new local CI recipe. In 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches✨ Simplify code
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…stage 2) The heavy Rust CI now runs as crane checks via `nix flake check` (stage 1), so `just rs ci` no longer repeats cargo clippy/doc/test, and check.yml no longer sets a persistent CARGO_TARGET_DIR. Residual `cargo check`s (default / no-default feature combos crane's all-features run doesn't cover) compile into the in-workspace ./target, which the runner wipes per job -- nothing grows on $HOME anymore. Local `just rs check` is unchanged. Add a self-hosted CI assertion that nothing wrote under $HOME/cargo-target, so a CARGO_TARGET_DIR override can't silently reintroduce an unbounded target dir. This also removes the hardcoded-./target wasm-recipe footgun on the runner. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
$HOME/cargo-target is shared across repos (moq-pro) and both runners, so the broad find flagged a concurrent moq-pro job's writes. Check only this repo's old per-runner path (moq-$RUNNER_NAME) -- the dir our removed CARGO_TARGET_DIR pointed at -- so a real leak is caught without false positives from neighbors. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Effectively reverts the crane apparatus from #1801 while keeping the problem #1801 actually fixed: the heavy checks no longer compile into a persistent CARGO_TARGET_DIR (which had grown unbounded to 161G and filled the disk). Instead of crane's whole-deps blob, the runner caches cargo compilation per-crate with sccache, so a Cargo.lock change recompiles only the changed crate + its reverse-deps. ./target stays ephemeral (wiped per job) -- no persistent target dir to bound. The crane checks rebuilt the entire third-party graph on any Cargo.lock change (e.g. adding serde_with = ~tens of minutes when the box is busy), because buildDepsOnly is keyed on the whole lockfile. - nix/overlay.nix: remove the crane check apparatus (moqChecks, checkDeps, checkCommonArgs, checkSrc). - flake.nix: `checks = { }`. `nix flake check` still validates flake eval + dev shell, just without compiling the workspace. - rs/justfile: run all-features clippy/doc/test + the feature-edge cargo checks here, as plain cargo. - justfile: refresh the `nix flake check` gate comment. sccache is wired into the runner environment (see the oci repo), not the repo: jobs just run cargo, and the cache is invisible infra that benefits every repo's Rust jobs. Release artifacts are unchanged -- still built via crane buildPackage, hermetically (the sandbox scrubs the runner env). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Why
The self-hosted A1 runner filled its 200G boot volume and CI started failing with
No space left on device. Root cause: the heavy Rust CI (just rs ci→cargo clippy/doc/test --all-features) compiled into a persistentCARGO_TARGET_DIR($HOME/cargo-target/moq-$RUNNER_NAME) that grew unbounded (every branch's artifacts, never pruned — 161G), was unsafe to share across parallel jobs, and lived outside the workspace so the per-job cleanup never touched it. Crane already built the release binaries, but the CI checks never went through it.What
Move the heavy checks into crane, exposed via flake
checks, and makenix flake checkthe thing that runs them:clippy—--all-targets --all-features -- -D warningsdoc—--no-deps --all-features,RUSTDOCFLAGS=-D warningstest—--all-targets --all-featuresDependencies compile once (
cargoArtifacts = buildDepsOnly), land in the Cachix binary cache, are shared across machines, and are LRU-evicted by the Nix store's free-space GC. Only first-party code recompiles, inside Nix's sandbox — no persistent target dir to bound.Then (stage 2 in this PR):
just rs cino longer repeats cargo clippy/doc/test (crane owns them); it keeps non-compiling hygiene (fmt/shear/sort),cargo-deny(needs network, can't run in the sandbox), and the default / no-default-featurecargo checks the all-features crane run doesn't cover.check.ymldrops the persistentCARGO_TARGET_DIR; residualcargo checks use the in-workspace./target, which the runner wipes per job.$HOME/cargo-target, so aCARGO_TARGET_DIRoverride can't silently reintroduce an unbounded target dir.Local
just rs check(the fast cargo inner loop) is unchanged.Verification
CI on the self-hosted aarch64-linux runner is authoritative (Linux-only features: alsa, libva, jemalloc). Confirmed green through iterations: the
--all-featuresdep graph — includingboring-sys/quiche — builds in the sandbox (neededgitfor BoringSSL patches), test fixtures (include_*!data) are kept in the check source, and thetestsuite passes inside the sandbox.Notes
CARGO_INCREMENTAL=0, in theociinfra repo).CARGO_TARGET_DIRalso removes the hardcoded-./targetwasm-recipe footgun that bit branchclaude/merge-main-into-dev-992spqon the self-hosted runner.cargoArtifactsacross packages+checks to cut redundant dep compiles; Nix-vendoring the other languages (GobuildGoModule, uv viauv2nix, bun viabun2nix) to extend the "sandbox-except-/nix" model beyond Rust.