From 32575ffdec9e4015c2b8967025fae36204a52c40 Mon Sep 17 00:00:00 2001 From: Vaiz <4908982+Vaiz@users.noreply.github.com> Date: Tue, 1 Sep 2026 11:23:04 +0100 Subject: [PATCH 1/3] docs(anvil): document the action pinning policy 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> --- crates/cargo-anvil/docs/design/github.md | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/crates/cargo-anvil/docs/design/github.md b/crates/cargo-anvil/docs/design/github.md index ec9fe6963..19c29231c 100644 --- a/crates/cargo-anvil/docs/design/github.md +++ b/crates/cargo-anvil/docs/design/github.md @@ -901,6 +901,39 @@ Recommended root workflow shape: - All cargo-tool installs done by the catalog setup recipes use `--locked` (with `cargo install` or `cargo binstall` depending on `installer`). +### Action pinning + +Third-party actions are pinned one of two ways, and the split is deliberate rather +than inconsistent. + +Actions whose publisher has enabled GitHub [immutable releases][immutable] are pinned +by tag — `codecov/codecov-action@v7.0.0`, +`marocchino/sticky-pull-request-comment@v3.0.5`, `cargo-bins/cargo-binstall@v1.21.0`. +An immutable release locks its Git tag to one commit: the tag cannot be moved, and +cannot be deleted while the release exists. The tag name cannot be reused even after +the repository is deleted and recreated, and publishing generates a release +attestation covering the tag, commit SHA and assets. The tag is a stable identifier +under those rules, and unlike a SHA it stays readable in the diff when the pin is +bumped. Generated files carry a +`# immutable release, the tag cannot be moved` comment at each such pin, so the reason +a tag appears where a SHA is otherwise expected is visible at the use site. + +Every other action is pinned by commit SHA with the version in a trailing comment, for +example `actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1`. + +Immutability is a property of one published release, not a standing guarantee about +the publisher. When bumping a tag-pinned action, confirm the new release still reports +it: + +```console +$ gh api repos/codecov/codecov-action/releases/tags/v7.0.0 --jq .immutable +true +``` + +If that returns `false`, or the release is missing, pin the commit SHA instead. + +[immutable]: https://docs.github.com/en/code-security/concepts/supply-chain-security/immutable-releases + ## 10. Coverage upload After `pr-test` (and `scheduled-test`) runs the `anvil-llvm-cov` recipe, the reusable From acb69cc68cdc5af8560ad6e11325e69a8a740556 Mon Sep 17 00:00:00 2001 From: Vaiz <4908982+Vaiz@users.noreply.github.com> Date: Tue, 1 Sep 2026 12:17:43 +0100 Subject: [PATCH 2/3] docs(anvil): clarify pinning wording and tag-pin list Address review feedback on the new "Action pinning" section: fix the "pinned one of two ways" grammar, and make clear the three tag-pinned actions are the current generated-workflow set rather than an exhaustive list, since a repository's own workflows apply the same rule to their own actions. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- crates/cargo-anvil/docs/design/github.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/crates/cargo-anvil/docs/design/github.md b/crates/cargo-anvil/docs/design/github.md index 19c29231c..d216e6c38 100644 --- a/crates/cargo-anvil/docs/design/github.md +++ b/crates/cargo-anvil/docs/design/github.md @@ -903,12 +903,14 @@ Recommended root workflow shape: ### Action pinning -Third-party actions are pinned one of two ways, and the split is deliberate rather +Third-party actions are pinned in one of two ways, and the split is deliberate rather than inconsistent. Actions whose publisher has enabled GitHub [immutable releases][immutable] are pinned -by tag — `codecov/codecov-action@v7.0.0`, -`marocchino/sticky-pull-request-comment@v3.0.5`, `cargo-bins/cargo-binstall@v1.21.0`. +by tag. In the generated workflows that is, at the time of writing, +`codecov/codecov-action@v7.0.0`, `marocchino/sticky-pull-request-comment@v3.0.5` and +`cargo-bins/cargo-binstall@v1.21.0`; a repository's own hand-maintained workflows apply +the same rule to the actions they use, so the list a reader sees there may be longer. An immutable release locks its Git tag to one commit: the tag cannot be moved, and cannot be deleted while the release exists. The tag name cannot be reused even after the repository is deleted and recreated, and publishing generates a release From 875290c64db9b48d6fe47d2b30e592fdced6bcad Mon Sep 17 00:00:00 2001 From: Vaiz <4908982+Vaiz@users.noreply.github.com> Date: Tue, 1 Sep 2026 12:43:38 +0100 Subject: [PATCH 3/3] chore(anvil): refresh .anvil.lock for cargo-anvil 0.6.0 The 0.6.0 version bump (#125) did not regenerate the lock, so it still recorded tool_version = "0.5.0". regenerate-check therefore fails on every branch whose merge-base includes that bump: the job reports "Manifest update required: 1 item(s) - .anvil.lock" with all 86 generated files unchanged. Produced by `cargo run -p cargo-anvil -- anvil`; a re-run is now a no-op. Only the tool_version line changes. No generated file, template or workflow is touched. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .anvil.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.anvil.lock b/.anvil.lock index a908ee9df..8e99d392b 100644 --- a/.anvil.lock +++ b/.anvil.lock @@ -1,6 +1,6 @@ version = 1 tool = "anvil" -tool_version = "0.5.0" +tool_version = "0.6.0" catalog_checksum = "sha256:7e4e7f7fa0e7f9491d3f5123f80ef209261e71b9cd9039e2f388e4287dc2f6bc" [[file]]