Skip to content
quarry Artifact [0b166e2a56]
Login

Artifact [0b166e2a56]

Artifact 0b166e2a5658db9329e2a0464fcddffe2917972e53dcdeab1f4a85704f10fb3a:


package api

import (
	"archive/tar"
	"bufio"
	"compress/gzip"
	"crypto/sha256"
	"encoding/hex"
	"io"
	"os"
	"os/exec"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"testing"
)

// releaseStub stands in for build-linux.sh: a quarry that prints its
// version, a zit, and, unless NO_RUNNERS is set, every runner download
// the tree's build script lists with their SHA256SUMS, as the real build
// lays them out. An arm64 build's binaries start with an ELF header for
// aarch64 (x86-64 with STUB_ARM64_WRONG set). Each call is logged to
// RELEASE_STUB_LOG with whether it could see the run token.
const releaseStub = `#!/bin/sh
set -eu
arch=$1 prefix=$2
echo "build $arch runners=${NO_RUNNERS:-yes} token=${QUARRY_TOKEN:-} zitpw=${ZIT_PASSWORD:-}" >>"$RELEASE_STUB_LOG"
mkdir -p "$prefix"
if [ "$arch" = arm64 ]; then
  m='\267'; [ -z "${STUB_ARM64_WRONG:-}" ] || m='>'
  for b in quarry zit; do
    printf '\177ELF\002\001\001\000\000\000\000\000\000\000\000\000\002\000'"$m"'\000 %s %s\n' "$b" "$VERSION" >"$prefix/$b"
  done
else
  printf '#!/bin/sh\necho "quarry %s"\n' "$VERSION" >"$prefix/quarry"
  printf '#!/bin/sh\necho "zit 0.0.0 linux-%s"\n' "$arch" >"$prefix/zit"
fi
chmod 0755 "$prefix/quarry" "$prefix/zit"
[ -z "${NO_RUNNERS:-}" ] || exit 0
mkdir -p "$prefix/runner"
for t in $(sed -n 's/^RUNNER_TARGETS="\(.*\)"$/\1/p' scripts/build-linux.sh); do
  os=${t%/*}; a=${t#*/}; ext=; [ "$os" = windows ] && ext=.exe
  echo "runner $t $VERSION" >"$prefix/runner/quarry-runner-$os-$a$ext"
done
if command -v sha256sum >/dev/null 2>&1; then s="sha256sum"; else s="shasum -a 256"; fi
(cd "$prefix/runner" && $s quarry-runner-* >SHA256SUMS)
`

// releaseTree is a throwaway quarry-shaped repository at version ver,
// carrying the scripts release.sh runs and tagged version-<ver>; it
// returns the checkout and the tagged check-in.
func releaseTree(t *testing.T, ver string) (string, string) {
	t.Helper()
	for _, bin := range []string{"zit", "sh", "tar", "gzip"} {
		if _, err := exec.LookPath(bin); err != nil {
			t.Skipf("%s not on PATH", bin)
		}
	}
	dir := t.TempDir()
	zitIn(t, dir, "init")
	files := map[string][]byte{
		"VERSION":      []byte(ver + "\n"),
		"CHANGELOG.md": []byte("# Changelog\n\n## " + ver + " — 2026-10-02\n\n- A release.\n\n## 0.1.0\n\n- Before.\n"),
		"LICENSE":      []byte("license\n"),
	}
	for _, s := range []string{"release.sh", "version-stamp.sh", "runner-check.sh", "build-linux.sh"} {
		raw, err := os.ReadFile(filepath.Join("..", "..", "scripts", s))
		if err != nil {
			t.Fatal(err)
		}
		files["scripts/"+s] = raw
	}
	for name, body := range files {
		p := filepath.Join(dir, filepath.FromSlash(name))
		if err := os.MkdirAll(filepath.Dir(p), 0o755); err != nil {
			t.Fatal(err)
		}
		if err := os.WriteFile(p, body, 0o644); err != nil {
			t.Fatal(err)
		}
		zitIn(t, dir, "add", name)
	}
	zitIn(t, dir, "commit", "-m", "release "+ver)
	checkin := strings.SplitN(zitIn(t, dir, "info", "current"), "\n", 2)[0]
	zitIn(t, dir, "tag", "add", "version-"+ver, checkin)
	return dir, checkin
}

func zitIn(t *testing.T, dir string, args ...string) string {
	t.Helper()
	cmd := exec.Command("zit", args...)
	cmd.Dir = dir
	out, err := cmd.CombinedOutput()
	if err != nil {
		t.Fatalf("zit %v: %v\n%s", args, err, out)
	}
	return string(out)
}

// runRelease runs release.sh in dir with the stub builder, logging its
// builds to log; env comes last, so it overrides.
func runRelease(t *testing.T, dir, log string, env []string, args ...string) (string, error) {
	t.Helper()
	stub := filepath.Join(t.TempDir(), "build-stub.sh")
	if err := os.WriteFile(stub, []byte(releaseStub), 0o755); err != nil {
		t.Fatal(err)
	}
	cmd := exec.Command("sh", append([]string{"scripts/release.sh"}, args...)...)
	cmd.Dir = dir
	cmd.Env = append(os.Environ(), "RELEASE_BUILD=sh "+stub, "RELEASE_STUB_LOG="+log, "TMPDIR="+t.TempDir(),
		"QUARRY_TAG=", "QUARRY_USER=", "QUARRY_TOKEN=", "ZIT_PASSWORD=", "RELEASE_ARM64=")
	cmd.Env = append(cmd.Env, env...)
	b, err := cmd.CombinedOutput()
	return string(b), err
}

func readLog(t *testing.T, p string) string {
	t.Helper()
	b, err := os.ReadFile(p)
	if err != nil && !os.IsNotExist(err) {
		t.Fatal(err)
	}
	return string(b)
}

func fileSum(t *testing.T, p string) (string, int64) {
	t.Helper()
	raw, err := os.ReadFile(p)
	if err != nil {
		t.Fatal(err)
	}
	h := sha256.Sum256(raw)
	return hex.EncodeToString(h[:]), int64(len(raw))
}

// RELEASE.SH --DRY-RUN WRITES A RELEASE THE FORGE AND DEPLOY.SH READ
// (RFC 0020 §releases): the manifest parses as the Releases page parses
// it, every sha256 in it is SHA256SUMS' and the bytes', and the tarballs
// are the one-directory layout deploy.sh --release unpacks.
func TestReleaseScriptDryRunWritesWhatTheForgeReads(t *testing.T) {
	const ver = "9.8.7"
	dir, checkin := releaseTree(t, ver)
	out := filepath.Join(t.TempDir(), "out")
	builds := filepath.Join(t.TempDir(), "builds")
	if log, err := runRelease(t, dir, builds, nil, "--dry-run", "--out", out, ver); err != nil {
		t.Fatalf("FAIL: release.sh --dry-run: %v\n%s", err, log)
	}
	// linux-arm64 is opt-in: one build, amd64, with the runner downloads.
	if got := readLog(t, builds); got != "build amd64 runners=yes token= zitpw=\n" {
		t.Errorf("FAIL: the builds were\n%s\nwant amd64 alone, with the runners", got)
	}

	// SHA256SUMS: one sum and one bare name per line, as deploy.sh
	// insists, and a line for every file but itself and the manifest.
	sums := map[string]string{}
	f, err := os.Open(filepath.Join(out, "SHA256SUMS"))
	if err != nil {
		t.Fatal(err)
	}
	line := regexp.MustCompile(`^([0-9a-f]{64}) [ *]([A-Za-z0-9_][A-Za-z0-9._-]*)$`)
	sc := bufio.NewScanner(f)
	for sc.Scan() {
		m := line.FindStringSubmatch(sc.Text())
		if m == nil {
			t.Errorf("FAIL: SHA256SUMS line %q is not a sum and a bare name", sc.Text())
			continue
		}
		sums[m[2]] = m[1]
	}
	f.Close()
	entries, err := os.ReadDir(out)
	if err != nil {
		t.Fatal(err)
	}
	var names []string
	for _, e := range entries {
		n := e.Name()
		names = append(names, n)
		if n == "SHA256SUMS" || n == "release-manifest.json" {
			continue
		}
		got, _ := fileSum(t, filepath.Join(out, n))
		if sums[n] != got {
			t.Errorf("FAIL: SHA256SUMS says %s is %q; its bytes are %s", n, sums[n], got)
		}
	}
	sort.Strings(names)
	want := []string{
		"SHA256SUMS",
		"quarry-9.8.7-linux-amd64.tar.gz", "quarry-9.8.7-src.tar.gz",
		"quarry-runner-darwin-amd64", "quarry-runner-darwin-arm64", "quarry-runner-linux-amd64",
		"quarry-runner-linux-arm64", "quarry-runner-windows-amd64.exe",
		"release-manifest.json",
	}
	if strings.Join(names, " ") != strings.Join(want, " ") {
		t.Errorf("FAIL: the release holds\n  %v\nwant\n  %v", names, want)
	}
	if len(sums) != len(want)-2 {
		t.Errorf("FAIL: SHA256SUMS has %d lines; want %d", len(sums), len(want)-2)
	}

	// The manifest, through the Releases page's own parser.
	raw, err := os.ReadFile(filepath.Join(out, "release-manifest.json"))
	if err != nil {
		t.Fatal(err)
	}
	m, err := parseReleaseManifest(raw, ver)
	if err != nil {
		t.Fatalf("FAIL: the forge refuses the manifest: %v\n%s", err, raw)
	}
	if m.Version != ver || m.Tag != "version-"+ver || m.Checkin != checkin || m.Date == "" {
		t.Errorf("FAIL: manifest release = %q %q %q %q; want %s, version-%s, %s and a date", m.Version, m.Tag, m.Checkin, m.Date, ver, ver, checkin)
	}
	described := append([]releaseArtifact{}, m.Artifacts...)
	if m.Source == nil {
		t.Error("FAIL: the manifest names no source archive")
	} else {
		described = append(described, *m.Source)
	}
	seen := map[string]bool{}
	for _, a := range described {
		seen[a.Name] = true
		got, size := fileSum(t, filepath.Join(out, a.Name))
		if a.SHA256 != got || a.SHA256 != sums[a.Name] || a.Size != size {
			t.Errorf("FAIL: manifest says %s is %s, %d bytes; its bytes are %s, %d; SHA256SUMS says %s", a.Name, a.SHA256, a.Size, got, size, sums[a.Name])
		}
		if a.Target == "" || a.Qualification == "" {
			t.Errorf("FAIL: %s has target %q and qualification %q; want both", a.Name, a.Target, a.Qualification)
		}
	}
	for n := range sums {
		if !seen[n] {
			t.Errorf("FAIL: %s is published and the manifest does not describe it", n)
		}
	}
	omitted := map[string]bool{}
	for _, o := range m.Omitted {
		omitted[o.Target] = o.Reason != ""
	}
	for _, t2 := range []string{"linux-arm64", "darwin-arm64", "darwin-amd64", "windows-amd64"} {
		if !omitted[t2] {
			t.Errorf("FAIL: the manifest does not name %s as omitted, with a reason: %+v", t2, m.Omitted)
		}
	}
	if len(m.Qualification) == 0 {
		t.Error("FAIL: the manifest carries no qualification notes")
	}

	// The layout deploy.sh --release unpacks: one directory, holding
	// quarry, zit, CHANGELOG.md and LICENSE, and nothing else.
	checkLayout(t, out, ver, "amd64")
	t.Log("ok: the dry run's manifest parses, its sums are SHA256SUMS' and the bytes', the tarballs are deploy's layout")
}

// checkLayout holds a forge tarball to the layout deploy.sh --release
// unpacks: one directory, holding quarry, zit, CHANGELOG.md and LICENSE.
func checkLayout(t *testing.T, out, ver, arch string) {
	t.Helper()
	top := "quarry-" + ver + "-linux-" + arch
	members := tarMembers(t, filepath.Join(out, top+".tar.gz"))
	want := []string{top + "/", top + "/CHANGELOG.md", top + "/LICENSE", top + "/quarry", top + "/zit"}
	if strings.Join(members, " ") != strings.Join(want, " ") {
		t.Errorf("FAIL: %s.tar.gz holds %v; want %v", top, members, want)
	}
}

func tarMembers(t *testing.T, p string) []string {
	t.Helper()
	f, err := os.Open(p)
	if err != nil {
		t.Fatal(err)
	}
	defer f.Close()
	gz, err := gzip.NewReader(f)
	if err != nil {
		t.Fatal(err)
	}
	tr := tar.NewReader(gz)
	var out []string
	for {
		h, err := tr.Next()
		if err == io.EOF {
			break
		}
		if err != nil {
			t.Fatal(err)
		}
		name := strings.TrimPrefix(h.Name, "./")
		if h.Typeflag == tar.TypeDir && !strings.HasSuffix(name, "/") {
			name += "/"
		}
		out = append(out, name)
	}
	sort.Strings(out)
	return out
}

// RELEASE.SH REFUSES WHAT IS NOT RELEASE X.Y.Z: another version than
// VERSION, a check-in that does not carry the tag itself, an untracked
// file, a changed one, a changelog with no section for it, and a run
// started by another tag.
func TestReleaseScriptRefusesWhatIsNotTheRelease(t *testing.T) {
	const ver = "9.8.7"
	dir, _ := releaseTree(t, ver)
	out := filepath.Join(t.TempDir(), "out")
	refused := func(why, want string, args ...string) {
		t.Helper()
		log, err := runRelease(t, dir, filepath.Join(t.TempDir(), "builds"), nil, append([]string{"--dry-run", "--out", out}, args...)...)
		if err == nil || !strings.Contains(log, want) {
			t.Errorf("FAIL: %s: err %v, output\n%s\nwant a refusal naming %q", why, err, log, want)
		}
	}
	refused("another version", "VERSION holds 9.8.7, not 9.8.8", "9.8.8")

	if err := os.WriteFile(filepath.Join(dir, "stray.txt"), []byte("x\n"), 0o644); err != nil {
		t.Fatal(err)
	}
	refused("an untracked file", "untracked files", ver)
	os.Remove(filepath.Join(dir, "stray.txt"))

	if err := os.WriteFile(filepath.Join(dir, "LICENSE"), []byte("changed\n"), 0o644); err != nil {
		t.Fatal(err)
	}
	refused("a changed file", "has changes", ver)
	zitIn(t, dir, "revert")

	if err := os.WriteFile(filepath.Join(dir, "CHANGELOG.md"), []byte("# Changelog\n\n## 9.8.70\n\n## 0.1.0-9.8.7\n"), 0o644); err != nil {
		t.Fatal(err)
	}
	refused("no changelog heading", "no \"## 9.8.7\" heading", ver)
	zitIn(t, dir, "revert")

	cmd := exec.Command("sh", "scripts/release.sh", "--dry-run", ver)
	cmd.Dir = dir
	cmd.Env = append(os.Environ(), "QUARRY_TAG=version-9.9.9")
	if b, err := cmd.CombinedOutput(); err == nil || !strings.Contains(string(b), "started by the tag version-9.9.9") {
		t.Errorf("FAIL: a run started by another tag: err %v, output\n%s", err, b)
	}

	// The next check-in inherits nothing: the tag is its parent's.
	if err := os.WriteFile(filepath.Join(dir, "LICENSE"), []byte("next\n"), 0o644); err != nil {
		t.Fatal(err)
	}
	zitIn(t, dir, "commit", "-m", "after the release")
	refused("an untagged check-in", "does not carry version-9.8.7", ver)
	t.Log("ok: a wrong version, a dirty tree, no changelog section, another tag and an untagged check-in are refused")
}

// LINUX-ARM64 IS OPT-IN: with RELEASE_ARM64=1 the cross toolchain is
// asked for before anything builds, the arm64 build skips the runner
// downloads (built once, with amd64), and its binaries must be ELF for
// aarch64.
func TestReleaseScriptBuildsArm64OnlyWhenAskedAndChecksIt(t *testing.T) {
	const ver = "9.8.7"
	dir, _ := releaseTree(t, ver)

	builds := filepath.Join(t.TempDir(), "builds")
	log, err := runRelease(t, dir, builds, []string{"RELEASE_ARM64=1", "ARM64_CC=no-such-cc-for-quarry", "ARM64_CXX=sh"},
		"--dry-run", "--out", filepath.Join(t.TempDir(), "out"), ver)
	if err == nil || !strings.Contains(log, "no-such-cc-for-quarry") {
		t.Errorf("FAIL: a missing ARM64_CC: err %v, output\n%s\nwant a refusal naming it", err, log)
	}
	if got := readLog(t, builds); got != "" {
		t.Errorf("FAIL: a missing cross compiler still built:\n%s", got)
	}

	builds = filepath.Join(t.TempDir(), "builds")
	log, err = runRelease(t, dir, builds, []string{"RELEASE_ARM64=1", "ARM64_CC=sh", "ARM64_CXX=sh", "STUB_ARM64_WRONG=1"},
		"--dry-run", "--out", filepath.Join(t.TempDir(), "out"), ver)
	if err == nil || !strings.Contains(log, "aarch64") {
		t.Errorf("FAIL: an arm64 build that is not aarch64: err %v, output\n%s", err, log)
	}

	out := filepath.Join(t.TempDir(), "out")
	builds = filepath.Join(t.TempDir(), "builds")
	if log, err := runRelease(t, dir, builds, []string{"RELEASE_ARM64=1", "ARM64_CC=sh", "ARM64_CXX=sh"}, "--dry-run", "--out", out, ver); err != nil {
		t.Fatalf("FAIL: release.sh --dry-run with arm64: %v\n%s", err, log)
	}
	if got, want := readLog(t, builds), "build amd64 runners=yes token= zitpw=\nbuild arm64 runners=1 token= zitpw=\n"; got != want {
		t.Errorf("FAIL: the builds were\n%s\nwant\n%s", got, want)
	}
	checkLayout(t, out, ver, "arm64")
	raw, err := os.ReadFile(filepath.Join(out, "release-manifest.json"))
	if err != nil {
		t.Fatal(err)
	}
	m, err := parseReleaseManifest(raw, ver)
	if err != nil {
		t.Fatal(err)
	}
	found := false
	for _, a := range m.Artifacts {
		found = found || (a.Target == "linux-arm64" && a.Name == "quarry-9.8.7-linux-arm64.tar.gz")
	}
	for _, o := range m.Omitted {
		if o.Target == "linux-arm64" {
			t.Errorf("FAIL: linux-arm64 was built and is still listed as omitted")
		}
	}
	if !found {
		t.Errorf("FAIL: the manifest does not describe the arm64 tarball: %+v", m.Artifacts)
	}
	t.Log("ok: arm64 is opt-in, its compiler is asked for first, its binaries must be aarch64, the runners build once")
}

// --OUT IS NEVER CLEARED: a directory with something in it is refused
// and left as it was; an empty one is filled.
func TestReleaseScriptNeverDeletesTheOutDirectory(t *testing.T) {
	const ver = "9.8.7"
	dir, _ := releaseTree(t, ver)
	out := t.TempDir()
	keep := filepath.Join(out, "mine.txt")
	if err := os.WriteFile(keep, []byte("mine\n"), 0o644); err != nil {
		t.Fatal(err)
	}
	log, err := runRelease(t, dir, filepath.Join(t.TempDir(), "builds"), nil, "--dry-run", "--out", out, ver)
	if err == nil || !strings.Contains(log, "not empty") {
		t.Errorf("FAIL: a non-empty --out: err %v, output\n%s\nwant a refusal", err, log)
	}
	if b, err := os.ReadFile(keep); err != nil || string(b) != "mine\n" {
		t.Errorf("FAIL: the file in --out is gone or changed: %q, %v", b, err)
	}
	empty := t.TempDir()
	if log, err := runRelease(t, dir, filepath.Join(t.TempDir(), "builds"), nil, "--dry-run", "--out", empty, ver); err != nil {
		t.Errorf("FAIL: an empty --out: %v\n%s", err, log)
	}
	if _, err := os.Stat(filepath.Join(empty, "SHA256SUMS")); err != nil {
		t.Errorf("FAIL: the empty --out was not filled: %v", err)
	}
	t.Log("ok: a non-empty --out is refused untouched, an empty one is filled")
}

// zitShim is a zit on PATH for the publish path: `zit uv` is answered
// from UV_DIR, a forge's unversioned files as plain files, printing
// `uv list` as zit 0.3.36 does (uvList in zit's src/cmd/sync.zig: the
// live names, sorted, one per line) and writing `uv pull -o DIR` as
// DIR/<name>; every other verb runs the real zit. Each call's argv and
// the token variables it could see go to UV_LOG.
const zitShim = `#!/bin/sh
{
  printf 'argv:'; for a in "$@"; do printf ' %s' "$a"; done; printf '\n'
  printf 'env: QUARRY_TOKEN=%s ZIT_PASSWORD=%s\n' "${QUARRY_TOKEN:-}" "${ZIT_PASSWORD:-}"
} >>"$UV_LOG"
[ "$1" = uv ] || exec "$REAL_ZIT" "$@"
verb=$2; shift 3
case "$verb" in
list)
  (cd "$UV_DIR" && find . -type f | sed 's|^\./||' | LC_ALL=C sort) ;;
pull)
  name=$1; o=.; shift
  while [ $# -gt 0 ]; do case "$1" in -o) o=$2; shift ;; esac; shift; done
  [ -f "$UV_DIR/$name" ] || { echo "zit uv: the server holds no '$name'" >&2; exit 1; }
  mkdir -p "$o/$(dirname "$name")" && cp "$UV_DIR/$name" "$o/$name" ;;
push)
  file=$1; name=$1; shift
  while [ $# -gt 0 ]; do case "$1" in --as) name=$2; shift ;; esac; shift; done
  mkdir -p "$UV_DIR/$(dirname "$name")" && cp "$file" "$UV_DIR/$name" ;;
*) exit 2 ;;
esac
`

// THE PUBLISH PATH (RFC 0020, RFC 0021 §runs): every file goes to
// releases/X.Y.Z/ with SHA256SUMS first and the manifest last, as the
// run's login with its token only in ZIT_PASSWORD; no build and no zit
// call outside the uv verbs sees the token. A re-run finding the manifest
// for this check-in publishes nothing and succeeds; one for another
// check-in fails.
func TestReleaseScriptPublishesInOrderWithTheTokenOnlyInZitsEnvironment(t *testing.T) {
	const ver = "9.8.7"
	const token = "qrt_7_s3cr3t"
	dir, checkin := releaseTree(t, ver)
	realZit, err := exec.LookPath("zit")
	if err != nil {
		t.Skip("zit not on PATH")
	}
	bin, uvDir := t.TempDir(), t.TempDir()
	if err := os.WriteFile(filepath.Join(bin, "zit"), []byte(zitShim), 0o755); err != nil {
		t.Fatal(err)
	}
	// Another release's manifest, whose name a loose match would take for this one's.
	decoy := filepath.Join(uvDir, "releases", "9.8.70", "release-manifest.json")
	if err := os.MkdirAll(filepath.Dir(decoy), 0o755); err != nil {
		t.Fatal(err)
	}
	if err := os.WriteFile(decoy, []byte("{}"), 0o644); err != nil {
		t.Fatal(err)
	}
	uvLog := filepath.Join(t.TempDir(), "uv.log")
	env := []string{"PATH=" + bin + string(os.PathListSeparator) + os.Getenv("PATH"), "REAL_ZIT=" + realZit,
		"UV_DIR=" + uvDir, "UV_LOG=" + uvLog, "QUARRY_USER=run-7", "QUARRY_TOKEN=" + token,
		"RELEASE_URL=http://forge.test/r/quarry", "QUARRY_TAG=version-" + ver}
	builds := filepath.Join(t.TempDir(), "builds")
	out := filepath.Join(t.TempDir(), "out")
	if log, err := runRelease(t, dir, builds, env, "--out", out, ver); err != nil {
		t.Fatalf("FAIL: release.sh publish: %v\n%s", err, log)
	}
	if got := readLog(t, builds); strings.Contains(got, token) {
		t.Errorf("FAIL: a build saw the token:\n%s", got)
	}

	// Every call: argv never holds the token; QUARRY_TOKEN is gone from
	// every zit; ZIT_PASSWORD is the token on the uv verbs alone.
	var pushed []string
	lines := strings.Split(strings.TrimSpace(readLog(t, uvLog)), "\n")
	for i := 0; i+1 < len(lines); i += 2 {
		argv, envLine := lines[i], lines[i+1]
		if strings.Contains(argv, token) {
			t.Errorf("FAIL: the token is in argv: %s", argv)
		}
		uv := strings.HasPrefix(argv, "argv: uv ")
		want := "env: QUARRY_TOKEN= ZIT_PASSWORD="
		if uv {
			want += token
			if !strings.Contains(argv, " --user run-7") || !strings.Contains(argv, " http://forge.test/r/quarry") {
				t.Errorf("FAIL: a uv call is not to the forge as run-7: %s", argv)
			}
		}
		if envLine != want {
			t.Errorf("FAIL: %s ran with %q; want %q", argv, envLine, want)
		}
		if f := strings.Fields(argv); uv && f[2] == "push" {
			for j, w := range f {
				if w == "--as" && j+1 < len(f) {
					pushed = append(pushed, f[j+1])
				}
			}
		}
	}
	entries, err := os.ReadDir(out)
	if err != nil {
		t.Fatal(err)
	}
	if len(pushed) != len(entries) {
		t.Errorf("FAIL: pushed %d files; the release has %d: %v", len(pushed), len(entries), pushed)
	}
	if len(pushed) < 2 || pushed[0] != "releases/9.8.7/SHA256SUMS" || pushed[len(pushed)-1] != "releases/9.8.7/release-manifest.json" {
		t.Errorf("FAIL: the push order was %v; want SHA256SUMS first and the manifest last", pushed)
	}
	for _, e := range entries {
		want, _ := fileSum(t, filepath.Join(out, e.Name()))
		got, _ := fileSum(t, filepath.Join(uvDir, "releases", ver, e.Name()))
		if got != want {
			t.Errorf("FAIL: the forge's %s is not the release's", e.Name())
		}
	}

	// Re-run: the forge holds this check-in's manifest; nothing is built or pushed.
	before := readLog(t, uvLog)
	builds2 := filepath.Join(t.TempDir(), "builds")
	log, err := runRelease(t, dir, builds2, env, "--out", filepath.Join(t.TempDir(), "out"), ver)
	if err != nil || !strings.Contains(log, "already holds") {
		t.Errorf("FAIL: a re-run against the published release: err %v, output\n%s", err, log)
	}
	if strings.Contains(strings.TrimPrefix(readLog(t, uvLog), before), "uv push") || readLog(t, builds2) != "" {
		t.Errorf("FAIL: a re-run built or pushed again")
	}

	// The forge's manifest names another check-in: refused, nothing pushed.
	held := filepath.Join(uvDir, "releases", ver, "release-manifest.json")
	raw, err := os.ReadFile(held)
	if err != nil {
		t.Fatal(err)
	}
	other := strings.Repeat("ab", len(checkin)/2)
	if err := os.WriteFile(held, []byte(strings.ReplaceAll(string(raw), checkin, other)), 0o644); err != nil {
		t.Fatal(err)
	}
	before = readLog(t, uvLog)
	log, err = runRelease(t, dir, filepath.Join(t.TempDir(), "builds"), env, "--out", filepath.Join(t.TempDir(), "out"), ver)
	if err == nil || !strings.Contains(log, other[:12]) {
		t.Errorf("FAIL: a held manifest for another check-in: err %v, output\n%s\nwant a refusal naming %s", err, log, other[:12])
	}
	if strings.Contains(strings.TrimPrefix(readLog(t, uvLog), before), "uv push") {
		t.Errorf("FAIL: a mismatched release was pushed over")
	}
	t.Log("ok: SHA256SUMS first, manifest last, the token only in the uv calls' ZIT_PASSWORD; a re-run is a no-op, a mismatch fails")
}