From c397994ce8ffe6411c49c79bffca19226c508984 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Thu, 27 Aug 2026 16:34:16 +0800 Subject: [PATCH] =?UTF-8?q?feat(deploy):=20=E9=83=A8=E7=BD=B2=E6=94=B6?= =?UTF-8?q?=E5=B0=BE=E8=BD=89=E5=91=BC=E5=8F=AB=20restart-gate.sh=20requir?= =?UTF-8?q?e=20=E6=8E=9B=E4=B8=8A=E9=87=8D=E5=95=9F=E9=96=98=E9=96=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit What:`tools/deploy.sh` 新增 `restart_gate_sh()` 與 `mark_restart()` 兩個函式,並在全部指令成功、印出 `result` 之前呼叫 `mark_restart`。`install` 與 `update` 會轉呼叫 `jsc-hooks` 的 `hooks/restart-gate.sh require {模式} {domain}...` 掛上重啟閘門,成功就多印一行 `restart{狀態檔路徑}`;`uninstall` 與 dry-run 不寫。輸出行別表與檔頭的環境變數說明同步補上。 Why:部署換掉的是磁碟上的技能檔,目前工作階段載入的還是舊版。這段落差期間跑技能,改動看起來沒生效,人會以為部署失敗又重跑一次。要有一個「這台機器有一輪部署還沒重啟」的證據留在檔案上,判定那一端才擋得下來。 How:狀態檔的路徑、格式與判讀全留在 `jsc-hooks` 的 `restart-gate.sh`,這裡只轉呼叫它的 `require` 子命令,比照 `jsc-sdlc` 轉呼叫 `sdlc-gate.sh wp-lock` 的慣例。兩邊各拼一份格式就會對不上:這裡一開始自己寫四欄 TSV,而 hooks 那端讀的是 `key=value`,狀態檔存在卻解不出欄位,改成轉呼叫才修好,格式只能有一個真實來源。找腳本的順序比照 `jsc-sdlc` 的 `wp-gate.sh`:環境變數 `JSC_HOOKS_DIR` 優先,再找並排的工作樹,最後找 plugin 快取;找不到就印 `note` 行據實說「這次沒有掛上重啟閘門」,不自己補寫一份——閘門本來就由 `jsc-hooks` 判讀,它不在就沒有判定點,寫下去只是留一個沒人讀的檔案,還會讓下一輪誤以為閘門掛上了。`require` 一律接 `{結束碼}{指令} 該指令的結束碼;dry-run 時結束碼印「-」 # skip{domain}{原因} 本地 clone 是開發中的樹,略過 git pull # note{cli}{原因} 非逐指令的說明(例:kiro 整批改走複製退路的理由) +# restart{路徑} 這次寫下的重啟狀態檔 # result{cli}{mode}{domain 清單}{ok|fail} # 結束碼:全部指令成功 0;任一指令失敗 1;參數錯誤 2。skip、note 不算失敗,但呼叫端要據實回報。 # marketplace 指令一輪只跑一次:install 與 update 先跑,uninstall 最後跑。 @@ -18,7 +19,13 @@ # kiro 的執行檔是 kiro-cli;先探測這個版本認不認得 plugin 子指令(部分版本已經完全 # 移除,例:2.18.1),認得才逐一嘗試、失敗才退回複製,不認得就整批直接走複製, # 不逐一撞一次「unrecognized subcommand」才退回。 +# install 或 update 全數成功時,收尾寫一行進 $JSC_HOME/restart-required,代表這台機器有一輪 +# 部署還沒重啟。擋人邏輯不在這裡:由 jsc-hooks 讀這個檔案提示使用者重啟,逃生門 +# JSC_RESTART_GATE=off 也由那邊判讀。 +# 更新指引與移除指引由同目錄的 write-guides.sh 產生,一輪部署跑一次,不在這支腳本裡: +# 這支腳本的職責是「對單一 CLI 部署」,指引寫的是整台機器的樣貌。 # 環境變數: +# JSC_HOME hook 資料目錄,重啟狀態檔寫在這裡(預設 ~/.jsc) # GITEA_HOST Gitea 站台,可省略 scheme(預設 https://gitea.jsc.idv.tw) # JSC_GITEA_OWNER 存取庫的 owner(預設 plugins) # JSC_LOCAL_PLUGINS antigravity/kiro 用的本地 clone 目錄 @@ -57,6 +64,41 @@ usage() { exit 2 } +# 找 jsc-hooks 的 restart-gate.sh。順序比照 jsc-sdlc 的 wp-gate.sh:環境變數指定優先, +# 再找並排的工作樹,最後找 plugin 快取。找不到就回非零,由呼叫端據實回報。 +restart_gate_sh() { + if [ -n "${JSC_HOOKS_DIR:-}" ] && [ -f "$JSC_HOOKS_DIR/restart-gate.sh" ]; then + printf '%s\n' "$JSC_HOOKS_DIR/restart-gate.sh"; return 0 + fi + _root=$(cd "$(dirname "$0")/.." 2>/dev/null && pwd) || return 1 + for _c in "$_root/../hooks/hooks/restart-gate.sh" "$_root/../jsc-hooks/hooks/restart-gate.sh"; do + [ -f "$_c" ] && { printf '%s\n' "$_c"; return 0; } + done + _c=$(ls -d "$HOME"/.claude/plugins/cache/*/jsc-hooks/*/hooks/restart-gate.sh 2>/dev/null | sort | tail -n1) + [ -n "$_c" ] && [ -f "$_c" ] && { printf '%s\n' "$_c"; return 0; } + return 1 +} + +# 掛上部署後的重啟閘門。狀態檔的路徑、格式與判讀全在 jsc-hooks 的 restart-gate.sh, +# 這裡只轉呼叫它的 require 子命令,比照 jsc-sdlc 轉呼叫 sdlc-gate.sh wp-lock 的慣例。 +# 兩邊各拼一份格式就會對不上:2026-08-27 這裡曾自己寫四欄 TSV,而 hooks 那端讀的是 +# key=value,狀態檔存在卻解不出欄位。格式只能有一個真實來源。 +# 找不到 restart-gate.sh 時不要自己補寫一份:閘門本來就由 jsc-hooks 判讀,它不在就沒有 +# 判定點,寫下去只是留一個沒人讀的檔案,還會讓下一輪誤以為閘門掛上了。 +mark_restart() { + [ "$DRYRUN" = 1 ] && return 0 + case "$MODE" in install|update) ;; *) return 0 ;; esac + if ! rg=$(restart_gate_sh); then + printf 'note\t%s\t%s\n' "$CLI" "找不到 jsc-hooks 的 restart-gate.sh,這次沒有掛上重啟閘門" + return 0 + fi + if JSC_CLI="$CLI" sh "$rg" require "$MODE" $DOMAINS