#!/usr/bin/env bash # scripts/release-check 的迴歸測試(inkstone/ISEP#67) # # 兩個方向都要有證據: # A 群「該擋」(exit 2)——現行版本缺 tag 或缺 release,且**說得出缺哪一站+怎麼補** # (這就是工單驗收 4:「故意漏一步 → 管線要擋下來並說出缺哪一站」) # B 群「該過」(exit 0)——現行版本 tag+release 都在;更舊版本缺件只黃字提醒不擋; # 指定版本時看的是那一版;裁定不補的版本不再黃字 # # 🔴 全程離線(RELEASE_CHECK_FIXTURE),不打 Gitea。fixture 直接給收貨端與送貨端的事實。 set -u TOOL="${1:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/release-check}" TMP=$(mktemp -d); trap 'rm -rf "$TMP"' EXIT PASS=0; FAIL=0; N=0 mkfx() { # $1=檔名 之後 heredoc cat > "$TMP/$1" } # t <期望exit> <說明> <必須出現的字串> [額外參數…] t() { want="$1"; desc="$2"; must="$3"; fx="$4"; shift 4 N=$((N+1)) out=$(RELEASE_CHECK_FIXTURE="$TMP/$fx" 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,16p' | sed 's/^/ /'; FAIL=$((FAIL+1)) fi } # not <說明> <不該出現的字串> [額外參數…] not() { desc="$1"; bad="$2"; fx="$3"; shift 3 N=$((N+1)) out=$(RELEASE_CHECK_FIXTURE="$TMP/$fx" 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:這就是 2026-09-07 的真實狀態——v0.24.0 有 tag、沒 release mkfx a1.json <<'JSON' {"current":"0.24.0", "dingban":["0.24.0","0.23.0","0.22.0"], "tags":["v0.24.0","v0.23.0","v0.22.0"], "releases":["v0.22.0"], "loaded":"0.24.0"} JSON t 2 "現行 v0.24.0 有 tag 沒 release → 擋,且指名缺 release 站" "缺這一站:release(Gitea)" a1.json t 2 "缺 release 時給得出補法,而且是正本的絕對路徑(貼了就能跑)" "$(dirname "$TOOL")/release-ship v0.24.0" a1.json # A2:連 tag 都沒有(定版了、tag 沒推) mkfx a2.json <<'JSON' {"current":"0.20.0", "dingban":["0.20.0","0.18.0"], "tags":["v0.18.0"], "releases":["v0.18.0"], "loaded":"0.20.0"} JSON t 2 "現行版本連 tag 都沒有 → 擋,且指名缺 tag 站" "缺這一站:tag(Gitea)" a2.json t 2 "缺 tag 時給得出補法(push tag)" "git push origin v0.20.0" a2.json # A3:指定版本 → 判的是那一版 mkfx a3.json <<'JSON' {"current":"0.24.0", "dingban":["0.24.0","0.23.0"], "tags":["v0.24.0","v0.23.0"], "releases":["v0.24.0"], "loaded":"0.24.0"} JSON t 2 "指定 v0.23.0 而它沒 release → 擋(就算工作樹宣稱的 v0.24.0 是好的)" "現行版本 v0.23.0 的送貨端斷了" a3.json v0.23.0 t 0 "同一份事實不指定版本 → 看 v0.24.0,放行" "送貨端完成" a3.json echo "── B 群:該過(現行版本 tag+release 都在)──" # B1:全部送到 mkfx b1.json <<'JSON' {"current":"0.18.0", "dingban":["0.18.0","0.9.0"], "tags":["v0.18.0","v0.9.0"], "releases":["v0.18.0","v0.9.0"], "loaded":"0.18.0"} JSON t 0 "現行版本 tag+release 都在 → 放行" "送貨端完成" b1.json # B2:現行版本送到了,但更舊的 定版 版本缺件 → 仍放行,只黃字 mkfx b2.json <<'JSON' {"current":"0.24.0", "dingban":["0.24.0","0.23.0","0.22.0"], "tags":["v0.24.0","v0.22.0"], "releases":["v0.24.0","v0.22.0"], "loaded":"0.24.0"} JSON t 0 "現行送到、舊版缺件 → 放行(不 over-block)" "送貨端完成" b2.json t 0 "舊版缺件會被黃字提醒出來" "v0.23.0 缺:tag(Gitea)+release(Gitea)" b2.json # B3:載入端落後(送貨端完成,但這個 session 掛的是舊版)→ 仍 exit 0,但要報出來 mkfx b3.json <<'JSON' {"current":"0.22.0", "dingban":["0.22.0","0.18.0"], "tags":["v0.22.0","v0.18.0"], "releases":["v0.22.0","v0.18.0"], "loaded":"0.21.0"} JSON t 0 "載入端落後 → 送貨端仍算完成(exit 0)" "送貨端完成" b3.json t 0 "載入端落後會被明確報出+給 update/重啟的修法" "載入端落後" b3.json # B4:裁定不補的三版(總管 09-07)→ 不再黃字,表上標「裁定不補」 mkfx b4.json <<'JSON' {"current":"0.24.0", "dingban":["0.24.0","0.22.0","0.21.0","0.20.0","0.19.0","0.18.0"], "tags":["v0.24.0","v0.22.0","v0.18.0"], "releases":["v0.24.0","v0.22.0","v0.18.0"], "loaded":"0.24.0"} JSON t 0 "v0.19/0.20/0.21 缺 tag+release 但已裁定不補 → 表上標出裁決出處" "裁定不補(inkstone/ISEP#67 → 6574)" b4.json not "裁定不補的版本不再黃字念(天天念會被學會忽略)" "更舊的定版版本也缺件" b4.json t 2 "但指定 v0.21.0 來問,它就是現行、照擋(裁決只免黃字,不改事實)" "現行版本 v0.21.0 的送貨端斷了" b4.json v0.21.0 echo "" echo "──────────────────────────────" printf '共 %d 項:✅ %d / ❌ %d\n' "$N" "$PASS" "$FAIL" [ "$FAIL" -eq 0 ]