Files
ISEP/scripts/gitea-bootstrap.sh
T
Leo c2638668e3 ISEP 0.1.0:環境設定收成一個 plugin,本機與雲端共用一份
leo 2026-08-20:「同一個 plugin 你用,薄殼也用,保證兩邊同步」
              「我要你幫雲端做薄殼,永遠都有問題,你要做的就是這組設定
                你自己可以 dogfooding」

搬進來:41 支 hook(51 條註冊)/7 支 command/2 支 skill/23 支腳本。
不搬 .env、wiki、docs——那些是知識不是環境。

51 條 hook 路徑全部從 $CLAUDE_PROJECT_DIR/.claude/hooks/ 改成 ${CLAUDE_PLUGIN_ROOT}/hooks/,
零漏網。那正是薄殼一直壞掉的根:雲端 cwd 不是真身,寫死路徑就斷。

尚未驗證:Claude Code 能不能從私有 Gitea repo 裝 marketplace(要憑證)。
下一步就是在本機實際裝一次,通了才動雲端 bootstrap.sh。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-20 11:41:46 +08:00

81 lines
4.7 KiB
Bash
Executable File
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/sh
# gitea-bootstrap.sh — 新 repo 開通工作管理元件(狀態標籤)。冪等,重跑無害。
#
# 為什麼是腳本不是一段叮嚀(leo 2026-08-09:「每到一個新的 repo 就要建立這些管理元件」):
# 靠人/靠 AI 記得 = 必然漂移。今天一天就抓到三條「規則寫了沒人驗」。
# label 是 repo-scoped、沒有跨 repo 繼承 ⇒ 每個 repo 都要建一次 ⇒ 必須一行做完。
#
# 用法(在該 repo 目錄下跑,或用 -r 指定):
# scripts/gitea-bootstrap.sh # 用當前 repo 的 gitea remote
# scripts/gitea-bootstrap.sh -r Leo/some-repo # 指定 repotoken 仍從當前 repo 取)
#
# milestone 不在這裡建——milestone sprint 一次交貨,每個 repo 的交貨內容不同,
# 不能預設。建法見 /issue-handle skill。
set -eu
REPO=""
[ "${1:-}" = "-r" ] && { REPO="${2:?-r 後面要接 owner/repo}"; }
REMOTE=$(git remote get-url gitea 2>/dev/null) || {
echo "✗ 當前目錄沒有名為 gitea 的 remote。請 cd 到目標 repo,或先加 remote。" >&2; exit 1; }
TOKEN=$(printf '%s' "$REMOTE" | sed -E 's|.*//[^:]+:([^@]+)@.*|\1|')
[ "$TOKEN" = "$REMOTE" ] && { echo "✗ gitea remote URL 裡沒有 token,無法取得認證。" >&2; exit 1; }
HOST=$(printf '%s' "$REMOTE" | sed -E 's|.*@([^/]+)/.*|\1|')
[ -n "$REPO" ] || REPO=$(printf '%s' "$REMOTE" | sed -E 's|.*://[^/]+/(.+)\.git$|\1|')
echo "→ repo: $REPO host: $HOST"
# 狀態機(互斥 scope label)。順序=出貨流程:
# s/todo → s/doing → s/stage →(leo 蓋章 + arm + 推 prod)→ closed
# 🔴 不建 s/doneclosed 就是 done,多一個就是同一件事兩個真相。
# 🔴 s/triage 存在的理由:**「留白」查不出來**。撈得到 s/todo,卻撈不到
# 「所有還沒驗傷的」——沒有標籤不是一種狀態,是查詢的死角
# leo 2026-08-09 建 Triage 看板時暴露的設計缺陷)。
# p/ 是另一個軸:s/ 答「走到哪」、p/ 答「多重要」——
# s/backlog 的東西也可以是 p/high,併成一組就表達不出來。
set -- \
's/triage|d4c5f9|新進來的,還沒驗傷——還沒決定要不要做' \
's/backlog|c2e0c6|驗過了、確定要做,但還沒排進任何 sprint(wishlist/功能需求/待規劃)' \
's/todo|ededed|已排進 sprint,等開工' \
's/doing|0e8a16|進行中——現在有人在做' \
's/stage|5319e7|已推上 stage,等 leo 去 youlin 的 stage 環境驗收(出貨流程第⑤步)' \
's/pending|fbca04|卡住——等外部/等人,不是沒人做' \
'p/high|b60205|高——擋住交付或有時間壓力' \
'p/low|bfd4f2|低——想做,但晚一點沒關係'
# 🔴 先抓現有清單再建。**Gitea 允許同名 label、回 201 不是 422**
# ⇒ 靠「重複會被擋」達成冪等是錯的。2026-08-09 實撞:本腳本第一版
# 在 arcrun-rag 造出每個標籤各兩份——那會直接弄壞互斥狀態機(同名兩個 id,
# 貼哪一個都不會把另一個頂掉),事後手動刪掉四個重複 id 才救回來。
EXISTING=$(curl -s -H "Authorization: token $TOKEN" -H "Cache-Control: no-cache" \
"https://$HOST/api/v1/repos/$REPO/labels?limit=100" \
| python3 -c "import json,sys;print(' '.join(l['name'] for l in json.load(sys.stdin)))")
created=0; existed=0; failed=0
for spec in "$@"; do
name=${spec%%|*}; rest=${spec#*|}; color=${rest%%|*}; desc=${rest#*|}
case " $EXISTING " in *" $name "*) echo " · 已存在 $name"; existed=$((existed+1)); continue ;; esac
payload=$(NAME="$name" COLOR="$color" DESC="$desc" python3 -c '
import json,os
print(json.dumps({"name":os.environ["NAME"],"color":"#"+os.environ["COLOR"],
"description":os.environ["DESC"],"exclusive":True}))')
code=$(printf '%s' "$payload" | curl -s -o /tmp/.bootstrap-out -w '%{http_code}' \
-X POST -H "Authorization: token $TOKEN" -H "Content-Type: application/json" \
--data-binary @- "https://$HOST/api/v1/repos/$REPO/labels")
case "$code" in
201) echo " ✓ 建立 $name"; created=$((created+1)) ;;
422) echo " · 已存在 $name"; existed=$((existed+1)) ;;
*) echo " ✗ $name → HTTP $code: $(head -c 120 /tmp/.bootstrap-out)"; failed=$((failed+1)) ;;
esac
done
# 複驗:從 repo 端讀回來,不信自己送出的指令(2026-08-09 教訓:宣告 vs 證據)
echo "→ 複驗(從 repo 讀回):"
curl -s -H "Authorization: token $TOKEN" -H "Cache-Control: no-cache" \
"https://$HOST/api/v1/repos/$REPO/labels?limit=100" \
| python3 -c "import json,sys;print(' ',sorted(l['name'] for l in json.load(sys.stdin) if l['name'].startswith('s/')))"
echo "→ 新建 $created/已存在 $existed/失敗 $failed"
[ "$failed" -eq 0 ] || exit 1