fef35ed03a
- hooks/lib/release_chain.py:問 Gitea 的判準一份三處用(匿名讀,D20) - scripts/release-ship:前置①比「要建的那個 tag 的樹」裡的 plugin.json,不比工作樹/最新 tag (總管 09-07 在 v0.23.0 被擋的情境現在放行);note 從 Gitea compare 生,從 plugin 快取跑也行; 覆核改跑 release-check <那個 tag> - scripts/release-check [vX.Y.Z]:指定版本;v0.19/0.20/0.21 依裁決標「不補」不再黃字;補法印正本絕對路徑 - hooks/lib/beacon_report.py ④:最新 tag 沒 release/main 定版沒打 tag ⇒ 一行缺站+補法;都在安靜; 只快取「都在」6 小時 - 測試:test-release-ship 14、test-release-check 14、信標 26→33;docs:TESTING A37/A38、盤點表、README 60 支腳本、 白名單加 release-ship/release-check 形狀、mistakes 一條 - 沒改 plugin.json 版本號(待總管定版) Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0178ef1fGw3XeZtpN7LaZrm4
117 lines
5.9 KiB
Bash
Executable File
117 lines
5.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# scripts/release-ship 的迴歸測試(inkstone/ISEP#67)
|
||
#
|
||
# 兩個方向都要有證據:
|
||
# A 群「該擋」(exit 2)——前置條件沒滿足就不給建 release,且說得出是哪一個前置
|
||
# ① 那個 tag 的樹裡 plugin.json 跟 tag 號碼對不上 ② Gitea 上沒那個 tag ③ 版本寫法不對
|
||
# B 群「該放行」(exit 0)——前置都在就建;release 已存在則冪等不重複建;--dry-run 不 POST;
|
||
# 🔴 **不是最新的那個 tag 也建得了**(總管 09-07 在 v0.23.0 被擋的那個情境)
|
||
#
|
||
# 🔴 全程離線(RELEASE_SHIP_FIXTURE + RELEASE_SHIP_SINK),不打 Gitea、不建任何真 release。
|
||
# fixture 的形狀見 hooks/lib/release_chain.py `Chain` 的註解。
|
||
set -u
|
||
TOOL="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/release-ship}"
|
||
TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT
|
||
PASS=0; FAIL=0; N=0
|
||
|
||
# 🔴 工作樹故意擺一個跟任何 tag 都對不上的版本:前置①要是偷看工作樹,B 群會整組紅
|
||
WT="$TMP/worktree"; mkdir -p "$WT/.claude-plugin"
|
||
printf '{"name":"isep","version":"9.9.9"}\n' > "$WT/.claude-plugin/plugin.json"
|
||
export CLAUDE_PROJECT_DIR="$WT"
|
||
|
||
# t <期望exit> <說明> <必須出現的字串> <fixture檔> [額外參數…]
|
||
t() {
|
||
want="$1"; desc="$2"; must="$3"; fx="$4"; shift 4
|
||
N=$((N+1))
|
||
rm -f "$TMP/sink.json" "$TMP/sink.json.checkfx.json"
|
||
out=$(RELEASE_SHIP_FIXTURE="$TMP/$fx" RELEASE_SHIP_SINK="$TMP/sink.json" \
|
||
python3 "$TOOL" "$@" 2>&1); rc=$?
|
||
ok=1
|
||
[ "$rc" -eq "$want" ] || ok=0
|
||
if [ -n "$must" ] && ! printf '%s' "$out" | grep -qF "$must"; then ok=0; fi
|
||
if [ "$ok" -eq 1 ]; then printf ' ✅ %s\n' "$desc"; PASS=$((PASS+1))
|
||
else
|
||
printf ' ❌ %s —— 期望 exit=%s%s,實得 exit=%s\n' "$desc" "$want" \
|
||
"${must:+ 且輸出含「$must」}" "$rc"
|
||
printf '%s\n' "$out" | sed -n '1,14p' | sed 's/^/ /'; FAIL=$((FAIL+1))
|
||
fi
|
||
}
|
||
# not <說明> <不該出現的字串> <fixture檔> [額外參數…]
|
||
not() {
|
||
desc="$1"; bad="$2"; fx="$3"; shift 3
|
||
N=$((N+1))
|
||
rm -f "$TMP/sink.json" "$TMP/sink.json.checkfx.json"
|
||
out=$(RELEASE_SHIP_FIXTURE="$TMP/$fx" RELEASE_SHIP_SINK="$TMP/sink.json" \
|
||
python3 "$TOOL" "$@" 2>&1)
|
||
if printf '%s' "$out" | grep -qF "$bad"; then
|
||
printf ' ❌ %s —— 不該出現卻出現了:%s\n' "$desc" "$bad"; FAIL=$((FAIL+1))
|
||
else printf ' ✅ %s\n' "$desc"; PASS=$((PASS+1)); fi
|
||
}
|
||
|
||
echo "── A 群:該擋(前置條件沒滿足)──"
|
||
|
||
# A1:tag 的樹裡 plugin.json 跟 tag 號碼對不上(這種 tag 本來就不該存在)
|
||
cat > "$TMP/a1.json" <<'JSON'
|
||
{"tags":["v0.22.0"],"manifest":{"v0.22.0":"0.21.0"},"releases":[]}
|
||
JSON
|
||
t 2 "tag 的樹裡 plugin.json 是 0.21.0、tag 是 v0.22.0 → 擋,指名前置①" "前置①" a1.json v0.22.0
|
||
t 2 "前置①被擋時講得出修法(刪 tag、重新定版)" "重新定版" a1.json v0.22.0
|
||
|
||
# A2:Gitea 上沒有這個 tag
|
||
cat > "$TMP/a2.json" <<'JSON'
|
||
{"tags":["v0.18.0"],"manifest":{"v0.18.0":"0.18.0"},"releases":["v0.18.0"]}
|
||
JSON
|
||
t 2 "Gitea 沒有該 tag → 擋,指名前置②+叫人先推 tag" "git push origin v0.22.0" a2.json v0.22.0
|
||
|
||
# A3:版本寫法不對
|
||
cat > "$TMP/a3.json" <<'JSON'
|
||
{"tags":[],"releases":[]}
|
||
JSON
|
||
t 2 "版本寫法不對 → 擋" "版本寫法" a3.json "0.22"
|
||
|
||
echo "── B 群:該放行 ──"
|
||
|
||
# B1:前置都在、release 還沒建 → 建(fixture sink),然後覆核通過
|
||
cat > "$TMP/b1.json" <<'JSON'
|
||
{"current":"0.22.0","dingban":["0.22.0","0.18.0"],"loaded":"0.22.0",
|
||
"tags":["v0.22.0","v0.18.0"],"manifest":{"v0.22.0":"0.22.0","v0.18.0":"0.18.0"},
|
||
"releases":["v0.18.0"],
|
||
"commits":{"v0.18.0...v0.22.0":["定版 v0.22.0(ship-check 送得到)","修一支閘(inkstone/ISEP#1)"]}}
|
||
JSON
|
||
t 0 "前置齊全、release 缺 → 建起來" "已建立 release「v0.22.0 — ship-check 送得到」" b1.json v0.22.0
|
||
t 0 "建完回頭跑 release-check 覆核(問收貨端)" "覆核(release-check v0.22.0" b1.json v0.22.0
|
||
t 0 "note 自動從 Gitea 的 commit 清單生成(不靠本機 git log)" "commit 清單自動生成" b1.json v0.22.0
|
||
|
||
# B2:release 已存在 → 冪等,不重複建、不動它
|
||
cat > "$TMP/b2.json" <<'JSON'
|
||
{"current":"0.18.0","dingban":["0.18.0"],"loaded":"0.18.0",
|
||
"tags":["v0.18.0"],"manifest":{"v0.18.0":"0.18.0"},"releases":["v0.18.0"]}
|
||
JSON
|
||
t 0 "release 已存在 → 冪等放行、不重複建" "本來就在了" b2.json v0.18.0 --notes-file "$TMP/b2.json"
|
||
not "release 已存在時不准說「已建立」(09-05 那句假綠)" "已建立 release" b2.json v0.18.0
|
||
|
||
# B3:--dry-run 不 POST
|
||
cat > "$TMP/b3.json" <<'JSON'
|
||
{"tags":["v0.22.0"],"manifest":{"v0.22.0":"0.22.0"},"releases":[]}
|
||
JSON
|
||
t 0 "--dry-run 全走一遍但不 POST" "不 POST" b3.json v0.22.0 --dry-run
|
||
not "--dry-run 不寫 sink(真的沒建)" "fixture-created" b3.json v0.22.0 --dry-run
|
||
|
||
# B4:🔴 不是最新的 tag 也建得了(總管 09-07:在 v0.23.0 的 checkout 跑被擋,訊息說最新是 v0.24.0)
|
||
cat > "$TMP/b4.json" <<'JSON'
|
||
{"current":"0.24.0","dingban":["0.24.0","0.23.0","0.22.0"],"loaded":"0.24.0",
|
||
"tags":["v0.24.0","v0.23.0","v0.22.0"],
|
||
"manifest":{"v0.24.0":"0.24.0","v0.23.0":"0.23.0","v0.22.0":"0.22.0"},
|
||
"releases":["v0.22.0"],
|
||
"commits":{"v0.22.0...v0.23.0":["定版 v0.23.0(雲端拿得到票與主線)"]}}
|
||
JSON
|
||
t 0 "最新 tag 是 v0.24.0,要建的是 v0.23.0 → 照建(前置①看 tag 的樹,不看「最新」)" \
|
||
"已建立 release「v0.23.0 — 雲端拿得到票與主線」" b4.json v0.23.0
|
||
t 0 "覆核的是 v0.23.0 這一版,不是工作樹宣稱的 0.24.0" "v0.23.0 ✅ ✅ ✅ ←" b4.json v0.23.0
|
||
not "工作樹 plugin.json 是 9.9.9 也不會被拿來比(B 群全綠就是證據,這條釘住訊息)" "9.9.9" b4.json v0.23.0
|
||
|
||
echo ""
|
||
echo "──────────────────────────────"
|
||
printf '共 %d 項:✅ %d / ❌ %d\n' "$N" "$PASS" "$FAIL"
|
||
[ "$FAIL" -eq 0 ]
|