fix(scripts): template 來源改指活帳號,404 不再靜默寫入垃圾內容
scripts/install.sh 與 scripts/update.sh 的更新來源指向已被 GitHub suspend 的 uncle6me-web 帳號,實測全部 404 ⇒ 自動更新靜默失效。改成與 system-dev-template 本體、以及本 repo 現行世代 system-dev/scripts/ 一致的正解:預設公開 GitHub youlinhsieh/system-dev-template,可用 TEMPLATE_SOURCE 環境變數覆寫,不改檔。 同時補上 looks_like_error_page 判斷(沿用 template repo 已修好的寫法):curl 對 404 常回傳非空的錯誤頁內容,只判斷「非空」會把它當成正常檔案寫入且不報錯。 現在錯誤頁會被偵測、檔案不寫入、FAILED 清單於結尾列出、腳本以非零狀態碼結束。 實測: - 修正後來源多個路徑回真實 HTTP 200(CLAUDE.md/VERSION/self-update 兩支腳本)。 - 刻意把 TEMPLATE_SOURCE 指回死帳號重跑兩支腳本:全部項目進 FAILED 清單、 無任何檔案被錯誤頁污染、exit code 1。 - 兩支腳本 bash -n 語法檢查通過。 已知缺口(不在本次範圍,留待另決):template repo 內部檔案佈局已從 .claude/wiki/、docs/ 搬到 system-dev/ 前綴,這兩支舊世代腳本仍用舊路徑, 其中一部分檔案(wiki 範本、docs/README、SDD 範本等)在新帳號上仍 404—— 現在會清楚回報失敗而不是靜默吞掉,但尚未逐一改點新路徑。 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
+42
-3
@@ -26,9 +26,29 @@ t() { if [ "$IS_ZH" = "yes" ]; then printf '%s\n' "$1"; else printf '%s\n' "$2";
|
||||
# tn = 不換行版(給 prompt 用)
|
||||
tn() { if [ "$IS_ZH" = "yes" ]; then printf '%s' "$1"; else printf '%s' "$2"; fi; }
|
||||
|
||||
REPO_URL="https://raw.githubusercontent.com/uncle6me-web/system-dev-template/main/template"
|
||||
# 來源預設=公開 GitHub(leo 2026-07-21:「要發佈的正稿,從頭就不要用奇怪的網址,
|
||||
# 以免改來改去」)。舊的 uncle6me-web 帳號已被 suspend(讀 404)=自動更新靜默失效,
|
||||
# 這顆雷已在 system-dev-template 本體修過(正解=改指 youlinhsieh 這個公開帳號),
|
||||
# 這裡只是把同一個修法補進 Arcrun 這份沒跟到的 copy。
|
||||
# 內部要指私有草稿源時用環境變數覆寫,不改檔:
|
||||
# TEMPLATE_SOURCE=https://<私有 raw base> bash scripts/install.sh
|
||||
TEMPLATE_SOURCE="${TEMPLATE_SOURCE:-https://raw.githubusercontent.com/youlinhsieh/system-dev-template/main}"
|
||||
REPO_URL="$TEMPLATE_SOURCE/template"
|
||||
CREATED=()
|
||||
SKIPPED=()
|
||||
FAILED=()
|
||||
|
||||
# 404 頁面常常「非空」(GitHub raw 對不存在的路徑回 "404: Not Found"),
|
||||
# 只判斷 [ -s file ] 會把錯誤頁內容當成檔案寫進去且完全不報錯(template issue #13 撞過的雷)。
|
||||
# 這裡量身做一個輕量判斷:檔案很短又長得像錯誤訊息 → 當失敗。
|
||||
looks_like_error_page() {
|
||||
local f="$1"
|
||||
[ -s "$f" ] || return 0
|
||||
if [ "$(wc -l < "$f" | tr -d ' ')" -le 2 ] && head -c 200 "$f" | grep -qiE '40[0-9]|not found|<html'; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# ── 解析模組參數 ──────────────────────────────────
|
||||
MODULE=""
|
||||
@@ -211,8 +231,12 @@ download_if_missing() {
|
||||
local dest="$1" src="$2"
|
||||
if [ ! -f "$dest" ]; then
|
||||
mkdir -p "$(dirname "$dest")"
|
||||
curl -sSL "$src" -o "$dest"
|
||||
CREATED+=("$dest")
|
||||
if curl -sSL "$src" -o "$dest" 2>/dev/null && ! looks_like_error_page "$dest"; then
|
||||
CREATED+=("$dest")
|
||||
else
|
||||
rm -f "$dest"
|
||||
FAILED+=("$dest $(tn "(來源抓不到:$src)" "(source unreachable: $src)")")
|
||||
fi
|
||||
else
|
||||
SKIPPED+=("$dest $(tn '(已存在,跳過)' '(already exists, skipped)')")
|
||||
fi
|
||||
@@ -332,6 +356,16 @@ if [ ${#SKIPPED[@]} -gt 0 ]; then
|
||||
for item in "${SKIPPED[@]}"; do echo " - $item"; done
|
||||
fi
|
||||
|
||||
# 來源抓不到要出聲,不能安靜吞掉——404 內容不會被寫進檔案(已在 download_if_missing 擋掉),
|
||||
# 但使用者必須知道「這幾個檔沒裝到」,不然會誤以為裝完整了。
|
||||
if [ ${#FAILED[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
t "❌ 抓取失敗(來源不可達,未寫入任何檔案):" "❌ Fetch failed (source unreachable, no file was written):"
|
||||
for item in "${FAILED[@]}"; do echo " x $item"; done
|
||||
t " 請檢查網路,或用 TEMPLATE_SOURCE=<其他來源> 重跑。" \
|
||||
" Check your network, or rerun with TEMPLATE_SOURCE=<alternate source>."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "─────────────────────────────────"
|
||||
|
||||
@@ -429,3 +463,8 @@ fi
|
||||
t " GitHub issue:CC 可直接 /issue-handle 讀回自己 repo 的 issue(禁自動輪詢)" \
|
||||
" GitHub issues: CC can use /issue-handle to read issues from its own repo (no auto-polling)"
|
||||
echo ""
|
||||
|
||||
# 有任何來源抓取失敗 → 用非零 exit code 出聲,不能靜靜地當「裝完了」收工。
|
||||
if [ ${#FAILED[@]} -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
+45
-4
@@ -23,18 +23,43 @@ esac
|
||||
t() { if [ "$IS_ZH" = "yes" ]; then printf '%s\n' "$1"; else printf '%s\n' "$2"; fi; }
|
||||
tn() { if [ "$IS_ZH" = "yes" ]; then printf '%s' "$1"; else printf '%s' "$2"; fi; }
|
||||
|
||||
REPO_RAW="https://raw.githubusercontent.com/uncle6me-web/system-dev-template/main"
|
||||
# 來源預設=公開 GitHub(leo 2026-07-21:「要發佈的正稿,從頭就不要用奇怪的網址,
|
||||
# 以免改來改去」)。舊的 uncle6me-web 帳號已被 suspend(讀 404)=自動更新靜默失效,
|
||||
# 這顆雷已在 system-dev-template 本體修過(正解=改指 youlinhsieh 這個公開帳號),
|
||||
# 這裡只是把同一個修法補進 Arcrun 這份沒跟到的 copy。
|
||||
# 內部要指私有草稿源時用環境變數覆寫,不改檔:
|
||||
# TEMPLATE_SOURCE=https://<私有 raw base> bash scripts/update.sh
|
||||
REPO_RAW="${TEMPLATE_SOURCE:-https://raw.githubusercontent.com/youlinhsieh/system-dev-template/main}"
|
||||
TEMPLATE_URL="$REPO_RAW/template"
|
||||
|
||||
UPDATED=()
|
||||
KEPT=()
|
||||
NEW=()
|
||||
TEMPLATED=()
|
||||
FAILED=()
|
||||
|
||||
# 404 頁面常常「非空」(GitHub raw 對不存在的路徑回 "404: Not Found"),
|
||||
# 只判斷 [ -s file ] 會把錯誤頁內容當成檔案寫進去且完全不報錯(template issue #13 撞過的雷)。
|
||||
looks_like_error_page() {
|
||||
local f="$1"
|
||||
[ -s "$f" ] || return 0
|
||||
if [ "$(wc -l < "$f" | tr -d ' ')" -le 2 ] && head -c 200 "$f" | grep -qiE '40[0-9]|not found|<html'; then
|
||||
return 0
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
# ── 版本比對:先看本機 vs 遠端,給使用者「值不值得更新」的判斷 ──
|
||||
LOCAL_VER="$(tn '(未知)' '(unknown)')"
|
||||
[ -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 '')"
|
||||
# 容錯:curl 對 404 會把「404: Not Found」當內容輸出(非空),舊版直接把它寫進 REMOTE_VER
|
||||
# 拿去跟本機版本比對,比對邏輯不會報錯、只會靜靜判斷「版本不同」或誤判「已最新」。
|
||||
# 這裡驗證必須像版號(X.Y.Z),否則一律視為取不到。
|
||||
case "$REMOTE_VER" in
|
||||
[0-9]*.[0-9]*.[0-9]*) : ;; # 形如 1.9.0 → 合法
|
||||
*) REMOTE_VER="" ;; # 404 / HTML 錯誤頁 / 其他 → 當作沒抓到
|
||||
esac
|
||||
|
||||
echo ""
|
||||
echo "🔄 system-dev-template updater"
|
||||
@@ -64,7 +89,7 @@ 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 curl -sSL "$src" -o "$dest.tmp" 2>/dev/null && ! looks_like_error_page "$dest.tmp"; then
|
||||
if cmp -s "$dest" "$dest.tmp"; then
|
||||
rm -f "$dest.tmp" # 內容相同,不算更新
|
||||
else
|
||||
@@ -73,13 +98,15 @@ update_file() {
|
||||
fi
|
||||
else
|
||||
rm -f "$dest.tmp"
|
||||
FAILED+=("$dest")
|
||||
t " ⚠️ 抓取失敗,保留原檔:$dest" " ⚠️ Download failed, keeping the original: $dest"
|
||||
fi
|
||||
else
|
||||
if curl -sSL "$src" -o "$dest" 2>/dev/null && [ -s "$dest" ]; then
|
||||
if curl -sSL "$src" -o "$dest" 2>/dev/null && ! looks_like_error_page "$dest"; then
|
||||
NEW+=("$dest") # 新功能:舊版沒有的檔
|
||||
else
|
||||
rm -f "$dest"
|
||||
FAILED+=("$dest")
|
||||
t " ⚠️ 抓取失敗:$dest" " ⚠️ Download failed: $dest"
|
||||
fi
|
||||
fi
|
||||
@@ -98,7 +125,7 @@ keep_with_template() {
|
||||
if [ -f "$dest" ]; then
|
||||
KEPT+=("$dest")
|
||||
local tmpl="${dest%.sh}.template.sh"
|
||||
if curl -sSL "$src" -o "$tmpl.tmp" 2>/dev/null && [ -s "$tmpl.tmp" ]; then
|
||||
if curl -sSL "$src" -o "$tmpl.tmp" 2>/dev/null && ! looks_like_error_page "$tmpl.tmp"; then
|
||||
if [ -f "$tmpl" ] && cmp -s "$tmpl" "$tmpl.tmp"; then
|
||||
rm -f "$tmpl.tmp" # 模板版沒變,不重複提示
|
||||
else
|
||||
@@ -227,8 +254,22 @@ if [ -f ".claude/settings.json" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# 有任何檔案抓取失敗要出聲,不能安靜吞掉(404 內容已被 looks_like_error_page 擋掉、
|
||||
# 不會污染既有檔案,但使用者必須知道「這幾個檔沒更新到」)。
|
||||
if [ ${#FAILED[@]} -gt 0 ]; then
|
||||
echo ""
|
||||
t "❌ 抓取失敗(來源不可達,原檔已保留不動):" "❌ Fetch failed (source unreachable, original files kept untouched):"
|
||||
for f in "${FAILED[@]}"; do echo " x $f"; done
|
||||
t " 請檢查網路,或用 TEMPLATE_SOURCE=<其他來源> 重跑。" \
|
||||
" Check your network, or rerun with TEMPLATE_SOURCE=<alternate source>."
|
||||
fi
|
||||
|
||||
echo ""
|
||||
t "🚀 更新完成:${LOCAL_VER} → ${REMOTE_VER}" "🚀 Update complete: ${LOCAL_VER} → ${REMOTE_VER}"
|
||||
t " 下次更新直接跑:bash scripts/update.sh" " Next time, just run: bash scripts/update.sh"
|
||||
t " 改了什麼看:CHANGELOG.md" " See what changed: CHANGELOG.md"
|
||||
echo ""
|
||||
|
||||
if [ ${#FAILED[@]} -gt 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user