708d335fa7
REVIEW OF THE PREVIOUS COMMIT, NOT NEW MACHINERY. The diagnosis it states was re-verified in both directions before anything here was written: `dist plan --tag=v0.1.0-rc2` gets past the tag/version check (stopping at the pinned cargo-dist-version, as expected) and `--tag=v0.1.0-rc3` reproduces the CI error verbatim, naming `--tag=v0.1.0-rc2` as the fix in its own help text. The workflow was never broken. Both claimed fault injections also reproduce exactly: the comparison replaced by `if false;`, and `expected` derived from the tag, each produce four failures and exit 1 -- exit code read unpiped, since a pager's status would mask it. WHAT THE TEST COULD NOT SEE. Disabling the dirty-tree guard outright left all six checks green and the script exiting 0. That guard is not decoration: it is what stops a tag naming a commit that was never tested, and its failure is irreversible in the same way the version mismatch is. The cause is the previous repair. Moving the negative cases to a clean throwaway checkout is what made the tag comparison reachable at all -- and it thereby removed the only circumstance in which the test could observe the tree guard. The guard whose PRECEDENCE caused the original vacuity became the one thing the suite could not see. The vacuity and its repair are not two events; the repair relocated the blind spot rather than closing it. So the new check is aimed the other way: a tag that MATCHES the version, run against a dirtied checkout, so the comparison passes and a refusal can only be the tree. Verified discriminating -- with the guard disabled it fails with exit 1, and the two faults are independent in both directions (comparison disabled leaves the tree check passing, guard disabled leaves the three tag checks passing), so the seventh check is not a restatement of the other six. Also recorded, rather than guarded: the `dist plan` second opinion can be disabled with the suite green, because every input the test feeds it has already been refused by the textual check. That follows from the arm being optional by design -- pinning it would mean installing a dist matching cargo-dist-version, the very mismatch the script tolerates on purpose. Stated so the silence is not mistaken for coverage. Two corrections of fact. The CI step lives in the `kb` job beside pr-watch-test.sh, where this repo keeps its check_the_checkers -- not in `test`; tooling.md now says so. And the awk version parser was probed rather than hardened: `version.workspace = true` yields empty, which the root path refuses loudly and the per-crate loop skips; a non-first [package] block and build metadata both parse correctly; a trailing comment on the version line mis-parses but fails CLOSED and prints the mis-parsed value in the refusal. No manifest in this workspace has one, so nothing was changed for it. No version bumped, no tag cut. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FC2jVn8Au7E9JPkw6bwXXH
92 lines
4.1 KiB
Bash
Executable File
92 lines
4.1 KiB
Bash
Executable File
#!/bin/sh
|
|
# check_the_checker for scripts/release-preflight.sh.
|
|
#
|
|
# It exists for the reason scripts/assemble-stamp-test.sh does: the guard is the
|
|
# whole value, and a guard that silently stopped guarding is invisible from the
|
|
# outside -- a preflight that accepted everything would print the same reassuring
|
|
# lines it prints today.
|
|
#
|
|
# IT ASSERTS THE REASON, NOT THE EXIT CODE, and that is the point. A first version
|
|
# checked only "did it refuse", and every negative case passed while the tag
|
|
# comparison was disabled -- because the script refuses a DIRTY WORKING TREE first,
|
|
# and this repo's tree is usually dirty (bd auto-exports .beads/issues.jsonl). Four
|
|
# of five checks were answering "is the tree dirty" while claiming to answer "does
|
|
# it catch a bad tag". Injecting `if false;` into the comparison is what exposed it.
|
|
# See context/design-principles.md section 7 -- a check adjacent to the thing it names.
|
|
set -eu
|
|
|
|
root=$(cd "$(dirname "$0")/.." && pwd)
|
|
script="$root/scripts/release-preflight.sh"
|
|
fails=0
|
|
|
|
# Refuses, AND the refusal names the tag/version mismatch rather than the tree.
|
|
refuses_for_the_tag() {
|
|
what=$1; tag=$2
|
|
out=$(sh "$script" "$tag" 2>&1) && { echo "FAIL: $what -- accepted" >&2; fails=$((fails+1)); return; }
|
|
case "$out" in
|
|
*"Cargo.toml has"*) echo " ok: $what (refused, naming the version)" ;;
|
|
*"uncommitted changes"*) echo "FAIL: $what -- refused for the DIRTY TREE, so this check proved nothing" >&2; fails=$((fails+1)) ;;
|
|
*) echo "FAIL: $what -- refused for an unrecognised reason:" >&2; echo "$out" | head -3 >&2; fails=$((fails+1)) ;;
|
|
esac
|
|
}
|
|
|
|
version=$(awk '/^\[package\]/{p=1;next} /^\[/{p=0} p&&/^version *=/{gsub(/[" ]/,"");sub(/^version=/,"");print;exit}' \
|
|
"$root/Cargo.toml")
|
|
test -n "$version" || { echo "FAIL: could not read the root version" >&2; exit 1; }
|
|
echo "release-preflight-test: root version is $version"
|
|
|
|
# The dirty-tree guard runs first, so the negative cases are exercised against a
|
|
# CLEAN checkout of this tree rather than the working copy. Without this the test
|
|
# cannot reach the comparison it exists to check.
|
|
tmp=$(mktemp -d)
|
|
trap 'rm -rf "$tmp"' EXIT
|
|
git -C "$root" archive HEAD | (cd "$tmp" && tar x)
|
|
cp -f "$script" "$tmp/scripts/release-preflight.sh"
|
|
cp -f "$root/Cargo.toml" "$tmp/Cargo.toml"
|
|
(cd "$tmp" && git init -q . && git add -A && git -c user.email=t@t -c user.name=t commit -qm t)
|
|
script="$tmp/scripts/release-preflight.sh"
|
|
|
|
if sh "$script" --self-test >/dev/null 2>&1; then
|
|
echo " ok: --self-test (accepted)"
|
|
else
|
|
echo "FAIL: --self-test refused" >&2; fails=$((fails+1))
|
|
fi
|
|
|
|
if sh "$script" >/dev/null 2>&1; then
|
|
echo "FAIL: no argument should be a usage error" >&2; fails=$((fails+1))
|
|
else
|
|
echo " ok: no argument is a usage error (refused)"
|
|
fi
|
|
|
|
refuses_for_the_tag "a tag one character off" "v${version}x"
|
|
refuses_for_the_tag "the shape that actually broke CI" "v0.1.0-rc99"
|
|
refuses_for_the_tag "a bare version with no v" "$version"
|
|
|
|
# The positive direction, which only a clean tree can exercise.
|
|
if sh "$script" "v$version" >/dev/null 2>&1; then
|
|
echo " ok: the matching tag v$version (accepted)"
|
|
else
|
|
echo "FAIL: the matching tag v$version was refused" >&2; fails=$((fails+1))
|
|
fi
|
|
|
|
# The dirty-tree guard, which every check above is deliberately blind to: they
|
|
# run on a CLEAN checkout precisely so the tag comparison is reachable at all.
|
|
# The tag here MATCHES the version, so the comparison passes and a refusal can
|
|
# only be the tree -- which is what separates this check from the ones above
|
|
# instead of duplicating them. Disabling the guard leaves all six of those green.
|
|
echo "dirtied by release-preflight-test" >> "$tmp/README.md"
|
|
if out=$(sh "$script" "v$version" 2>&1); then
|
|
echo "FAIL: a dirty tree -- accepted" >&2; fails=$((fails+1))
|
|
else
|
|
case "$out" in
|
|
*"uncommitted changes"*) echo " ok: a dirty tree (refused, naming the tree)" ;;
|
|
*) echo "FAIL: a dirty tree -- refused, but not for the tree:" >&2; echo "$out" | head -3 >&2; fails=$((fails+1)) ;;
|
|
esac
|
|
fi
|
|
|
|
if [ "$fails" -ne 0 ]; then
|
|
echo "release-preflight-test: $fails failure(s)" >&2
|
|
exit 1
|
|
fi
|
|
echo "release-preflight-test: all checks passed"
|