Files
system-dev-template/scripts/update.sh
T
Leo 25cb4d1f63 feat: v1.2.0 — issue 處理指引 + pre-write-guard 定位釐清 + 開發 wiki 隔離
issue #1:新增 /issue-handle slash command,CC 處理 GitHub issue 的
普世指引——讀回自己 repo 直接做、跨 repo 發要先問人、禁掛 Actions/cron
自動輪詢(會觸發 GitHub 異常偵測)。屬共用指引,install/update 不分模組裝。

issue #2:pre-write-guard.sh 釐清定位為「按需手填的空插槽」,非裝上就
生效的警察。檔頭明講有 CC 在場時直接叫 CC 寫貼合的 guard 更好;install/
update 安裝時提示「預設不攔,要手填才生效」,消除安全錯覺。hook 執行維持
安靜不洗版。

另:repo 自己裝了一套開發用 wiki(內部記錄),與 template/ 成品範本實體
隔離,.gitignore 排除 .claude/wiki/、.claude/hooks/、.claude/VERSION,
不推 GitHub。

升版 1.2.0,CHANGELOG 記錄。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-23 12:20:23 +08:00

176 lines
7.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
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/bash
# system-dev-template updater
# 已安裝舊版的人,一鍵更新到新版。
#
# 核心安全原則:只覆蓋「模板/邏輯檔」,絕不碰「使用者資料檔」。
# ✅ 可覆蓋:hooks/*.sh、commands/*.md、TEMPLATE-*、wiki/INDEX.md
# ——這些由模板維護,使用者不會手改,新版直接換掉。
# 🔒 絕不碰:wiki/status.md、mistakes.md、decisions-summary.md、.wikiignore、
# settings.json、CLAUDE.md
# ——這些是使用者自己填的內容,覆蓋=清空他的記憶與設定。
#
# 「第一次更新」的雞生蛋問題:
# 舊版本機沒有 update.sh。所以第一次靠 README 那行 curl 從遠端抓這支腳本來跑。
# 跑完它會把自己也更新進 scripts/update.sh,之後就能直接跑本機的 `bash scripts/update.sh`。
set -euo pipefail
REPO_RAW="https://raw.githubusercontent.com/uncle6me-web/system-dev-template/main"
TEMPLATE_URL="$REPO_RAW/template"
UPDATED=()
KEPT=()
NEW=()
# ── 版本比對:先看本機 vs 遠端,給使用者「值不值得更新」的判斷 ──
LOCAL_VER="(未知)"
[ -f ".claude/VERSION" ] && LOCAL_VER="$(tr -d '[:space:]' < .claude/VERSION)"
REMOTE_VER="$(curl -sSL "$TEMPLATE_URL/.claude/VERSION" 2>/dev/null | tr -d '[:space:]' || echo '')"
echo ""
echo "🔄 system-dev-template updater"
echo "================================="
echo " 本機版本:${LOCAL_VER:-未知}"
echo " 最新版本:${REMOTE_VER:-取不到(檢查網路)}"
echo ""
if [ -z "$REMOTE_VER" ]; then
echo "❌ 取不到遠端版本,可能是網路問題。請稍後再試。"
exit 1
fi
if [ "$LOCAL_VER" = "$REMOTE_VER" ]; then
echo "✅ 已是最新版($LOCAL_VER),不需更新。"
echo " (仍會同步模板邏輯檔,確保 hooks/commands 與最新一致。)"
echo ""
fi
# ── 工具函式 ───────────────────────────────────────
# 覆蓋更新:模板/邏輯檔,無條件抓最新版蓋掉。
update_file() {
local dest="$1" src="$2"
mkdir -p "$(dirname "$dest")"
if [ -f "$dest" ]; then
if curl -sSL "$src" -o "$dest.tmp" 2>/dev/null && [ -s "$dest.tmp" ]; then
if cmp -s "$dest" "$dest.tmp"; then
rm -f "$dest.tmp" # 內容相同,不算更新
else
mv "$dest.tmp" "$dest"
UPDATED+=("$dest")
fi
else
rm -f "$dest.tmp"
echo " ⚠️ 抓取失敗,保留原檔:$dest"
fi
else
if curl -sSL "$src" -o "$dest" 2>/dev/null && [ -s "$dest" ]; then
NEW+=("$dest") # 新功能:舊版沒有的檔
else
rm -f "$dest"
echo " ⚠️ 抓取失敗:$dest"
fi
fi
}
# 保留:使用者資料檔,只記錄「有保留」,永遠不動。
keep_file() {
[ -f "$1" ] && KEPT+=("$1") || true
}
# ── 偵測已安裝哪些模組(依現有檔案判斷,更新只動已裝的)──
HAS_WIKI=false
HAS_SDD=false
[ -d ".claude/wiki" ] && HAS_WIKI=true
if [ -f ".claude/hooks/sdd-guard.sh" ] || [ -d "docs/3-specs/TEMPLATE-sdd" ]; then HAS_SDD=true; fi
echo "📦 偵測到已安裝模組:"
$HAS_WIKI && echo " • LLM Wiki"
$HAS_SDD && echo " • SDD"
{ $HAS_WIKI || $HAS_SDD; } || echo " (未偵測到任何模組——這裡可能還沒安裝,請改跑 install.sh"
echo ""
# ── 模板/邏輯檔:覆蓋更新 ──────────────────────────
# 共用 hook 與指引
update_file ".claude/hooks/pre-write-guard.sh" "$TEMPLATE_URL/.claude/hooks/pre-write-guard.sh"
update_file ".claude/commands/issue-handle.md" "$TEMPLATE_URL/.claude/commands/issue-handle.md"
update_file ".claude/VERSION" "$TEMPLATE_URL/.claude/VERSION"
if $HAS_WIKI; then
# wiki 的「邏輯檔」:導航與 hooks,可覆蓋
update_file ".claude/wiki/INDEX.md" "$TEMPLATE_URL/.claude/wiki/INDEX.md"
update_file ".claude/hooks/session-start-recall.sh" "$TEMPLATE_URL/.claude/hooks/session-start-recall.sh"
update_file ".claude/hooks/wiki-secret-scan.sh" "$TEMPLATE_URL/.claude/hooks/wiki-secret-scan.sh"
update_file ".claude/commands/wiki-init.md" "$TEMPLATE_URL/.claude/commands/wiki-init.md"
update_file ".claude/commands/wiki-capture.md" "$TEMPLATE_URL/.claude/commands/wiki-capture.md"
update_file ".claude/commands/wiki-update.md" "$TEMPLATE_URL/.claude/commands/wiki-update.md"
update_file ".claude/commands/wiki-recall.md" "$TEMPLATE_URL/.claude/commands/wiki-recall.md"
# wiki 的「使用者資料」:絕不碰
keep_file ".claude/wiki/status.md"
keep_file ".claude/wiki/mistakes.md"
keep_file ".claude/wiki/decisions-summary.md"
keep_file ".claude/wiki/.wikiignore"
fi
if $HAS_SDD; then
# SDD 範本與 hook:可覆蓋
update_file "docs/3-specs/TEMPLATE-sdd/design.md" "$TEMPLATE_URL/docs/3-specs/TEMPLATE-sdd/design.md"
update_file "docs/3-specs/TEMPLATE-sdd/tasks.md" "$TEMPLATE_URL/docs/3-specs/TEMPLATE-sdd/tasks.md"
update_file "docs/2-architecture/decisions/TEMPLATE-adr.md" "$TEMPLATE_URL/docs/2-architecture/decisions/TEMPLATE-adr.md"
update_file ".claude/commands/sdd-check.md" "$TEMPLATE_URL/.claude/commands/sdd-check.md"
update_file ".claude/hooks/sdd-guard.sh" "$TEMPLATE_URL/.claude/hooks/sdd-guard.sh"
fi
# ── 自我更新:把最新的 update.sh 也抓下來(含 install.sh)──
# 這兩支在 main/scripts/ 下,不在 template/。
update_file "scripts/update.sh" "$REPO_RAW/scripts/update.sh"
update_file "scripts/install.sh" "$REPO_RAW/scripts/install.sh"
chmod +x .claude/hooks/*.sh scripts/*.sh 2>/dev/null || true
# ── 使用者資料檔:絕不碰,但提醒「設定可能有新欄位要手動補」──
keep_file ".claude/settings.json"
keep_file "CLAUDE.md"
# ── 結果輸出 ───────────────────────────────────────
echo ""
echo "─────────────────────────────────"
if [ ${#NEW[@]} -gt 0 ]; then
echo ""
echo "🆕 新功能(舊版沒有,已加入):"
for f in "${NEW[@]}"; do echo " + $f"; done
fi
if [ ${#UPDATED[@]} -gt 0 ]; then
echo ""
echo "⬆️ 已更新(覆蓋成新版):"
for f in "${UPDATED[@]}"; do echo " ~ $f"; done
fi
if [ ${#NEW[@]} -eq 0 ] && [ ${#UPDATED[@]} -eq 0 ]; then
echo ""
echo "✨ 模板邏輯檔已全部最新,無需變動。"
fi
if [ ${#KEPT[@]} -gt 0 ]; then
echo ""
echo "🔒 完整保留(你的內容/設定,從未碰過):"
for f in "${KEPT[@]}"; do echo " = $f"; done
fi
# ── settings.json 提醒:新模組 hook 可能要手動補 ──
if [ -f ".claude/settings.json" ]; then
MISSING=()
$HAS_WIKI && ! grep -q "session-start-recall.sh" .claude/settings.json && MISSING+=("SessionStart: session-start-recall.sh")
$HAS_WIKI && ! grep -q "wiki-secret-scan.sh" .claude/settings.json && MISSING+=("PreToolUse(Write|Edit): wiki-secret-scan.sh")
$HAS_SDD && ! grep -q "sdd-guard.sh" .claude/settings.json && MISSING+=("PreToolUse(Write|Edit): sdd-guard.sh")
if [ ${#MISSING[@]} -gt 0 ]; then
echo ""
echo "📌 settings.json 是你的設定(沒動),但偵測到缺以下 hook,請手動補上:"
for h in "${MISSING[@]}"; do echo " • $h"; done
fi
fi
echo ""
echo "🚀 更新完成:${LOCAL_VER}${REMOTE_VER}"
echo " 下次更新直接跑:bash scripts/update.sh"
echo " 改了什麼看:CHANGELOG.md"
echo ""