#!/bin/bash # 開票側門閘的測試(docs/TESTING.md A4) # 判準:4 種該擋、8 種不該擋、1 種有戳記時放行 = 13 條(v1,仍須全過,不能為了 # 新案例把舊的改壞)+ inkstone/ISEP#72 擴大範圍後新增的案例(隱式/小寫 POST、 # milestone/label/PR、org 端點、Arcrun#100 重演)。 cd "$(dirname "$0")/.." || exit 1 H=hooks/ticket-api-bypass-guard.sh PASS=0; FAIL=0 run(){ # $1=want $2=cmd printf '%s' "{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":$(python3 -c 'import json,sys;print(json.dumps(sys.argv[1]))' "$2")}}" \ | bash "$H" >/dev/null 2>&1 got=$? if [ "$got" = "$1" ]; then PASS=$((PASS+1)); printf ' ✅ '; else FAIL=$((FAIL+1)); printf ' ❌ '; fi printf 'want=%s got=%s %.56s\n' "$1" "$got" "$2" } SAVED=""; [ -f /tmp/.ticket-where-ok ] && SAVED=$(cat /tmp/.ticket-where-ok) rm -f /tmp/.ticket-where-ok echo "── 該擋(沒有搜尋戳記,且真的在開新票)──" run 2 'curl -X POST https://git.uncle6.me/api/v1/repos/inkstone/ISEP/issues -d @b.json' run 2 'python3 -c "req(\"POST\", f\"{API}/repos/{REPO}/issues\", {\"title\":\"x\"})"' run 2 'curl --request POST "$API/repos/inkstone/InkStoneCo/issues"' run 2 'req("POST",f"{API}/repos/{REPO}/issues",{"title":"x","labels":[1]})' echo "── 不該擋(誤攔比漏擋更該修)──" run 0 'curl -s "https://git.uncle6.me/api/v1/repos/inkstone/ISEP/issues?state=open"' run 0 'req("POST", f"{API}/repos/{REPO}/issues/14/comments", {"body":"x"})' run 0 'req("POST", f"{API}/repos/{REPO}/issues/5/labels", {"labels":[1]})' run 0 'req("PATCH", f"{API}/repos/{REPO}/issues/5", {"state":"closed"})' run 0 'scripts/ticket new ISEP -F /tmp/b.md --title "x"' run 0 'echo "等一下要開票到 /repos/x/issues"' run 0 'grep -n issues hooks/ticket-api-bypass-guard.sh' run 0 'curl -s "$API/repos/inkstone/Arcrun/issues?state=open&limit=100"' echo "── 有新鮮戳記時放行 ──" python3 -c "import json,time;json.dump({'at':time.time(),'n':0,'top':[]},open('/tmp/.ticket-where-ok','w'))" run 0 'curl -X POST https://git.uncle6.me/api/v1/repos/inkstone/ISEP/issues' rm -f /tmp/.ticket-where-ok echo echo "── ISEP#72:2026-08-27 實際撞到的繞法(v1 grep -qw POST 漏掉的),該擋 ──" run 2 'url = "https://git.uncle6.me/api/v1/repos/inkstone/ISEP/issues"; req = urllib.request.Request(url, data=json.dumps(payload).encode(), headers=h); urllib.request.urlopen(req)' run 2 'python3 -c "requests.post(f\"{API}/repos/{REPO}/issues\", json={\"title\":\"x\"})"' echo echo "── ISEP#72:範圍擴大到 milestone/label/PR,該擋 ──" run 2 'curl -X POST https://git.uncle6.me/api/v1/repos/inkstone/ISEP/milestones -d @m.json' run 2 'curl -X POST https://git.uncle6.me/api/v1/repos/inkstone/ISEP/labels -d @l.json' run 2 'curl -X POST https://git.uncle6.me/api/v1/repos/inkstone/ISEP/pulls -d @p.json' run 2 'curl -X POST https://git.uncle6.me/api/v1/orgs/inkstone/labels -d @l.json' echo echo "── ISEP#72:帶 ID 的 milestone/label/PR 子路徑,不該擋(改狀態/合併,不是新增)──" run 0 'curl -X PATCH https://git.uncle6.me/api/v1/repos/inkstone/ISEP/milestones/3 -d @m.json' run 0 'curl -X PATCH https://git.uncle6.me/api/v1/repos/inkstone/ISEP/labels/9 -d @l.json' run 0 'curl -X POST https://git.uncle6.me/api/v1/repos/inkstone/ISEP/pulls/12/merge' echo echo "── ISEP#72:有戳記時,milestone/label/PR 也放行(不是只有 issues)──" python3 -c "import json,time;json.dump({'at':time.time(),'n':0,'top':[]},open('/tmp/.ticket-where-ok','w'))" run 0 'curl -X POST https://git.uncle6.me/api/v1/repos/inkstone/ISEP/milestones -d @m.json' rm -f /tmp/.ticket-where-ok echo echo "── ISEP#72:Arcrun#100 重演——標題撞同主題舊票,擋下來還要點名 ──" echo " (這條打真實 Gitea 網路;離線環境會印 SKIP,不算失敗。標題故意用" echo " 裸引號的 python dict 寫法,跟 2026-08-27 那 13 張票實際的寫法一致——" echo " curl -d 那種「JSON 被跳脫成字串塞進另一層引號」的寫法,本閘的猜題功能" echo " 刻意不支援,見 hook 檔頭「只認雙引號」那段註解,訊息裡不會列候選舊票," echo " 但擋下來這件事不受影響,另有獨立案例覆蓋。)" if git remote -v 2>/dev/null | grep 'git\.uncle6\.me' | grep -q '@'; then OUT=$(printf '%s' "{\"tool_name\":\"Bash\",\"tool_input\":{\"command\":$(python3 -c 'import json,sys;print(json.dumps(sys.argv[1]))' 'req("POST", f"{API}/repos/{REPO}/issues", {"title":"總圖說我一條關聯都沒有,三元組 graph 全部消失"})')}}" \ | bash "$H" 2>&1 >/dev/null) RC=$? if [ "$RC" = 2 ] && printf '%s' "$OUT" | grep -q 'Arcrun#100'; then PASS=$((PASS+1)); echo " ✅ 擋下來(rc=2)且點名 Arcrun#100" else FAIL=$((FAIL+1)); echo " ❌ rc=$RC,訊息裡有沒有 Arcrun#100:"; printf '%s\n' "$OUT" | grep -q 'Arcrun#100' && echo "有" || echo "沒有" printf '%s\n' "$OUT" fi else echo " ⏭️ SKIP(這台機器的 git remote 沒帶 git.uncle6.me 的憑證,連不上就不算數)" fi [ -n "$SAVED" ] && printf '%s' "$SAVED" > /tmp/.ticket-where-ok echo echo "$PASS/$((PASS+FAIL)) 通過" [ "$FAIL" -eq 0 ]