diff --git a/RELEASE.md b/RELEASE.md index 2f5f19938..298c87d49 100644 --- a/RELEASE.md +++ b/RELEASE.md @@ -197,6 +197,17 @@ first-class release artifact while `npm i maxplayer` answered `no binary for dar mac (#446), because the build matrix and the npm platform list were independent lists and nothing compared them. +`verify-release-version.sh` has two arms and says which ones ran. The tree arm reads the crate +version, the npm manifests, the payload pins and the release notes; the artifact arm inspects a built +binary's own `--version` line and build stamp. So it is invoked +`./scripts/verify-release-version.sh ` — both call sites in CI and the +release job pass a path, and the version without a leading `v`. A run with no binary path is a +refusal, not a pass: to check the tree alone, ask for it by name with +`./scripts/verify-release-version.sh --no-artifacts` — the same opt-out flag +`verify-release-surface.sh` takes, printing the same `ok: skipping the built-artifact check +(--no-artifacts) — …` line and closing with `PASS (NO ARTIFACTS)`. Before that, a missing path +silently skipped the artifact arm and still printed `PASS: everything states ` with exit 0. + The trusted-publisher entry is the step no check can make: it lives on npmjs.com, needs an org admin, and must exist BEFORE the tag. Without it the publish job fails on that package — loudly, which is correct — but only after the packages ahead of it in the loop have published, and npm does not allow diff --git a/scripts/verify-release-version.sh b/scripts/verify-release-version.sh index 51cadcf7e..bca95da96 100755 --- a/scripts/verify-release-version.sh +++ b/scripts/verify-release-version.sh @@ -25,23 +25,63 @@ # and is not — and it is why `(unknown)` fails a release closed here even though the binary is # allowed to print it from a build path that genuinely had no git to read. # +# ── Which arms ran is part of the result (#1007 follow-up) ─────────────────────────────────────── +# This script has two arms: the TREE checks (crate version, npm manifests, payload pins, release +# notes) and the ARTIFACT check (the built binary's own `--version` line and build stamp). The +# artifact arm used to be skipped whenever no binary path was supplied — and the run still printed +# `PASS: everything states ` and exited 0. A gate whose teeth are absent must not read as a +# full pass, so a binary path is now REQUIRED unless the caller opts out in writing with +# `--no-artifacts`, and the final line always names the arms that actually ran. +# +# The flag is `--no-artifacts`, spelled and printed the way `verify-release-surface.sh` already +# spells and prints it — same opt-out name, same `ok: skipping the built-artifact check +# (--no-artifacts) — …` line — so one house style covers both release gates and a reader who knows +# one knows the other. +# # Usage: -# ./scripts/verify-release-version.sh [path-to-binary] +# ./scripts/verify-release-version.sh # both arms (releases, CI) +# ./scripts/verify-release-version.sh --no-artifacts # tree arm only, and says so # e.g. ./scripts/verify-release-version.sh 0.1.0 result/bin/maxplayer +# ./scripts/verify-release-version.sh 0.1.0 --no-artifacts # # Pass the version WITHOUT a leading `v` — the workflow strips it from the tag. set -euo pipefail -VERSION="${1:-}" -BINARY="${2:-}" +USAGE="usage: verify-release-version.sh " die() { echo "verify-release-version: $*" >&2; exit 1; } -[ -n "$VERSION" ] || die "usage: verify-release-version.sh [path-to-binary]" +VERSION="" +BINARY="" +NO_ARTIFACTS=0 +for arg in "$@"; do + case "$arg" in + --no-artifacts) NO_ARTIFACTS=1 ;; + -h|--help) echo "$USAGE"; exit 0 ;; + -*) die "unknown option '$arg' — $USAGE" ;; + *) + if [ -z "$VERSION" ]; then VERSION="$arg" + elif [ -z "$BINARY" ]; then BINARY="$arg" + else die "unexpected extra argument '$arg' — $USAGE" + fi + ;; + esac +done + +[ -n "$VERSION" ] || die "$USAGE" case "$VERSION" in v*) die "pass the version without a leading 'v' (got '$VERSION')" ;; esac + +# Fail closed on a missing artifact rather than skipping its arm: a run that inspected no binary +# proves nothing about the thing being shipped, and must not be mistakable for a full pass. +if [ -n "$BINARY" ] && [ "$NO_ARTIFACTS" -eq 1 ]; then + die "--no-artifacts was given together with the binary path '$BINARY' — pick one: check the artifact, or declare in writing that you are not checking it" +fi +if [ -z "$BINARY" ] && [ "$NO_ARTIFACTS" -eq 0 ]; then + die "the ARTIFACT arm did not run: no path to a built binary was given, so nothing here would have checked that the artifact reports $VERSION or carries a resolvable build stamp. Pass the binary — $USAGE — or opt out explicitly with --no-artifacts, which passes while naming the arm it skipped" +fi [ -f Cargo.toml ] || die "run from the repo root (Cargo.toml missing)" # Fail closed on the tools rather than skipping a check: a version check that silently did not run @@ -170,6 +210,17 @@ if [ -n "$BINARY" ]; then [ "$stamp_sha" = "$head_sha" ] \ || die "the artifact was built from $stamp_sha but this tree is at $head_sha — the binary and the source being packaged are different commits" echo "ok: build stamp $stamp_sha resolves to a commit and is this tree's HEAD" +else + # The skip is printed, never silent, and in the same words `verify-release-surface.sh` uses for + # its own `--no-artifacts` opt-out — the reader of either gate's log sees one house style. + echo "ok: skipping the built-artifact check (--no-artifacts) — holding the tree-stated version only; nothing here binds a built artifact to $VERSION or to this commit" fi -echo "PASS: everything states $VERSION" +# The summary states which arms ran, so a reader does not have to infer it from the exit code — the +# inference that let a 4-line run and a 7-line run both read as `PASS: everything states `. +TREE_ARM="tree (crate version, npm manifests, payload pins, release notes)" +if [ -n "$BINARY" ]; then + echo "PASS: everything states $VERSION — arms run: $TREE_ARM + built artifact ($BINARY)" +else + echo "PASS (NO ARTIFACTS): the tree states $VERSION — arms run: $TREE_ARM; the built-artifact check did NOT run (--no-artifacts)" +fi