Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions RELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 <version> <path-to-binary>` — 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 <version> --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 <version>` 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
Expand Down
61 changes: 56 additions & 5 deletions scripts/verify-release-version.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 <version>` 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 <version> [path-to-binary]
# ./scripts/verify-release-version.sh <version> <path-to-binary> # both arms (releases, CI)
# ./scripts/verify-release-version.sh <version> --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 <version> <path-to-binary|--no-artifacts>"

die() { echo "verify-release-version: $*" >&2; exit 1; }

[ -n "$VERSION" ] || die "usage: verify-release-version.sh <version> [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
Expand Down Expand Up @@ -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 <version>`.
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
Loading