fix(ci): anchor the release-skip marker to a trailer, and test it
release / tag (push) Successful in 1s

The tagger searched the entire commit message for a bracketed marker as a
substring. The commit that introduced the manifest-bump step described that
marker in its own body — so the tagger read its own documentation as an
instruction and skipped the release. Run 15 reported success with no tag, no
manifest bump and no error. Same failure family as everything else in this
sweep: the wrong thing happened silently.

The rule is now a git trailer matched anchored to its own line, consistent
with Bump-Type, and it lives in bin/should-skip-release rather than untested
inside YAML. tests/release_skip_test.sh pins six cases, including the exact
regression: a message that spells the marker out in prose must still tag.

A marker you cannot mention without triggering is a footgun, not a mechanism.

Bump-Type: patch

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BeAp5LTscnz2W7Ubt4eJ6m
This commit is contained in:
2026-08-23 14:39:31 +02:00
co-authored by Claude Opus 5
parent 78b9b59eca
commit e2a312d05e
3 changed files with 92 additions and 4 deletions
+61
View File
@@ -0,0 +1,61 @@
#!/bin/sh
# Tests for bin/should-skip-release.
#
# The regression these exist for: an unanchored substring match let a commit
# that merely *described* the skip marker skip its own release.
set -u
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
SUT="$ROOT/bin/should-skip-release"
pass=0
fail=0
if [ ! -f "$SUT" ]; then
printf 'FAIL: %s does not exist\n' "$SUT"
exit 1
fi
# expect <skip|tag> <label> <<message on stdin>>
expect() {
_want=$1
_label=$2
_msg=$3
printf '%s\n' "$_msg" | sh "$SUT"
_rc=$?
if [ "$_want" = skip ]; then _wrc=0; else _wrc=1; fi
if [ "$_rc" -eq "$_wrc" ]; then
pass=$((pass + 1)); printf ' ok %s\n' "$_label"
else
fail=$((fail + 1)); printf ' FAIL %s (want %s, rc=%s)\n' "$_label" "$_want" "$_rc"
fi
}
expect skip 'trailer on its own line' 'chore(release): bump
Skip-Release: true'
expect skip 'trailer, case-insensitive' 'chore: x
skip-release: TRUE'
expect tag 'ordinary commit' 'feat: add a thing
Bump-Type: minor'
# --- the actual regression -------------------------------------------------
expect tag 'prose MENTIONING the marker must still tag' 'docs+ci: document the release flow
CI commits the manifest bump with a Skip-Release: true trailer so it does
not re-trigger the tagger. The old [skip-release] marker was a substring
match, which is exactly why this commit would have skipped itself.
Bump-Type: patch'
expect tag 'legacy bracketed marker no longer skips' 'chore: something [skip-release]'
expect tag 'empty message' ''
printf '\nrelease_skip: %d passed, %d failed\n' "$pass" "$fail"
[ "$fail" -eq 0 ]