From 14aa05aace49a588d7661ea6401fa31cc68247c5 Mon Sep 17 00:00:00 2001 From: Sascha Brawer Date: Sun, 9 Aug 2026 18:01:00 +0200 Subject: [PATCH] release.yml: fail fast if the pushed tag doesn't match Cargo.toml's version Nothing verified that the git tag triggering a release (e.g. "v1.2.3") actually matches Cargo.toml's package version. A mismatched tag would still build, push, and attest a full release -- the registry tag would just disagree with what the binary and SBOM internally report as their own version, discovered only after the fact (if at all). Add a verify-version job that runs before the (expensive, ~11-16 min per arch) build job and fails immediately with a clear message on a mismatch, instead of burning CI time on a release that has to be thrown away anyway. build now depends on it via needs:. Extracts the version with a small awk script scoped to the [package] section specifically (not a bare "version = " grep), since dependency entries can also contain "version = ..." fields -- scoping to [package] means those can never cause a false match regardless of where they appear in the file. Verified against the current Cargo.toml, both the matching and mismatching cases. cargo metadata would also work, but this repo pins an exact Rust toolchain via rust-toolchain.toml, so running any `cargo` subcommand here would make rustup download and install that whole toolchain first, just to read one string -- not worth it for what should be an near-instant pre-flight check. --- .github/workflows/release.yml | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a497f51..03c465a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -22,9 +22,40 @@ env: permissions: {} jobs: + verify-version: + name: Verify release tag matches Cargo.toml version + runs-on: ubuntu-24.04 + timeout-minutes: 5 + permissions: + contents: read + + steps: + - name: Check out repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Compare tag to Cargo.toml version + run: | + TAG="${{ github.ref_name }}" + CARGO_VERSION=$(awk ' + /^\[package\]/ { in_package=1; next } + /^\[/ { in_package=0 } + in_package && /^version[[:space:]]*=/ { + match($0, /"[^"]*"/) + print substr($0, RSTART+1, RLENGTH-2) + exit + } + ' Cargo.toml) + EXPECTED_TAG="v${CARGO_VERSION}" + if [ "$TAG" != "$EXPECTED_TAG" ]; then + echo "::error::Git tag '${TAG}' does not match Cargo.toml's package version '${CARGO_VERSION}' (expected tag '${EXPECTED_TAG}'). Bump and commit Cargo.toml's version before tagging a release, or fix the tag." >&2 + exit 1 + fi + echo "OK: tag ${TAG} matches Cargo.toml version ${CARGO_VERSION}" + build: name: Build architecture-specific images runs-on: ${{ matrix.runner }} + needs: [verify-version] # Observed ~11-16 min per arch as of 2026-08; generous headroom over that, # well short of the 360 min default, so a hang fails fast instead of # burning runner-minutes for hours.