refactor(anvil): adopt cargo-each for scoped checks - #151
refactor(anvil): adopt cargo-each for scoped checks#151martin-kolinek wants to merge 28 commits into
Conversation
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Codecov Report✅ All modified and coverable lines are covered by tests. ❌ Your project status has failed because the head coverage (97.5%) is below the target coverage (100.0%). You can increase the head coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #151 +/- ##
=======================================
- Coverage 97.5% 97.5% -0.1%
=======================================
Files 300 300
Lines 69048 69048
=======================================
- Hits 67386 67385 -1
- Misses 1662 1663 +1
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
🟡 Changes recommended
The include-file projection format changed but the impact cache freshness key doesn’t encode a projection-format version, risking “cache hit” reuse of old-format include files that can break the new cargo each @selection call sites.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Pull request overview
This PR refactors cargo-anvil’s impact-scoped check execution to use cargo-each as the package selection + execution boundary, shifting impact outputs from pre-built --package name@version ... strings / --skip into tokenized selector streams (--workspace, repeated --package + name, or --none).
Changes:
- Change impact cache projection to emit one selector token per line and update
_anvil-impact-includeconsumers to capture a splattable array. - Delegate many “ordinary” checks (clippy, docs, udeps, etc.) to
cargo each ... --once -- ...while preserving bespoke orchestration in specialized recipes. - Update tests, snapshots, docs, templates, and lockfile to reflect the new selector contract and
cargo-eachdependency.
File summaries
| File | Description |
|---|---|
| justfiles/anvil/impact.just | Emit tokenized cargo-each selectors (--none/--package name) and adjust include resolution. |
| justfiles/anvil/helpers.just | Document new selector-token capture pattern ($selection = @(& ... )). |
| justfiles/anvil/checks/udeps.just | Run udeps through cargo each @selection --once and add cargo-each prereqs. |
| justfiles/anvil/checks/semver-check.just | Consume selection token array and update empty-tier handling to --none. |
| justfiles/anvil/checks/mutants-diff.just | Delegate execution gating to cargo-each and add cargo-each prereqs. |
| justfiles/anvil/checks/msrv-test.just | Use cargo-each for affected selection and add cargo-each prereqs. |
| justfiles/anvil/checks/miri.just | Run miri through cargo-each selection. |
| justfiles/anvil/checks/miri-tree-borrows.just | Run tree-borrows miri through cargo-each selection. |
| justfiles/anvil/checks/miri-strict-provenance.just | Run strict-provenance miri through cargo-each selection. |
| justfiles/anvil/checks/miri-race-coverage.just | Run race-coverage miri through cargo-each selection. |
| justfiles/anvil/checks/loom.just | Update affected parsing to use selection tokens and --none. |
| justfiles/anvil/checks/llvm-cov.just | Update selection parsing to use bare names and --none. |
| justfiles/anvil/checks/license-headers.just | Gate workspace-wide tool via cargo-each selection. |
| justfiles/anvil/checks/fmt.just | Gate formatting via selection and delegate workspace iteration to cargo-each. |
| justfiles/anvil/checks/external-types.just | Replace manual metadata filtering/iteration with cargo-each --filter lib. |
| justfiles/anvil/checks/examples.just | Run build examples via cargo-each selection. |
| justfiles/anvil/checks/ensure-no-default-features.just | Gate tool via cargo-each selection and add cargo-each prereqs. |
| justfiles/anvil/checks/ensure-no-cyclic-deps.just | Gate tool via cargo-each selection and add cargo-each prereqs. |
| justfiles/anvil/checks/doc-test.just | Run doc tests via cargo-each selection. |
| justfiles/anvil/checks/doc-build.just | Run doc build via cargo-each selection. |
| justfiles/anvil/checks/clippy.just | Run clippy via cargo-each selection. |
| justfiles/anvil/checks/cargo-sort.just | Gate cargo-sort via cargo-each selection and add cargo-each prereqs. |
| justfiles/anvil/checks/cargo-hack.just | Run cargo-hack via cargo-each selection. |
| justfiles/anvil/checks/careful.just | Run cargo-careful via cargo-each selection and --none skipping. |
| justfiles/anvil/checks/bolero.just | Update affected selection parsing for bolero to use token array. |
| justfiles/anvil/checks/bench.just | Run bench via cargo-each selection. |
| crates/cargo-anvil/tests/snapshots/snapshots__local_only.snap | Update emitted justfile snapshot to the new selector-token contract. |
| crates/cargo-anvil/tests/recipe_contracts.rs | Update contracts for --none and tokenized selector output. |
| crates/cargo-anvil/tests/impact.rs | Update impact-behavior tests for --none and token-per-line include files. |
| crates/cargo-anvil/templates/justfiles/anvil/impact.just | Template: emit tokenized selectors and updated include logic. |
| crates/cargo-anvil/templates/justfiles/anvil/helpers.just | Template: document new selector-token capture pattern. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/udeps.just | Template: udeps delegates to cargo-each and includes prereqs. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/semver-check.just | Template: selection tokens + --none semantics. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/mutants-diff.just | Template: cargo-each delegation + prereqs. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/msrv-test.just | Template: cargo-each selection + prereqs. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/miri.just | Template: cargo-each selection. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/miri-tree-borrows.just | Template: cargo-each selection. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/miri-strict-provenance.just | Template: cargo-each selection. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/miri-race-coverage.just | Template: cargo-each selection. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/loom.just | Template: token-array parsing and --none handling. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/llvm-cov.just | Template: token-array parsing and --none handling. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/license-headers.just | Template: gate via cargo-each selection + prereqs. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/fmt.just | Template: gate + delegate workspace iteration to cargo-each. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/external-types.just | Template: use cargo-each --filter lib instead of manual iteration. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/examples.just | Template: cargo-each selection. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/ensure-no-default-features.just | Template: gate via cargo-each selection + prereqs. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/ensure-no-cyclic-deps.just | Template: gate via cargo-each selection + prereqs. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/doc-test.just | Template: cargo-each selection. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/doc-build.just | Template: cargo-each selection. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/clippy.just | Template: cargo-each selection. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/cargo-sort.just | Template: gate via cargo-each selection + prereqs. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/cargo-hack.just | Template: cargo-each selection. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/careful.just | Template: cargo-each selection + prereqs. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/bolero.just | Template: token-array parsing updates. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/bench.just | Template: cargo-each selection + prereqs. |
| crates/cargo-anvil/src/anvil/artifacts/justfile.rs | Update enforcement of “capture include tokens into $selection array” contract. |
| crates/cargo-anvil/docs/implementation.md | Document new “bare selector + cargo-each resolves versions” behavior. |
| crates/cargo-anvil/docs/design/local.md | Update design doc to reflect token-per-line include cache and cargo-each usage. |
| crates/cargo-anvil/docs/design/github.md | Update workflow design text from --skip to --none semantics. |
| crates/cargo-anvil/docs/design/checks.md | Update check scoping model to cargo-each selectors and --none. |
| crates/cargo-anvil/docs/design/ado.md | Update ADO design text from --skip to --none semantics. |
| .anvil.lock | Update catalog checksum and justfile checksums after regeneration. |
Review details
- Files reviewed: 63/64 changed files
- Comments generated: 2
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
_anvil-impact-include should be backward-compatible with legacy cached include file formats to avoid post-upgrade local failures when an old impact cache is reused.
Review details
Suppressed comments (2)
justfiles/anvil/impact.just:624
- anvil-impact-include now returns token-per-line selectors, but it will also happily return legacy cached include.txt values as a single string token (e.g. "--skip" or "--package name@ver --package ..." from older Anvil versions). That can break local runs after an update if an existing target/anvil/impact cache is treated as fresh, because cargo-each will receive an unsupported selector token.
To make upgrades robust, consider parsing the cache file in a backward-compatible way: map legacy "--skip" -> "--none", and split legacy one-line "--package name@ver ..." into tokens while stripping any @version qualifiers.
crates/cargo-anvil/templates/justfiles/anvil/impact.just:624
- Same as the generated justfiles/anvil/impact.just: anvil-impact-include should be backward-compatible with legacy cached include.txt formats ("--skip" and single-line "--package name@ver ..."), otherwise local runs can break after upgrading if an old target/anvil/impact cache is considered fresh.
Consider parsing the cache file in a backward-compatible way (map "--skip" -> "--none", split legacy one-line lists into tokens, and strip any @version qualifiers).
- Files reviewed: 63/64 changed files
- Comments generated: 0 new
- Review effort level: Lite
There was a problem hiding this comment.
🔵 Needs a closer look
The Unix fake cargo shim in crates/cargo-anvil/tests/impact.rs doesn’t correctly handle cargo +<toolchain> install --list, which can break prereq-validation paths and make affected tests unreliable.
Review details
Suppressed comments (3)
Previously missed (3) — in code that hasn't changed since the last review.
crates/cargo-anvil/tests/impact.rs:933
- On Unix, the fake
cargoshim only special-casesinstall --listwhen those are the first two argv elements. In this repo_anvil_stable_toolchain_argscan prefix commands with a+<toolchain>argument, so calls likecargo +1.95 install --listwon’t hit this branch and can make prereq-validation tests flaky/incorrect.
crates/cargo-anvil/templates/justfiles/anvil/checks/llvm-cov.just:153 - The gate-scoping comment still claims $pkg contains version-qualified selectors ("--package X@ver ..."), but this PR changed impact projection to emit tokenized "--package" + bare package-name pairs (and cargo-each handles version-qualification). This comment is now misleading about what $pkg actually holds.
justfiles/anvil/checks/llvm-cov.just:153 - The gate-scoping comment still claims $pkg contains version-qualified selectors ("--package X@ver ..."), but this PR changed impact projection to emit tokenized "--package" + bare package-name pairs (and cargo-each handles version-qualification). This comment is now misleading about what $pkg actually holds.
- Files reviewed: 63/64 changed files
- Comments generated: 0 new
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
The updated local design doc example inlines _anvil-impact-include into cargo each without fail-fast exit-code handling, which can mislead users into running checks with an invalid/partial selection.
Review details
Suppressed comments (1)
Previously missed (1) — in code that hasn't changed since the last review.
crates/cargo-anvil/docs/design/local.md:536
- The example pipelines
_anvil-impact-includeinline intocargo each, but that loses the ability to fail fast when_anvil-impact-includeexits non-zero (e.g., impact-format ambiguity/metadata failures). The check recipes in this PR capture the selector array first and exit on$LASTEXITCODEbefore invoking cargo-each; the docs should mirror that safe pattern.
- Files reviewed: 63/64 changed files
- Comments generated: 0 new
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> # Conflicts: # .anvil.lock
There was a problem hiding this comment.
🟡 Changes recommended
The updated design doc example in crates/cargo-anvil/docs/design/local.md diverges from the repository-enforced scoped-check contract (required $selection capture), risking misleading copy/paste guidance.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 63/64 changed files
- Comments generated: 1
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
It changes core impact-scoping and check execution behavior across many recipes/docs/tests, so a final human review is needed to validate end-to-end workflow expectations.
Review details
- Files reviewed: 63/64 changed files
- Comments generated: 0 new
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
Selector-token validation and its contract tests are inconsistent about allowing version-qualified name@version tokens where the documented selector grammar expects bare package names.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
Suppressed comments (1)
crates/cargo-anvil/tests/recipe_contracts.rs:1260
- This contract seeds the impact selector cache with
fixture@0.1.0, but the new selector-token format is documented/used elsewhere as bare workspace package names (the version qualification is meant to be resolved by cargo-each later). Using a version-qualified selector here makes the test less representative of real impact cache contents and can mask regressions in selector validation.
Suggest switching this seeded selector (and the expected argv substring) to the bare fixture name.
- Files reviewed: 68/70 changed files
- Comments generated: 1
- Review effort level: Lite
Inline impact selection for simple one-shot checks and remove cargo-each from recipes that already need retained selection state. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
It makes broad, cross-cutting changes to impact scoping semantics and CI/recipe orchestration across many checks and templates, warranting final human review.
Review details
- Files reviewed: 68/70 changed files
- Comments generated: 0 new
- Review effort level: Lite
Preserve parallel Miri execution while carrying tokenized, version-qualified impact selectors through cargo-each and direct Cargo recipes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Integrate Windows coverage response-file handling while preserving doctest filtering and version-qualified impact selectors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
doc-test reconstructs selectors as bare --package <name> which undermines the repo’s version-qualified selector contract and can reintroduce ambiguous Cargo package selection.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 62/64 changed files
- Comments generated: 1
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
It mixes a cargo-anvil 0.9.0 release/version bump into a broad refactor PR and also leaves a small but real gap in the documented “fail-closed” selector grammar validation.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 62/64 changed files
- Comments generated: 2
- Review effort level: Lite
There was a problem hiding this comment.
🔵 Needs a closer look
The selector-cache validation in _anvil-impact-include can still accept certain malformed name@version tokens (multiple @), weakening the intended fail-closed contract for ANVIL_IMPACT=consume.
Review details
Suppressed comments (1)
crates/cargo-anvil/templates/justfiles/anvil/impact.just:644
_anvil-impact-includevalidates cachedname@versionselectors by splitting on the first@, but it currently accepts specs containing multiple@characters (e.g.pkg@1.0@junk), since$parts[1]is not checked for@. This weakens the “fail closed on malformed cache” guarantee forANVIL_IMPACT=consume.
Consider rejecting any selector whose version part still contains @ so only a single name@version separator is accepted.
- Files reviewed: 62/64 changed files
- Comments generated: 0 new
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
There are still documentation contract mismatches (notably the clippy invocation and selector token examples) that should be corrected to keep the design docs aligned with the updated cargo-each-based recipes.
Review details
Suppressed comments (2)
Previously missed (2) — in code that hasn't changed since the last review.
crates/cargo-anvil/docs/design/checks.md:185
- This table entry for
clippystill documents a directcargo clippy --workspace ...invocation, but the checks were refactored to dispatch throughcargo each ... --once -- cargo ... clippy '{packages}' .... Updating this keeps the design doc aligned with the current check contract and avoids readers copying an invocation shape that no longer matches Anvil’s recipes.
crates/cargo-anvil/templates/justfiles/anvil/helpers.just:51 - The docs describe tier members as "--package", "A", "--package", "B", but the impact cache and
_anvil-impact-formatemit version-qualified specs (name@version) as the selection tokens. Using bare names here is misleading (and inconsistent with the rest of the impact-format documentation).
- Files reviewed: 62/64 changed files
- Comments generated: 0 new
- Review effort level: Lite
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🔵 Needs a closer look
It includes a cargo-anvil version bump that appears to conflict with the repo’s documented release process (release via scripts/release-crate.ps1 in a dedicated PR).
Review details
Suppressed comments (1)
crates/cargo-anvil/Cargo.toml:7
- This PR bumps
cargo-anvilto 0.9.0 inline with a large refactor. The repo’s documented release flow is to land the functional changes first, then create a separate release PR that runs./scripts/release-crate.ps1 <crate_name> [new_version]to bump the version (and changelog) from main (see README.md:68-86). Consider reverting the version bump here (and the associated lock/README/.anvil.lock updates) or splitting the release into a dedicated PR.
[package]
name = "cargo-anvil"
version = "0.9.0"
edition.workspace = true
- Files reviewed: 62/64 changed files
- Comments generated: 0 new
- Review effort level: Lite
Preserve injectable impact caches while retaining tokenized, fail-closed selectors. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
🟡 Changes recommended
A contract test in crates/cargo-anvil/tests/recipe_contracts.rs now uses duplicated, substring-based assertions that no longer verify the version-qualified impact selector contract.
Once you've addressed the issues Copilot identified, you can request another Copilot review.
Review details
- Files reviewed: 60/61 changed files
- Comments generated: 1
- Review effort level: Lite
| assert!( | ||
| commands.contains( | ||
| "+nightly-test miri test --all-features --tests --no-run --message-format=json-render-diagnostics --package fixture@0.1.0" | ||
| ), | ||
| commands | ||
| .contains("+nightly-test miri test --all-features --tests --no-run --message-format=json-render-diagnostics --package fixture"), | ||
| "default Miri target selection was not preserved:\n{commands}" | ||
| ); |
🤖 Adopts cargo-each where it makes cargo-anvil recipes materially more concise.
--workspace/--package/--noneselectors from the impact cache