fix(cargo-anvil): make stable toolchains deterministic - #109
fix(cargo-anvil): make stable toolchains deterministic#109martin-kolinek wants to merge 22 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.7%) 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 #109 +/- ##
========================================
- Coverage 99.9% 97.7% -2.3%
========================================
Files 135 286 +151
Lines 17470 62174 +44704
========================================
+ Hits 17469 60753 +43284
- Misses 1 1421 +1420
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:
|
Add a conditional Linux PR check when a selecting toolchain file differs from the workspace MSRV, with support for mapped internal toolchains. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Run affected-package tests under every declared root MSRV across the same GitHub and ADO platform matrices as ordinary PR tests. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Validate resolver diagnostics across stdout and stderr so the regression tests behave consistently across host PowerShell implementations. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Collapse PowerShell line wrapping before asserting resolver errors so the tests are portable across host terminal widths. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Assert stable resolver diagnostic fragments independently so PowerShell continuation markers do not make the tests host-dependent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Remove the globally exported resolved toolchain and route stable commands through private Just helpers. Keep explicit nightly and MSRV selection at each command site, and preserve current-checkout toolchain selection for impact baselines. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Reject incomplete internal mappings, accept member MSRVs satisfied by the root floor, and cover public and mapped MSRV provisioning branches. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Install the Just bootstrap before invoking private resolver recipes in GitHub Actions, preserving recipe-based selection without assuming Just is preinstalled on hosted runners. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Accept PowerShell's platform-specific diagnostic wrapping while still asserting every actionable part of the mapped-toolchain error. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f7996e6f-5c20-4d7a-b2f7-690af95e557e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f7996e6f-5c20-4d7a-b2f7-690af95e557e
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f7996e6f-5c20-4d7a-b2f7-690af95e557e
Select stable toolchain arguments lazily in Just so Cargo and Rust commands run directly. Keep setup behavior recipe-owned and remove the generated resolver script. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f7996e6f-5c20-4d7a-b2f7-690af95e557e
Rely on Just's normal lazy evaluation and derive the repository root from the selector working directory so the embedded PowerShell works on Unix and Windows. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f7996e6f-5c20-4d7a-b2f7-690af95e557e
Make stable toolchain preparation a shared setup prerequisite and evaluate the optional toolchain argument directly inside PowerShell recipes without host-specific shell invocation. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f7996e6f-5c20-4d7a-b2f7-690af95e557e
Delegate repository toolchain files to rustup, keep command-scoped explicit selection, and validate workspace MSRVs with the selected compiler. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Copilot-Session: f7996e6f-5c20-4d7a-b2f7-690af95e557e
There was a problem hiding this comment.
Pull request overview
This PR makes cargo-anvil’s “stable” toolchain selection deterministic (no longer inheriting whatever stable happens to be on a runner image), adds an explicit PR MSRV test group, and updates generated workflow/container assets plus design docs to reflect the new selection rules.
Changes:
- Introduce a stable-toolchain resolver that prefers
RUSTUP_TOOLCHAIN, then a rootrust-toolchain{.toml}, then root MSRV fromCargo.toml, and thread that selection through stable cargo/rust invocations. - Add
pr-msrvgroup (anvil-msrv-test) and wire it into local groups plus GitHub Actions/Azure Pipelines templates. - Update container identity inputs and design/docs to reflect the new deterministic selection and MSRV behavior.
Reviewed changes
Copilot reviewed 96 out of 97 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| justfiles/anvil/versions.just | Add _anvil_stable_toolchain_args selector used by stable commands. |
| justfiles/anvil/tools.just | Add stable resolver/install primitive; route stable cargo invocations through selected toolchain; add MSRV validation support. |
| justfiles/anvil/mod.just | Import new MSRV check/group. |
| justfiles/anvil/impact.just | Ensure impact snapshots/metadata run under the same selected stable toolchain. |
| justfiles/anvil/groups/pr-slow.just | Include pr-msrv in the local slow umbrella and setup/validate graphs. |
| justfiles/anvil/groups/pr-msrv.just | New group: runs MSRV tests. |
| justfiles/anvil/checks/spellcheck.just | Run spellcheck via selected stable toolchain. |
| justfiles/anvil/checks/semver-check.just | Run cargo metadata/semver-checks via selected stable toolchain. |
| justfiles/anvil/checks/readme-check.just | Run metadata/doc2readme via selected stable toolchain. |
| justfiles/anvil/checks/mutants-full.just | Run mutants via selected stable toolchain. |
| justfiles/anvil/checks/mutants-diff.just | Run mutants via selected stable toolchain. |
| justfiles/anvil/checks/msrv-test.just | New check: affected-package tests under declared MSRV. |
| justfiles/anvil/checks/loom.just | Run metadata/tests via selected stable toolchain; setup depends on stable provisioning. |
| justfiles/anvil/checks/llvm-cov.just | Run metadata/coverage-gate via selected stable toolchain. |
| justfiles/anvil/checks/license-headers.just | Run heather via selected stable toolchain. |
| justfiles/anvil/checks/external-types.just | Run metadata via selected stable toolchain. |
| justfiles/anvil/checks/examples.just | Run examples build via selected stable toolchain; setup depends on stable provisioning. |
| justfiles/anvil/checks/ensure-no-default-features.just | Run ensure-no-default-features via selected stable toolchain. |
| justfiles/anvil/checks/ensure-no-cyclic-deps.just | Run ensure-no-cyclic-deps via selected stable toolchain. |
| justfiles/anvil/checks/doc-test.just | Run doctests via selected stable toolchain; setup depends on stable provisioning. |
| justfiles/anvil/checks/doc-build.just | Run doc build via selected stable toolchain; setup depends on stable provisioning. |
| justfiles/anvil/checks/deny.just | Run deny via selected stable toolchain. |
| justfiles/anvil/checks/clippy.just | Run clippy via selected stable toolchain. |
| justfiles/anvil/checks/cargo-sort.just | Run cargo-sort via selected stable toolchain. |
| justfiles/anvil/checks/cargo-hack.just | Run cargo-hack via selected stable toolchain. |
| justfiles/anvil/checks/careful.just | Use explicit nightly toolchain for cargo clean in careful flow. |
| justfiles/anvil/checks/bolero.just | Run metadata via selected stable toolchain. |
| justfiles/anvil/checks/bench.just | Run benches via selected stable toolchain; setup depends on stable provisioning. |
| justfiles/anvil/checks/audit.just | Run audit via selected stable toolchain. |
| justfiles/anvil/checks/aprz.just | Run aprz via selected stable toolchain. |
| crates/cargo-anvil/tests/schemas.rs | Expect new anvil-pr-msrv recipe in emitted recipe list. |
| crates/cargo-anvil/tests/recipe_contracts.rs | Adjust fixtures/shelling to support stable-toolchain arg arrays and new resolver behavior. |
| crates/cargo-anvil/tests/impact.rs | Update impact tests for stable toolchain selection and add MSRV test coverage. |
| crates/cargo-anvil/tests/container_upgrade.rs | Ensure upgrade removes retired legacy resolver artifact. |
| crates/cargo-anvil/tests/container_customization.rs | Stabilize container customization tests by pinning RUSTUP_TOOLCHAIN in invocations. |
| crates/cargo-anvil/templates/justfiles/anvil/versions.just | Template mirror of stable toolchain selector. |
| crates/cargo-anvil/templates/justfiles/anvil/tools.just | Template mirror of stable resolver/provisioning changes. |
| crates/cargo-anvil/templates/justfiles/anvil/mod.just | Template mirror of new imports. |
| crates/cargo-anvil/templates/justfiles/anvil/impact.just | Template mirror of deterministic toolchain usage in impact. |
| crates/cargo-anvil/templates/justfiles/anvil/groups/pr-slow.just | Template mirror of pr-msrv wiring. |
| crates/cargo-anvil/templates/justfiles/anvil/groups/pr-msrv.just | New template group for MSRV tests. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/spellcheck.just | Template mirror: stable toolchain for spellcheck. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/semver-check.just | Template mirror: stable toolchain for semver-check. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/readme-check.just | Template mirror: stable toolchain for readme check. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/mutants-full.just | Template mirror: stable toolchain for mutants-full. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/mutants-diff.just | Template mirror: stable toolchain for mutants-diff. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/msrv-test.just | New template check for MSRV tests. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/loom.just | Template mirror: stable toolchain for loom + setup dependency update. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/llvm-cov.just | Template mirror: stable toolchain for llvm-cov metadata/gate. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/license-headers.just | Template mirror: stable toolchain for heather. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/external-types.just | Template mirror: stable toolchain for metadata. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/examples.just | Template mirror: stable toolchain for examples + setup dependency update. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/ensure-no-default-features.just | Template mirror: stable toolchain for ensure-no-default-features. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/ensure-no-cyclic-deps.just | Template mirror: stable toolchain for ensure-no-cyclic-deps. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/doc-test.just | Template mirror: stable toolchain for doc-test + setup dependency update. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/doc-build.just | Template mirror: stable toolchain for doc-build + setup dependency update. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/deny.just | Template mirror: stable toolchain for deny. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/clippy.just | Template mirror: stable toolchain for clippy. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/cargo-sort.just | Template mirror: stable toolchain for cargo-sort. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/cargo-hack.just | Template mirror: stable toolchain for cargo-hack. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/careful.just | Template mirror: explicit nightly toolchain for careful clean. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/bolero.just | Template mirror: stable toolchain for metadata. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/bench.just | Template mirror: stable toolchain for bench + setup dependency update. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/audit.just | Template mirror: stable toolchain for audit. |
| crates/cargo-anvil/templates/justfiles/anvil/checks/aprz.just | Template mirror: stable toolchain for aprz. |
| crates/cargo-anvil/templates/github/setup-action.yml | Bootstrap just before resolving stable rustc version; update cache key inputs. |
| crates/cargo-anvil/templates/github/pr-impl-workflow.yml | Add pr-msrv job matrix to reusable PR workflow. |
| crates/cargo-anvil/templates/anvil/container/image-id.sh | Include Cargo.toml + optional toolchain files as image identity inputs. |
| crates/cargo-anvil/templates/anvil/container/image-id.ps1 | Same as above for PowerShell. |
| crates/cargo-anvil/templates/anvil/container/Containerfile.dockerignore | Allow-list Cargo.toml and rust-toolchain. |
| crates/cargo-anvil/templates/anvil/container/Containerfile | Remove hard requirement for rust-toolchain.toml. |
| crates/cargo-anvil/templates/ado/steps/setup.yml | Bootstrap just + stable provisioning before capturing version; update cache key inputs. |
| crates/cargo-anvil/templates/ado/pr-stages.yml | Add pr_msrv stage parallel to other PR slow stages. |
| crates/cargo-anvil/src/run.rs | Register new pr-msrv ADO step in generated artifact list. |
| crates/cargo-anvil/src/lib.rs | Update crate docs for new toolchain/MSRV requirements and PR group topology. |
| crates/cargo-anvil/src/anvil/artifacts/mod.rs | Classify pr-msrv as impact-consuming. |
| crates/cargo-anvil/src/anvil/artifacts/github.rs | Add pr-msrv group; assert setup now uses stable version capture helper. |
| crates/cargo-anvil/src/anvil/artifacts/container.rs | Update container image-id fixtures/inputs and assertions for new contract. |
| crates/cargo-anvil/src/anvil/artifacts/ado.rs | Add pr-msrv group/stage wiring and setup ordering assertions. |
| crates/cargo-anvil/README.md | Regenerated README reflecting new requirements and group topology. |
| crates/cargo-anvil/docs/design/README.md | Update design overview: toolchain ownership/selection and group list. |
| crates/cargo-anvil/docs/design/local.md | Document deterministic stable selection, setup graph changes, and new pr-msrv. |
| crates/cargo-anvil/docs/design/github.md | Document GitHub workflow changes and deterministic stable provisioning. |
| crates/cargo-anvil/docs/design/containers.md | Update container contract and identity inputs for MSRV/toolchain selection. |
| crates/cargo-anvil/docs/design/checks.md | Add pr-msrv group + msrv-test check and document stable selection semantics. |
| crates/cargo-anvil/docs/design/ado.md | Document ADO stage topology including pr_msrv and stable provisioning behavior. |
| .github/workflows/anvil-pr-impl.yml | Add pr-msrv job to this repo’s workflow. |
| .github/actions/anvil-setup/action.yml | Bootstrap just before stable version capture; update cache key inputs. |
| .anvil/container/image-id.sh | Repo’s generated container identity script updated for new inputs. |
| .anvil/container/image-id.ps1 | Repo’s generated container identity script updated for new inputs. |
| .anvil/container/Containerfile.dockerignore | Repo’s generated dockerignore allow-list updated. |
| .anvil/container/Containerfile | Repo’s generated containerfile updated to remove toolchain.toml requirement. |
| .anvil.lock | Update catalog checksum + tracked file checksums after regeneration. |
Suppressed comments (2)
justfiles/anvil/tools.just:614
_install-componentalways runsrustup component add --toolchain $selectedStableToolchain ...for thedefaulttoolchain. If_anvil_stable_toolchain_argsever evaluates to an empty/multi-element array,$selectedStableToolchainstays$nulland this invocation becomes invalid (--toolchainwith a missing value).
crates/cargo-anvil/templates/justfiles/anvil/tools.just:614_install-componentalways runsrustup component add --toolchain $selectedStableToolchain ...for thedefaulttoolchain. If_anvil_stable_toolchain_argsever evaluates to an empty/multi-element array,$selectedStableToolchainstays$nulland this invocation becomes invalid (--toolchainwith a missing value) in generated trees.
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| exit 2 | ||
| } | ||
|
|
||
| $repoRoot = '{{justfile_directory()}}' |
| exit 2 | ||
| } | ||
|
|
||
| $repoRoot = '{{justfile_directory()}}' |
| # _install-tool: install a cargo subcommand at the catalog version, | ||
| # Resolve or prepare the selected stable compiler without globally exporting it. | ||
| [script("pwsh", "-NoProfile")] | ||
| _anvil-resolve-stable action="resolve": |
There was a problem hiding this comment.
Does this need to be so complicated and long? Feels like what we're doing should be a simple check for file existence and if it doesn't exist, pull a value from cargo metadata. Why does it need 350 lines of powershell?
There was a problem hiding this comment.
🤖 Simplified in e7c4bd3. Anvil no longer parses rust-toolchain(.toml) or replays its profile, components, and targets; rustup owns all of that natively. The resolver now checks for a root toolchain file and otherwise handles the MSRV fallback, setup, internal mapping, and workspace validation. The small root rust-version read remains only to bootstrap the explicit compiler needed to run cargo metadata without depending on an ambient default.
| # value globally into unrelated recipes or helpers. | ||
| [private] | ||
| _anvil_stable_toolchain_args := trim(''' | ||
| @(& { |
There was a problem hiding this comment.
Is there a way to ask cargo about this rather than trying to parse rust-toolchain/rust-toolchain.toml?
There was a problem hiding this comment.
🤖 Cargo can authoritatively resolve package rust_version values, but it does not own rust-toolchain(.toml)—rustup does. In e7c4bd3, repository toolchain files are therefore delegated to rustup show active-toolchain, while workspace compatibility comes from cargo +<root-msrv> metadata. We retain only the minimal root-manifest read needed to discover that bootstrap MSRV; asking Cargo for it first would require choosing an ambient compiler before the deterministic compiler is known.
| Pop-Location | ||
| } | ||
| $resolved = [string] $active | ||
| $sourceMarker = $resolved.LastIndexOf(' (') |
There was a problem hiding this comment.
🤖: Repository paths containing ( corrupt the resolved toolchain name, while paths containing [ or ] make toolchain resolution fail before it runs.
Split rustup show active-toolchain at the first ( marker, and use Push-Location -LiteralPath $RepoRoot at both resolver call sites.
rustup includes the toolchain-file path in its reason suffix. With a checkout such as repo (fork), LastIndexOf(' (') finds the delimiter inside that path and emits a garbage +toolchain argument, breaking every stable Cargo/Rust command. Separately, Push-Location $RepoRoot treats brackets as wildcards; this occurs here and in tools.just, so an existing checkout such as br[x] cannot be entered during command selection or setup. The current shim fixtures exercise spaces and apostrophes but neither boundary.
🤖 Fixes runner-dependent stable Rust selection in cargo-anvil and adds explicit MSRV testing.
What changed
RUSTUP_TOOLCHAIN, then a selecting rootrust-toolchain/rust-toolchain.toml, then the root MSRVANVIL_MSRV_TOOLCHAINAdopter migration
Ambient runner stable is no longer accepted. Adopters must provide one of:
[workspace.package].rust-versionor[package].rust-versionshared by every workspace packagerust-toolchainorrust-toolchain.tomlRUSTUP_TOOLCHAINWorkspaces with missing or heterogeneous package MSRVs cannot use MSRV fallback and must select a catalog toolchain explicitly. Internal builds can override public selection with
RUSTUP_TOOLCHAINand map the public MSRV test run to a provisioned compiler withANVIL_MSRV_TOOLCHAIN.Motivation
Oxidizer PR #698 passed the legacy Rust 1.96.1 job but failed Anvil on a Windows ARM runner that had inherited Rust 1.98.0 and its new Clippy lints. Stable checks should not change behavior based on runner image rollout timing.
Coverage executes the ordinary test suite on the catalog nightly. The dedicated
pr-msrvgroup runs in parallel and ensures that the same affected unit and integration tests continue to compile and pass on the minimum supported compiler across every supported host configuration.