ci(anvil): update to cargo-anvil 0.6.0 to fix semver-check - #718
ci(anvil): update to cargo-anvil 0.6.0 to fix semver-check#718Evgenii (Vaiz) wants to merge 5 commits into
Conversation
There was a problem hiding this comment.
Pull request overview
Updates the repository’s Anvil-managed CI/automation surface by regenerating workflows, composite actions, and just recipes using cargo-anvil 0.5.0, aligning tool pins (notably cargo-semver-checks) to restore functional semver checking on current stable Rust toolchains and improve reporting for inconclusive comparisons.
Changes:
- Regenerated Anvil-managed
justfiles/anvil/**recipes (tiers, tools, checks) and bumped catalog tool pins (includingcargo-semver-checks0.49.0). - Restructured GitHub Actions wiring to use a shared
anvil-run-groupaction + supplemental status reporting, and updated workflow/job permission boundaries. - Added a managed local container runner (
.anvil/container/**) andANVIL_RUNNERrouting for tier entry points; normalizedCargo.toml[lints]blocks into managed regions.
Reviewed changes
Copilot reviewed 95 out of 96 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| justfiles/anvil/versions.just | Updates Anvil tool version pins (incl. cargo-semver-checks). |
| justfiles/anvil/tools.just | Updates installer/prereq logic (pwsh -NoProfile, source prereqs). |
| justfiles/anvil/tiers.just | Routes tier entrypoints through the runner dispatcher. |
| justfiles/anvil/runner.just | Adds runner dispatch (native vs container) for tier commands. |
| justfiles/anvil/mod.just | Imports new container/runner entrypoints into Anvil tree. |
| justfiles/anvil/helpers.just | Hardens impact formatting/metadata parsing and error handling. |
| justfiles/anvil/groups/scheduled-test.just | Regen header/structure for scheduled test group. |
| justfiles/anvil/groups/scheduled-runtime-analysis.just | Regen header/structure for scheduled runtime-analysis group. |
| justfiles/anvil/groups/scheduled-exhaustive.just | Regen header/structure for scheduled exhaustive group. |
| justfiles/anvil/groups/scheduled-advisories.just | Regen header/structure for scheduled advisories group. |
| justfiles/anvil/groups/pr-test.just | Regen header/structure for PR test group. |
| justfiles/anvil/groups/pr-slow.just | Regen header/structure for PR slow group. |
| justfiles/anvil/groups/pr-runtime-analysis.just | Regen header/structure for PR runtime-analysis group. |
| justfiles/anvil/groups/pr-mutants.just | Regen header/structure for PR mutants group. |
| justfiles/anvil/groups/pr-fast.just | Adjusts pr-fast membership (drops anvil-aprz from fast group). |
| justfiles/anvil/container.just | Adds anvil-container recipe entrypoint for host/container runs. |
| justfiles/anvil/checks/udeps.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/spellcheck.just | Updates spellcheck setup flow (defers source deps check to installer). |
| justfiles/anvil/checks/semver-check.just | Uses new cargo-semver-checks exit-code semantics and improved reporting. |
| justfiles/anvil/checks/readme-check.just | Hardened metadata parsing and impact package validation. |
| justfiles/anvil/checks/pr-title.just | Expands title validation diagnostics; treats empty PR_TITLE as skip. |
| justfiles/anvil/checks/mutants-full.just | Adds explicit Windows ARM skip behavior for mutants-full. |
| justfiles/anvil/checks/mutants-diff.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/loom.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/llvm-cov.just | Refines coverage opt-out handling and windows-arm behavior. |
| justfiles/anvil/checks/license-headers.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/external-types.just | Hardened metadata parsing; improves failure diagnostics. |
| justfiles/anvil/checks/examples.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/ensure-no-default-features.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/ensure-no-cyclic-deps.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/doc-test.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/doc-build.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/deny.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/clippy.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/cargo-sort.just | Updates script shell flags and clarifies formatting rationale. |
| justfiles/anvil/checks/cargo-hack.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/careful.just | Changes sysroot identity tracking to hash the resolved executable. |
| justfiles/anvil/checks/bench.just | Updates script shell flags and comment wording. |
| justfiles/anvil/checks/audit.just | Updates script shell flags and regen header. |
| justfiles/anvil/checks/aprz.just | Updates token acquisition behavior (container-aware) and adds re-run guard. |
| justfile | Adds anvil_runner variable for tier routing (ANVIL_RUNNER). |
| crates/routerama/Cargo.toml | Moves [lints] into an Anvil-managed region. |
| crates/routerama_macros/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/routerama_build/Cargo.toml | Moves [lints] into an Anvil-managed region. |
| crates/rest_over_grpc/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/rest_over_grpc_tests/Cargo.toml | Moves [lints] into an Anvil-managed region. |
| crates/rest_over_grpc_examples/Cargo.toml | Moves [lints] into an Anvil-managed region. |
| crates/rallocator/Cargo.toml | Moves [lints] into an Anvil-managed region. |
| crates/rallocator_wire/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/rallocator_telemetry/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/rallocator_cli/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/observed/Cargo.toml | Moves [lints] into an Anvil-managed region. |
| crates/observed_utils/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/observed_testing/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/observed_macros/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/observed_macros_impl/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/internity/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/internity_macros/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/fetch_winhttp/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/fetch_winhttp_impl/Cargo.toml | Marks [lints] as Anvil-managed. |
| crates/allocation_hints/Cargo.toml | Marks [lints] as Anvil-managed. |
| constants.env | Bumps CARGO_SEMVER_CHECKS_VERSION to 0.49.0 for non-Anvil consumers. |
| .github/workflows/anvil-scheduled.yml | Adjusts permissions to allow issue publishing via called workflow. |
| .github/workflows/anvil-scheduled-impl.yml | Switches to anvil-run-group; adds publish-failure issue publisher job. |
| .github/workflows/anvil-pr.yml | Splits PR vs merge-queue callers; tightens permissions; adds inputs. |
| .github/workflows/anvil-pr-impl.yml | Adds base ref input handling; uses anvil-run-group; adds status publishing hooks. |
| .github/actions/anvil-setup/just-problem-matcher.json | Adds a Just problem matcher for clearer failing-recipe annotations. |
| .github/actions/anvil-setup/action.yml | Adds matcher registration; validates group input; adjusts shell invocation. |
| .github/actions/anvil-scheduled-test/action.yml | Removed in favor of shared anvil-run-group. |
| .github/actions/anvil-scheduled-runtime-analysis/action.yml | Removed in favor of shared anvil-run-group. |
| .github/actions/anvil-scheduled-exhaustive/action.yml | Removed in favor of shared anvil-run-group. |
| .github/actions/anvil-scheduled-advisories/action.yml | Removed in favor of shared anvil-run-group. |
| .github/actions/anvil-pr-test/action.yml | Removed in favor of shared anvil-run-group. |
| .github/actions/anvil-pr-runtime-analysis/action.yml | Removed in favor of shared anvil-run-group. |
| .github/actions/anvil-pr-mutants/action.yml | Removed in favor of shared anvil-run-group. |
| .github/actions/anvil-pr-fast/action.yml | Removed in favor of shared anvil-run-group. |
| .github/actions/anvil-impact/action.yml | Adds explicit .delta.toml usage and documentation clarifications. |
| .github/actions/anvil-run-group/action.yml | New shared action to run a group + capture failing recipe output. |
| .github/actions/anvil-report-status/action.yml | New action to publish/clear supplemental commit statuses per group/runner. |
| .gitattributes | Forces LF endings for *.sh scripts. |
| .delta.toml | Removes managed [delta] root-files block; leaves managed region empty. |
| .anvil/container/run-in-container.sh | Adds managed container driver (bash) for local reproducible runs. |
| .anvil/container/run-in-container.ps1 | Adds managed container driver (pwsh) for Windows local runs via WSL docker. |
| .anvil/container/README.md | Adds managed documentation for local container execution. |
| .anvil/container/image-id.sh | Adds managed image identity computation (bash). |
| .anvil/container/image-id.ps1 | Adds managed image identity computation (pwsh). |
| .anvil/container/entrypoint.sh | Adds managed container entrypoint for per-user Cargo home wiring. |
| .anvil/container/Containerfile.dockerignore | Adds allowlist-based build-context filtering for container image builds. |
| .anvil/container/Containerfile | Adds managed image build definition for anvil container environment. |
| .anvil.lock | Updates Anvil lockfile to cargo-anvil 0.5.0 and new managed file set. |
Suppressed comments (1)
.github/workflows/anvil-pr-impl.yml:158
- Same concern as above: this step is tag-pinned and the comment asserts immutability that Git tags don’t guarantee. Prefer pinning to the release commit SHA to prevent unexpected upstream changes.
uses: marocchino/sticky-pull-request-comment@v3.0.5 # immutable release, the tag cannot be moved
💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 95 out of 96 changed files in this pull request and generated no new comments.
Suppressed comments (5)
.github/workflows/anvil-pr-impl.yml:153
- This
uses: ...@v3.0.5line claims the tag is immutable (“cannot be moved”), but Git tags can be retargeted. If the intent is supply-chain immutability, pin the action to a commit SHA (as this repo does for many other actions) and keep the version in the comment.
- name: Upsert anvil-semver advisory
if: always() && github.event_name == 'pull_request' && matrix.os == 'linux' && github.event.pull_request.head.repo.full_name == github.repository && hashFiles('target/anvil/comments/semver.md') != ''
uses: marocchino/sticky-pull-request-comment@v3.0.5 # immutable release, the tag cannot be moved
with:
.github/workflows/anvil-pr-impl.yml:159
- Same issue as above: release tags (like
v3.0.5) are not guaranteed immutable and can be moved. If you’re relying on immutability, pin to a commit SHA and keep the human-readable version in the comment.
- name: Clear anvil-semver advisory
if: always() && github.event_name == 'pull_request' && matrix.os == 'linux' && github.event.pull_request.head.repo.full_name == github.repository && hashFiles('target/anvil/comments/semver.md') == ''
uses: marocchino/sticky-pull-request-comment@v3.0.5 # immutable release, the tag cannot be moved
with:
.github/workflows/anvil-pr-impl.yml:207
- This switches Codecov Action from a commit-SHA pin to a moving
v7.0.0tag while also claiming it’s immutable. If the goal is a reproducible/supply-chain-safe workflow, prefer pinning to a specific commit SHA and keepv7.0.0as a comment.
uses: codecov/codecov-action@v7.0.0 # immutable release, the tag cannot be moved
.github/workflows/anvil-scheduled-impl.yml:67
- Same supply-chain concern here:
@v7.0.0is a mutable ref (tags can be moved). If you want immutability, pin to the commit SHA and keep the version as a comment.
uses: codecov/codecov-action@v7.0.0 # immutable release, the tag cannot be moved
.github/actions/anvil-setup/action.yml:149
- This swaps a commit-SHA pin for a
v1.21.0tag and asserts the tag can’t be moved. Git tags can be retargeted; if the intent is reproducible/supply-chain-safe installs, pin to the action commit SHA and keep thev1.21.0label as a comment.
- name: Install cargo-binstall
uses: cargo-bins/cargo-binstall@v1.21.0 # immutable release, the tag cannot be moved
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #718 +/- ##
=======================================
Coverage 100.0% 100.0%
=======================================
Files 587 587
Lines 63002 63002
=======================================
Hits 63002 63002
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:
|
anvil pins third-party actions two ways: by tag where the publisher has enabled GitHub immutable releases, and by commit SHA everywhere else with the version in a trailing comment. The rule was applied consistently but written down nowhere, so from the generated output alone the tag pins look like an inconsistency rather than a decision. That gap has a measurable cost. On microsoft/oxidizer#718 an automated reviewer flagged the tag pins four times in one review, once per pinned action, each time recommending a revert to SHA pinning on the grounds that Git tags are movable. The general rule is correct; it just does not apply to a tag held by an immutable release. Without the policy recorded anywhere, the same objection recurs on every adopting repo. Add an "Action pinning" subsection to the GitHub backend design under Security, covering what an immutable release actually guarantees, why that makes a tag an acceptable pin, and the fact that immutability is a property of one published release rather than a standing guarantee about the publisher -- so a bump must re-verify it and fall back to a SHA when the check fails. Documentation only; no template, workflow or behaviour changes. The five tag-pinned actions were re-checked while writing this and all report `immutable: true`: codecov/codecov-action v7.0.0, marocchino/sticky-pull-request-comment v3.0.5, cargo-bins/cargo-binstall v1.21.0, taiki-e/install-action v2.81.8 and github/codeql-action v4.37.7. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Regenerates the anvil-managed check tree from cargo-anvil 0.5.0 (was
0.3.0) and bumps CARGO_SEMVER_CHECKS_VERSION to match.
anvil-semver-check has been non-functional repo-wide. The recipe
installs the pin from justfiles/anvil/versions.just, which was
cargo-semver-checks 0.46.0 (rustdoc JSON v55/v56/v57), while the
recipe builds docs with the runner default stable toolchain, now Rust
1.98, whose rustdoc emits v60. Every library crate aborted with
"unsupported rustdoc format v60", and because the recipe is advisory
each tool crash was collected as a finding and posted as a sticky
"Potential breaking changes detected" comment. The 0.5.0 catalog pins
0.49.0, which reads v56/v57/v60.
The 0.5.0 semver-check recipe also separates the two outcomes: exit
100 (real deny-level findings) renders under "Potential breaking
changes", exit 101 (an unbuildable or missing baseline) under
"Inconclusive comparisons", so a broken tool no longer presents as
breaking-change output.
constants.env is not anvil-managed and is bumped by hand from 0.48.0
to 0.49.0 so the main.yml semver job and scripts/release-packages.ps1
use the same version the recipes install.
Two things needed manual resolution:
* cargo-anvil 0.5.0 appends an anvil-lints managed region without
detecting an existing unmanaged [lints] table, producing a duplicate
table in the 20 crates that had one. cargo rejects that outright
("duplicate key ... [lints]"), so the pre-existing block is removed
in favour of the managed region. Both are `workspace = true`, so
this is not a lint behaviour change.
* The anvil-delta managed region no longer carries `[delta]
root-files`. This repo's own top-level trip_wire_patterns already
lists Cargo.lock, Cargo.toml and rust-toolchain.toml, so impact
scoping is unchanged.
Six recipes carry deliberate repository-specific edits (fmt, bolero
and the four miri recipes, including miri's parallel artifact runner).
cargo-anvil left them alone and wrote .anvil-proposed sidecars; those
are not adopted here and are not committed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The 0.5.0 catalog runs every pwsh recipe as [script("pwsh",
"-NoProfile")]. The six recipes carrying repository-specific edits --
fmt, bolero, and the four miri recipes -- were left untouched by the
regeneration, so they kept the old [script("pwsh")] form. That left 46
recipes loading no profile and 7 script blocks loading the invoking
user's PowerShell profile.
A profile can change PATH, aliases, $ErrorActionPreference and output
encoding, so the inconsistency means these six checks can behave
differently from every other check on the same machine, and
differently from CI. It also costs profile load time on each
invocation.
This takes only the interpreter flag from the proposed templates. The
recipe bodies stay as they are: miri's parallel artifact runner is
deliberate (#706), and fmt and bolero carry their own repository
customizations.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
cargo-anvil 0.6.0 (2026-09-02) supersedes the 0.5.0 regeneration this branch started from. Its catalog pins cargo-semver-checks 0.50.0, which reads rustdoc JSON v57, v60 and v61 - covering the MSRV (1.95), the pinned RUST_LATEST (1.96.1) and the runner default stable (1.98) that broke the check in the first place. The 0.6.0 catalog also: * Replaces the job-output impact plumbing with an `anvil-impact` artifact that each group job downloads into target/anvil/impact, so scoped checks read the same cache as a local run. * Adds an MSRV test check and a pr-msrv group. * Replaces the .anvil/container script set with a generated Dockerfile and drops runner.just and the anvil-runner region. * Bumps cargo-deny 0.20.2, cargo-doc2readme 0.7.3, cargo-llvm-cov 0.9.0, cargo-mutants 27.1.0 and cargo-nextest 0.9.143. constants.env is not anvil-managed; CARGO_SEMVER_CHECKS_VERSION is bumped by hand to 0.50.0 so the workflow job and release-packages.ps1 install what the recipes install. The six customized recipes (fmt, bolero, four miri) were skipped again and keep the -NoProfile interpreter flag cherry-picked earlier. `cargo anvil --dry-run` reports zero pending writes, cargo metadata succeeds and just --list parses the tree. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
a434f92 to
703e662
Compare
There was a problem hiding this comment.
🔵 Needs a closer look
Several repository-specific Just recipes still rely on ANVIL_INCLUDE_* env vars, but the regenerated CI now scopes via the downloaded target/anvil/impact cache, risking unintended full-workspace runs and loss of impact scoping.
Review details
Suppressed comments (3)
justfiles/anvil/checks/miri.just:33
_anvil-miri-teststill depends onANVIL_INCLUDE_AFFECTEDfor scoping, but the regenerated workflows now use the downloadedtarget/anvil/impactcache (and setANVIL_IMPACT=consume) instead of exportingANVIL_INCLUDE_*. With the env var unset, this will default to--workspace, undermining PR-tier impact scoping and potentially making runtime-analysis runs much larger than intended. Consider depending onanvil-impactand, whenANVIL_INCLUDE_AFFECTEDisn’t already provided, populating it from_anvil-impact-include affected.
justfiles/anvil/checks/bolero.just:43anvil-bolerostill relies onANVIL_INCLUDE_AFFECTEDfor impact scoping, but the updated workflows now scope via the downloadedtarget/anvil/impactcache and do not populateANVIL_INCLUDE_*. WithANVIL_INCLUDE_AFFECTEDunset, this falls back to--workspaceand can unintentionally turn the PR-tier bolero run into a full-workspace run. Prefer depending onanvil-impactand deriving the include list via_anvil-impact-include affected.
justfiles/anvil/checks/fmt.just:21- This recipe still gates on
ANVIL_INCLUDE_MODIFIED == "--skip", but the regenerated CI flow now scopes via thetarget/anvil/impactcache +ANVIL_IMPACTand does not setANVIL_INCLUDE_*. As a result,anvil-fmtwill never observe the skip sentinel and will always run. Consider depending onanvil-impactand reading the scope via_anvil-impact-include modifiedto preserve the modified-tier short-circuit.
- Files reviewed: 90/91 changed files
- Comments generated: 0 new
- Review effort level: Lite
cargo-anvil 0.6.0 bumps the pinned cargo-doc2readme from 0.7.2 to 0.7.3, which fixes the docs.rs link builder to use the dependency's package name instead of its lib name. Three crates linked dependencies whose package name and lib name differ, so their checked-in READMEs no longer matched what the pinned generator produces and `anvil-readme-check` failed on all four Fast Checks runners: seatbelt tower_service -> tower-service rest_over_grpc tower_service -> tower-service http_extensions http_body -> http-body Regenerated with the pinned 0.7.3 and the workspace crates/README.j2 template; the only changes are those docs.rs URLs and the embedded dependency-info blob.
|
Answering the "Needs a closer look" review body from 2026-09-03 (the three suppressed comments on Verified against the tree at The cause is that these six recipes are repository-customized forks. They carry the older Resolution direction: the right fix is to adopt cargo-anvil's proposals and drop the local forks, because this PR's whole purpose is to consume anvil's generated output rather than maintain repository-specific variants of it. I am not doing that in this commit, because it is not mechanical: the customized Two related notes for anyone reading this thread. First, the |
`constants.env` feeds the pre-anvil `main` workflow, whose `static-analysis` job installs cargo-doc2readme and runs its own README check. cargo-anvil 0.6.0 pins 0.7.3 in `justfiles/anvil/versions.just`, but `constants.env` still said 0.7.2, so the two workflows disagreed about the generator for the same checked-in READMEs. That drift became visible once the READMEs were regenerated in ebf327a: `anvil-readme-check` went green under 0.7.3 while `static-analysis` failed on all four runners under 0.7.2 with the mirror-image error ERROR: Readme links to incompatible version of dependency `tower_service' (0.7.2 wants the lib name `tower_service`, 0.7.3 the package name `tower-service`). Only one of the two can be right for a single checked-in README, and it has to be the version anvil pins. This mirrors what the PR already does for CARGO_SEMVER_CHECKS_VERSION: when anvil bumps a tool pin, the hand-written constants file has to follow so the non-anvil consumers stay in step. Only the doc2readme pin is bumped here -- cargo-deny, cargo-llvm-cov, cargo-mutants, cargo-nextest and cargo-spellcheck also drift between the two files but nothing currently fails on them, so they are left alone rather than bumped speculatively.
`anvil-msrv-test` ran `cargo test --all-targets`. That flag expands to
`--lib --bins --tests --benches --examples`, so the recipe built AND
EXECUTED every bench target as part of the minimum-version check.
A bench declared `harness = false` delegates its run to a separate driver
binary -- criterion's, or a profiler runner such as `gungraun-runner`
driving Valgrind. `anvil-msrv-test-setup` installs only `cargo-delta` and
the MSRV toolchain, so that driver is never present and the group fails on
a prerequisite it does not declare:
--> Error in ae_basic_operations_cg: Failed to run benchmarks:
No such file or directory (os error 2).
Is gungraun-runner installed and gungraun-runner in your $PATH?
error: recipe `anvil-msrv-test` failed with exit code 1
That failure carries no minimum-version signal. An MSRV check exists to
prove the affected packages still compile and their tests still pass under
the declared minimum compiler; running benchmark harnesses is not part of
that, and it breaks the check for any adopter with a `harness = false`
bench. Observed on microsoft/oxidizer#718 (linux and linux-arm legs).
Use `--tests` instead. Chosen over the literally-equivalent
`--lib --bins --tests` because `--lib` errors with "no library targets
found" on a bin-only affected package under impact scoping -- the same
reason `anvil-miri` already selects `--tests`, documented in `miri.just`.
`--tests` selects exactly the targets carrying `test = true`: lib unit
tests, bin unit tests and integration tests.
A compile-only `--all-targets --no-run` pass was considered and rejected.
Benches and examples are dev-only targets that no consumer compiles, so
they do not constrain the crate's real MSRV, and the repository already
covers "do they still build" without running them: `anvil-bench` is
`cargo bench --no-run` and `anvil-examples` is `cargo build --examples`.
Adding the pass would double MSRV build time on the PR critical path for
a signal already owned elsewhere. This change makes `msrv-test` consistent
with that existing repository-wide policy.
No doctest coverage is lost: `--all-targets` suppresses doctests as well,
and `anvil-doc-test` owns them.
`msrv-test.just` was the only template with `cargo test --all-targets`.
`clippy.just` and `udeps.just` also pass `--all-targets`, but to `cargo
clippy` and `cargo udeps`, which compile without executing; both are left
as they are. `anvil-llvm-cov` and the other nextest paths are untouched.
The `impact.rs` contract test pinned the old argv; it now pins the new one
and additionally asserts that neither `--all-targets` nor `--benches` ever
reaches the MSRV invocations, so a regression fails loudly rather than
silently re-enabling bench execution.
Design doc, README and the mirrored lib.rs table updated to match; the
three emitted-tree snapshots re-recorded and reviewed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The generated workflows carried this comment at every tag-pinned action:
uses: codecov/codecov-action@v7.0.0 # immutable release, the tag cannot be moved
The claim is true for these specific pins -- GitHub's immutable-releases
feature does lock the tag to a commit, and the REST API reports
`"immutable": true` for each of them. But the sentence asserts a property
of the TAG, and read on its own it looks like a general claim that Git
tags are stable, which is false and is exactly the belief SHA-pinning
exists to defend against.
Read that way it is also self-undermining: if tags could not be moved,
the SHA pins on `actions/checkout` and `actions/download-artifact` in the
same file would be pointless. On microsoft/oxidizer#718 this produced four
separate automated-reviewer findings that a human had to rebut one at a
time.
Reword to name the mechanism the pin depends on instead:
# pinned by tag: this release is an immutable release (GitHub locks the tag to a commit)
Same length class, one line, and it no longer generalises: it says why
THIS pin is safe rather than what tags are. Applied to all five sites --
`cargo-bins/cargo-binstall` in setup-action.yml, `codecov/codecov-action`
in both pr- and scheduled-impl-workflow.yml, and both
`marocchino/sticky-pull-request-comment` uses in pr-impl-workflow.yml.
`docs/design/github.md` reproduces both the comment and a sample step, so
both copies are updated to keep the doc and the templates from drifting,
plus a sentence recording why the comment names a mechanism rather than
asserting tag stability. The "Action pinning" section already explained
that immutability is per-release and must be re-confirmed on a version
bump; added one sentence stating that `actions/checkout` and
`actions/download-artifact` stay SHA-pinned because immutable releases are
opt-in per publisher and theirs have not enabled it -- not because those
actions are less trusted.
Behaviour is unchanged: comments only, same action versions.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
`anvil-msrv-test` ran `cargo test --all-targets`. That flag expands to `--lib --bins --tests --benches --examples`, so the recipe built AND EXECUTED every bench target as part of the minimum-version check.
A bench declared `harness = false` delegates its run to a separate driver binary -- criterion's, or a profiler runner such as `gungraun-runner` driving Valgrind. `anvil-msrv-test-setup` installs only `cargo-delta` and the MSRV toolchain, so that driver is never present and the group fails on a prerequisite it does not declare:
--> Error in ae_basic_operations_cg: Failed to run benchmarks:
No such file or directory (os error 2).
Is gungraun-runner installed and gungraun-runner in your $PATH?
error: recipe `anvil-msrv-test` failed with exit code 1
That failure carries no minimum-version signal. An MSRV check exists to prove the affected packages still compile and their tests still pass under the declared minimum compiler; running benchmark harnesses is not part of that, and it breaks the check for any adopter with a `harness = false` bench. Observed on microsoft/oxidizer#718 (linux and linux-arm legs).
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
🤖 Clawpilot here! Posted automatically by Clawpilot (an AI agent), not by a human. Please verify before acting.
Fixes AB#7802687.
Problem
anvil-semver-checkhas been non-functional repo-wide. Every library crate aborts with:The recipe installs the pin from
justfiles/anvil/versions.just, which wascargo-semver-checks0.46.0 (rustdoc JSON v55/v56/v57). The recipe does not pin a toolchain for doc building, so it uses the runner default stable — now Rust 1.98, whose rustdoc emits v60. The tool aborts while parsing the JSON it just produced.Because the recipe is advisory, the crash was never surfaced as a failure. Each tool error was collected as a finding and posted as a sticky ":warning: Potential breaking changes detected" comment listing ~21 crates. Net effect: SemVer checking has been off across the workspace since the runner rolled to 1.98, and every PR carried a misleading breaking-change warning. Last observed on #715 (2026-08-31), also on #712 and #704.
#709 fixed this by editing the pin directly and was closed unmerged, because
versions.justis anvil-generated and a repository-local edit stops it receiving automatic updates. This PR takes the sanctioned route instead.Change
Regenerate the anvil-managed tree with
cargo anvilfrom cargo-anvil 0.6.0 (2026-09-02; previously 0.3.0, #596, 2026-07-24). The 0.6.0 catalog pinscargo-semver-checks0.50.0, which reads rustdoc JSON v57, v60 and v61.constants.envis not anvil-managed and is bumped by hand from 0.48.0 to 0.50.0, so themain.ymlsemverjob andscripts/release-packages.ps1install the same version the recipes do. That path pinsRUST_LATEST=1.96.1, which emits v57, so it was never broken — but 0.48.0 reads only v55/v56/v57, so a developer runningrelease-packages.ps1on current stable would hit the identical error locally.Compatibility
rustdoc JSON
format_versionagainst the toolchains in play:RUST_MSRV)RUST_LATEST)0.50.0 drops v55 and v56, both of which correspond to a rustc below the MSRV. Its install MSRV is Rust 1.93, below this repo's 1.95.
What else the 0.6.0 catalog brings
impact-linux/impact-windowsjobs no longer exportinclude_modified/include_affected/include_requiredas job outputs threaded into every group. They upload ananvil-impact-<os>artifact; each group job downloads it intotarget/anvil/impactand passesimpact_mode: consume, so scoped checks read the same cache a local run reads. The impact jobs also droplfs: true— they only touch paths and dependency metadata. The Codecov upload now gates onhashFiles(...)instead of a job output.justfiles/anvil/checks/msrv-test.justplus apr-msrvgroup, wired intoanvil-pr-impl.ymlacross the four legs..anvil/containerscript set (Containerfile,entrypoint.sh,image-id.*,run-in-container.*,README.md) is replaced by a single generatedDockerfile+.dockerignore.justfiles/anvil/runner.justand theanvil-runnerregion in the rootjustfileare removed, andcontainer.justbecomes animport?so the documentedwithout_artifactopt-out cannot break Justfile parsing.cargo-eachpin.semver-check.juststill separates exit 100 (completed check, deny-level findings) from exit 101 (check could not complete), rendering "Potential breaking changes" and "Inconclusive comparisons" under separate headings — so a broken tool no longer presents as breaking-change output. That was the third follow-up on fix(ci): bump cargo-semver-checks to 0.50.0 for rustdoc JSON v60 #709 and the third item on the work item.Two things that needed manual resolution
Duplicate
[lints]table. cargo-anvil appends ananvil-lintsmanaged region without detecting an existing unmanaged[lints]table. 20 crates had one, so regeneration produced two[lints]tables in each and cargo rejected the workspace outright. The pre-existing block is removed in favour of the managed region; both areworkspace = true, so this is not a lint behaviour change. Worth reporting upstream againstmicrosoft/ox-tools.anvil-deltaregion. The managed region no longer carries[delta] root-files = ["Cargo.lock", "Cargo.toml", "rust-toolchain.toml"], and cargo-anvil reports that it left the region empty because this repo defines top-leveltrip_wire_patterns. Those patterns already list all three files, so impact scoping is unchanged.Not adopted
Six recipes carry deliberate repository-specific edits:
fmt,bolero, and the fourmirirecipes — including miri's ~200-line parallel artifact runner (_anvil-miri-test, #706). cargo-anvil declined to overwrite them and wrote.anvil-proposedsidecars, which are not committed. They keep the[script("pwsh", "-NoProfile")]interpreter flag cherry-picked from the 0.5.0 sidecars, so all 53 script blocks in the tree are consistent and none load the invoking user's PowerShell profile.The proposed
bolero.juststill rewrites target discovery — per-packagecargo bolero listcalls, discovery failures raised as errors rather than swallowed as "no targets", and--releaseprofiles. Those look substantive rather than cosmetic and should be decided by someone who knows the bolero setup, not inside a CI-infra PR.Verification
cargo anvil --dry-runafter the change reports 133 unchanged items and zero pending writes, so the tree is fully in sync with the 0.6.0 catalog.cargo metadata --no-deps --lockedsucceeds.just --listparses the regenerated recipe tree.mainat c6addf0, which picked up the newthread_aware_corecrate; it already carries the managed lints region and needed no change..rsfiles are touched, so formatting and lint output cannot change.The workflow restructure — the impact artifact hand-off and the new
pr-msrvgroup — can only really be validated by CI on this PR.CI status notes (appended automatically by Clawpilot, an AI agent — please verify)
Fixed:
anvil-readme-checkon all four Fast Checks runnersThis was not a cargo-anvil defect. The recipe reported
error: recipe _anvil-readme failed with exit code 1immediately after anINFO: Readme is up to dateline, which looked like a success message paired with a non-zero exit, but the recipe iterates every eligible crate and exits 1 at the end if any crate failed. The "up to date" line was simply the last crate in the loop. Three earlier crates had genuinely failed:seatbeltReadme links to incompatible version of dependency 'tower-service'http_extensionsReadme links to incompatible version of dependency 'http-body'rest_over_grpcReadme links to incompatible version of dependency 'tower-service'Root cause: cargo-anvil 0.6.0 bumps the pinned
cargo-doc2readmefrom 0.7.2 to 0.7.3, and 0.7.3 builds docs.rs URLs from the dependency's package name rather than its lib name. The three crates above are the only ones in the workspace that link a dependency whose package name and lib name differ, so only their checked-in READMEs went stale. Regenerating them with the pinned 0.7.3 and the workspacecrates/README.j2template is the fix; the diff is limited to those docs.rs URLs and the embedded dependency-info blob.just anvil-readme-checknow passes over the whole workspace locally.Open, upstream:
anvil-msrv-testruns benchmark harnessesPR Job / Check Group: MSRV Testsfails on linux and linux-arm with:justfiles/anvil/checks/msrv-test.justandjustfiles/anvil/groups/pr-msrv.justare both added by this PR — the MSRV group is new in cargo-anvil 0.6.0. The generated recipe runscargo +$msrv test @pkg --all-targets --all-features --locked, and--all-targetsincludes--benches, socargo testbuilds and executes every bench target. This workspace has Callgrind benches built withharness = falsethat hand their work to a separategungraun-runnerbinary, which theanvil-pr-msrv-setupdependency chain does not install (it installs onlycargo-deltaand the MSRV toolchain). No other anvil check hits this, because the repository's actual test path isanvil-llvm-cov, which usescargo nextest runand therefore does not execute bench harnesses.This looks like an upstream cargo-anvil defect rather than something to patch here. An MSRV check exists to prove the workspace still compiles and its tests pass under the declared minimum toolchain; executing benchmark harnesses is not part of that, and it drags in profiler prerequisites (here
gungraun-runnerplus Valgrind) that the group never declares. Suggested upstream fix, in preference order:--lib --bins --testsinstead of--all-targets.--all-targetsbut add--no-runfor the bench portion, so bench targets are compiled (which is the MSRV-relevant signal) but never executed.Deliberately not doing here, per this PR's scope: adding a
gungraun-runnerinstall to the generatedpr-msrvsetup, or excludingarty_executorlocally. Both would be repository-specific edits to cargo-anvil's generated output, which is the failure mode this adoption is meant to avoid.Note that this PR is an unusually harsh test of the new group: it touches every crate's
Cargo.tomlto introduce the anvil-managed[lints]region, so impact analysis marks the entire workspace affected and the MSRV group runs everything, benches included. On an ordinary PR the failure would appear only when a bench-carrying crate is in the affected set.Open: six customized recipes lost their impact scoping
ANVIL_INCLUDE_AFFECTED/ANVIL_INCLUDE_MODIFIEDare no longer exported by anything under.github/**, but six repository-customized recipes still read them:miri.just,miri-tree-borrows.just,miri-strict-provenance.just,miri-race-coverage.just,bolero.justandfmt.just. Those recipes therefore fall back to--workspace, andanvil-fmtnever sees its--skipshort-circuit. cargo-anvil 0.6.0 detected the drift and wrote a.anvil-proposedsibling for each. Adopting those proposals is the correct resolution, but it is not mechanical — the customizedmiri.justis 256 lines against a 57-line proposal — so it needs a human decision about which repository-specific logic moves upstream. Tracked in the discussion thread on this PR.Follow-on:
constants.envhad to follow anvil's cargo-doc2readme pinRegenerating the READMEs in
ebf327acturnedanvil-readme-checkgreen on all four Fast Checks runners but brokestatic-analysison all four runners of the pre-anvilmainworkflow, with the mirror image of the original error:Note the underscore.
.github/workflows/main.ymlinstalls cargo-doc2readme fromCARGO_DOC2README_VERSIONinconstants.env, which still said0.7.2, whilejustfiles/anvil/versions.justpins0.7.3. The two workflows were therefore checking the same checked-in READMEs with two generators that disagree about whether a docs.rs URL uses the dependency's lib name (tower_service, 0.7.2) or its package name (tower-service, 0.7.3). Only one of the two can be right for a single file, and it has to be the version anvil pins.Fixed in
b6fff7eaby bumpingCARGO_DOC2README_VERSIONto0.7.3. This is the same move this PR already makes forCARGO_SEMVER_CHECKS_VERSION: when anvil bumps a tool pin, the hand-written constants file has to follow so the non-anvil consumers stay in step.For the record,
constants.envandjustfiles/anvil/versions.juststill disagree on five other tools —cargo-deny(0.19.8 vs 0.20.2),cargo-llvm-cov(0.8.7 vs 0.9.0),cargo-mutants(27.0.0 vs 27.1.0),cargo-nextest(0.9.137 vs 0.9.143) andcargo-spellcheck(0.15.1 vs 0.15.7). Nothing currently fails on any of them, so they are deliberately left alone here rather than bumped speculatively; they are worth reconciling when the pre-anvilmainworkflow is retired.