chore(release): deploy-from-committed 防呆流程(git 閘 + 清單)

壓測階段 6 抓到漂移新形態:cypher 改了但沒推 main → acr init 從 origin/main
codeload 抓到舊 worker → 薄殼打不存在的 /init/seed → 404。根因是「deploy 前沒先 push」。

防呆(沒 GH Actions,deploy 分開推,靠清單+閘不漏):
- scripts/check-release.sh 加「0. Git 同步」段:工作目錄髒 / 領先 origin/main 未 push → exit 1
- scripts/local-deploy.sh 實際 deploy 前強制跑 git 閘(未過拒絕 deploy;SKIP_GIT_CHECK=true 可強推)
- RELEASE-CHECKLIST.md:正確順序(先 commit+push main → 再 deploy → 線上打新端點驗證)

核心鐵則:self-hosted acr init 從 origin/main 抓 worker 源,故 git push 必須在 deploy 之前。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
uncle6me-web
2026-06-06 15:51:51 +08:00
parent 3e65e22775
commit 3d3de8b917
3 changed files with 116 additions and 1 deletions
+61
View File
@@ -0,0 +1,61 @@
# RELEASE-CHECKLIST — 出貨清單(沒有 GitHub Actions,每個 target 分開推,照順序不漏)
> 為什麼要這份:沒有 CI,deploy 是「一個個分開」的動作(git / CF workers / npm CLI)。
> 漏任一步就會「有些新有些舊」——壓測踩過兩次:
> - 第一次:CLI 改了但 npm 沒發 → 用戶 npm 裝到舊 CLI。
> - 第二次(階段 6):cypher 改了但**沒推 main** → `acr init` 從 origin/main codeload 抓到**舊 worker** → 薄殼打不存在的 APIseed 404)。
>
> 核心鐵則:**self-hosted `acr init` 從 `origin/main` 抓 worker 源。所以「git push main」必須在「部署」之前。**
> 順序錯了 = deploy 出去的 prod 是新的,但 self-hosted 用戶裝到的是舊的。
---
## 正確順序(照做不會忘)
### 0. 改完 code,先驗證
- [ ] 三端 typecheck 綠:`cd cli && npx tsc --noEmit``cd cypher-executor && npx tsc --noEmit``cd mcp && npx tsc --noEmit`
- [ ] 動到的 .sh`bash -n scripts/<檔>.sh`
### 1. ⬆️ 先 git commit + push**必須在 deploy 之前**
- [ ] `git add -A`(確認 `.env` / secret 沒被加:`git diff --cached --name-only | grep -iE '\.env|secret|token'` 應空)
- [ ] `git commit -m "..."`
- [ ] `git push origin main`
- 理由:self-hosted 從 `origin/main` codeload 抓 worker。沒先 push → 用戶抓到舊碼。
### 2. ✅ 跑出貨前檢查(會擋住「git 沒同步」)
- [ ] `bash scripts/check-release.sh` → 必須全綠(含「0. Git 同步」段)。
- 紅燈「領先 origin/main N commit 未 push」= 回步驟 1。
- 此腳本 git 未同步會 `exit 1`,是 deploy 的前置閘。
### 3. 🚀 deployworker + CLI npm
- [ ] Node ≥ 20(本機若預設舊版:`export PATH="$HOME/.nvm/versions/node/v22.21.0/bin:$PATH"`
- [ ] `bash scripts/local-deploy.sh --all`(或不帶 `--all` 只 deploy diff
- 此腳本**會先自動跑步驟 2 的 git 閘**;未過直接拒絕 deploy(要強推設 `SKIP_GIT_CHECK=true`,自負風險)。
- worker 走 `wrangler deploy`CLI 走 `npm publish`(版本未 bump 會自動 patch +1 + 寫 CHANGELOG)。
- npm publish 需 `npm login``.env``NPM_API_TOKEN`authToken)。
### 4. 🔁 deploy 後線上驗證(確認新碼真的上去了)
- [ ] `curl https://cypher.arcrun.dev/health` → 200
- [ ] 改了 cypher 路由時,**實際打那條新路由**確認存在(例:`curl -X POST https://cypher.arcrun.dev/init/seed``curl https://cypher.arcrun.dev/recipes` 應非空)。
← 這步就是階段 6 的教訓:別只看「部署成功」,要打新端點確認。
- [ ] 改了 CLI`npm view arcrun version` == `cli/package.json` version。
- [ ] landing 有改:確認 arcrun.dev 更新。
### 5. 📣 通知 / 收尾
- [ ] 若是回應壓測:到壓測報告加「開發者回覆」+ 請壓測者重跑。
---
## 一眼對照表:每個 target 怎麼推、誰依賴它
| Target | 推法 | 誰依賴「它在 origin/main」 |
|---|---|---|
| **git origin/main** | `git push origin main` | **self-hosted `acr init` codeload 抓這裡的 worker 源** → 必須最先 |
| CF workers26 個含 mcp | `local-deploy.sh`wrangler deploy | 平台 prodself-hosted 自己 deploy |
| CLInpm `arcrun` | `local-deploy.sh` 第 6 段 / `cd cli && npm publish` | 用戶 `npm i -g arcrun` |
| landingarcrun.dev | `cd landing && wrangler pages deploy` | 訪客 |
## 常見漏失(自我檢查)
- ❌ 「我 deploy 了 prod cypher 但忘了 push main」→ self-hosted 用戶 init 抓舊碼。**先 push 再 deploy。**
- ❌ 「改了 CLI 但版本沒 bump」→ npm publish 跳過(同版)。`local-deploy.sh` 會自動 bump,但手動 publish 時要記得。
- ❌ 「改了 cypher 路由只看到『部署成功』就收工」→ 要實際 curl 新路由確認(步驟 4)。
+39 -1
View File
@@ -24,6 +24,38 @@ echo ""
echo "═══ arcrun release 狀態檢查(release.feature 佐證)═══"
echo ""
# ── 0. Git 同步(最關鍵:self-hosted 從 origin/main codeload 抓 worker)──────
# 壓測階段 6 抓到的漂移:CLI 新(npm)但 worker 舊(main 沒推 init-seed)→ acr init
# 從 main 抓到舊 cypher → 薄殼打不存在的 API → 404。
# ∴ deploy 前 git 必須先 push main,否則 self-hosted 用戶裝到舊碼。
echo "【0. Git 同步(deploy 前必過——self-hosted 從 origin/main 抓 worker 源)】"
GIT_BLOCK=0
if git rev-parse --git-dir >/dev/null 2>&1; then
BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)
DIRTY=$(git status --porcelain 2>/dev/null | grep -v '^?? ' | head -1)
if [ -n "$DIRTY" ]; then
err "工作目錄有未 commit 的變動 → deploy 前先 commit(否則部署的不是 GitHub 上的碼)"
GIT_BLOCK=1
else
ok "工作目錄乾淨(無未 commit 追蹤檔變動)"
fi
# local main vs origin/main
git fetch origin "$BRANCH" --quiet 2>/dev/null || true
AHEAD=$(git rev-list --count "origin/$BRANCH..$BRANCH" 2>/dev/null || echo "?")
BEHIND=$(git rev-list --count "$BRANCH..origin/$BRANCH" 2>/dev/null || echo "?")
if [ "$AHEAD" = "0" ] && [ "$BEHIND" = "0" ]; then
ok "$BRANCH 與 origin/$BRANCH 同步(self-hosted codeload 會抓到最新 worker"
elif [ "$AHEAD" != "0" ] && [ "$AHEAD" != "?" ]; then
err "$BRANCH 領先 origin/$BRANCH $AHEAD 個 commit 未 push → **deploy 前先 git push**(否則 self-hosted 裝到舊 worker,重演壓測階段 6 的 seed 404)"
GIT_BLOCK=1
else
warn "$BRANCH vs origin/$BRANCHahead=$AHEAD behind=$BEHIND(確認狀態)"
fi
else
info "非 git repo,跳過 git 同步檢查"
fi
echo ""
# ── 1. CF Worker 部署單位(由 scripts/local-deploy.sh 掃描部署)──────────
# 註:GH Actions 2026-05-16 停用、公開 repo 已移除 .github/,現行 deploy 走 local-deploy.sh。
echo "【CF Workersscripts/local-deploy.sh 掃 wrangler.toml 後 wrangler deploy)】"
@@ -87,5 +119,11 @@ else
fi
echo ""
echo "═══ 完成。⚠ = 需注意;· = 資訊;✗ = 失敗 ═══"
if [ "$GIT_BLOCK" = "1" ]; then
echo "═══ ✗ Git 未同步 — deploy 前必須先 commit + git push(見上「0. Git 同步」)═══"
echo " 流程見 RELEASE-CHECKLIST.md。push 完再跑本檢查確認全綠。"
echo ""
exit 1
fi
echo "═══ ✓ 可 deploy。⚠ = 需注意;· = 資訊;✗ = 失敗。流程見 RELEASE-CHECKLIST.md ═══"
echo ""
+16
View File
@@ -149,6 +149,22 @@ if [[ "$DRY_RUN" == true ]]; then
exit 0
fi
# ── 3.5 Git 同步前置閘(壓測階段 6 教訓:deploy-from-committed)────────────────
# self-hosted `acr init` 從 origin/main codeload 抓 worker 源。若本機領先 main 未 push,
# 部署 prod 用的是新碼但 self-hosted 用戶抓到舊碼 → 薄殼打不存在的 API(seed 404)。
# ∴ 實際 deploy 前強制 git 同步檢查;未過用 --skip-git-check 可強制略過(自負風險)。
if [[ "${SKIP_GIT_CHECK:-false}" != "true" ]]; then
echo ""
echo "🔎 Git 同步前置檢查(deploy 前必過;要略過設 SKIP_GIT_CHECK=true..."
if ! bash scripts/check-release.sh >/tmp/arcrun-release-check.txt 2>&1; then
grep -E "✗|⚠|領先|未 commit|Git 未同步" /tmp/arcrun-release-check.txt | sed 's/^/ /'
echo "❌ Git 未同步 → 先 commit + git push 再 deploy(見 RELEASE-CHECKLIST.md)。"
echo " (確定要在未 push 狀態 deploy SKIP_GIT_CHECK=true bash scripts/local-deploy.sh ..."
exit 1
fi
echo " ✓ Git 已同步,繼續 deploy"
fi
# ── 4. wrangler whoami 健康檢查 ──────────────────────────────────────────────
# 隨便挑一個 worker dir 跑 whoamipnpm 需要在 npm package 內)