feat: 薄殼原則落地 + seed 下沉 API + MCP 進主庫 + 部署一致性
壓測四橫向問題修正(docs 壓測報告):
① 薄殼原則成鐵律:能力長在 API,CLI/MCP/lib 只暴露
- seed 下沉成 API 行為:cypher-executor POST /init/seed(一次灌 API+auth recipe),
種子資料移到 server src/lib/api-recipe-seeds.ts,CLI 改薄殼一次呼叫
- 解除 deployFullyOk 連坐 + init 補 seed auth recipe + update 補 seed/全 KV
- registry SUBMISSIONS_KV 補進 REQUIRED_KV_NAMESPACES(修 20/21)
② MCP 統一帳號來源(單一 remote MCP + .env 切 MCP URL)
- MCP 從 sibling repo 搬進 arcrun/mcp/(remote Worker,route 改 mcp.arcrun.dev)
- config 加 mcp_url 三層解析 + getMcpUrl + DEFAULT_MCP_URL
- 新增 acr mcp-setup:依 config 寫專案 .mcp.json(接案切資料夾自動切 MCP)
- acr --version 改動態讀 package.json(根治漂移)
③ Deploy 一致性
- tests/release.feature + scripts/check-release.sh
- local-deploy.sh:CLI npm publish + auto patch bump + CHANGELOG
- local-deploy.sh bash 3.2 相容修正(mapfile / 空陣列 set -u)
- builtins/pnpm-lock.yaml
④ README self-hosted 同步現況(移除 R2 殘留、加 flag/env、多帳號)
CLI bump → 1.3.0
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Executable
+91
@@ -0,0 +1,91 @@
|
||||
#!/bin/bash
|
||||
# check-release.sh — release.feature 的可執行佐證:列出每個 publish target 的目前狀態
|
||||
#
|
||||
# 用途:「完成推送」後跑這個,一眼確認所有對外介面是否同步到位(壓測報告第 3 點)。
|
||||
# - CF workers / landing:是否由 CI 部署(看 deploy.yml 掃描範圍)
|
||||
# - npm CLI:本機 cli/package.json version vs npm 上的版本(最常漂移的一個)
|
||||
# - MCP:是否有未部署變動
|
||||
#
|
||||
# 不做破壞性動作,只讀狀態。需要 network(npm view / curl)才能查線上版本;
|
||||
# 無 network 時只比對本機可知的部分,並誠實標「無法查線上」。
|
||||
#
|
||||
# 對應:tests/release.feature、.claude/rules/05-deploy-convention.md
|
||||
|
||||
set -uo pipefail
|
||||
cd "$(dirname "$0")/.." || exit 1
|
||||
|
||||
GREEN='\033[0;32m'; YELLOW='\033[0;33m'; RED='\033[0;31m'; GRAY='\033[0;90m'; NC='\033[0m'
|
||||
ok() { echo -e " ${GREEN}✓${NC} $1"; }
|
||||
warn() { echo -e " ${YELLOW}⚠${NC} $1"; }
|
||||
err() { echo -e " ${RED}✗${NC} $1"; }
|
||||
info() { echo -e " ${GRAY}·${NC} $1"; }
|
||||
|
||||
echo ""
|
||||
echo "═══ arcrun release 狀態檢查(release.feature 佐證)═══"
|
||||
echo ""
|
||||
|
||||
# ── 1. CF Worker 部署單位(由 scripts/local-deploy.sh 掃描部署)──────────
|
||||
# 註:GH Actions 2026-05-16 停用、公開 repo 已移除 .github/,現行 deploy 走 local-deploy.sh。
|
||||
echo "【CF Workers(scripts/local-deploy.sh 掃 wrangler.toml 後 wrangler deploy)】"
|
||||
WORKER_DIRS=$(find . -name 'wrangler.toml' -not -path '*/node_modules/*' -not -name 'wrangler.test.toml' \
|
||||
| xargs -n1 dirname 2>/dev/null | sort -u)
|
||||
WORKER_COUNT=$(echo "$WORKER_DIRS" | grep -c . )
|
||||
info "掃到 $WORKER_COUNT 個部署單位(push 對應目錄即自動 deploy)"
|
||||
echo "$WORKER_DIRS" | sed 's/^/ /'
|
||||
|
||||
# ── 2. CLI npm(最常漂移)──────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "【npm CLI(arcrun / acr)】"
|
||||
LOCAL_CLI=$(node -p "require('./cli/package.json').version" 2>/dev/null || echo "?")
|
||||
if command -v npm >/dev/null 2>&1; then
|
||||
REMOTE_CLI=$(npm view arcrun version 2>/dev/null || echo "無法查線上")
|
||||
else
|
||||
REMOTE_CLI="無 npm CLI 可查"
|
||||
fi
|
||||
if [ "$LOCAL_CLI" = "$REMOTE_CLI" ]; then
|
||||
ok "CLI 版本同步:本機 $LOCAL_CLI = npm $REMOTE_CLI"
|
||||
elif [ "$REMOTE_CLI" = "無法查線上" ] || [ "$REMOTE_CLI" = "無 npm CLI 可查" ]; then
|
||||
info "本機 CLI $LOCAL_CLI($REMOTE_CLI)"
|
||||
else
|
||||
warn "CLI 版本漂移:本機 $LOCAL_CLI ≠ npm $REMOTE_CLI"
|
||||
warn "→ 跑 scripts/local-deploy.sh(含 cli/ 變動時)會 npm publish;或手動 cd cli && npm publish"
|
||||
fi
|
||||
|
||||
# 偵測「cli 有未發佈變動但版本可能未 bump」
|
||||
if git rev-parse --git-dir >/dev/null 2>&1; then
|
||||
LAST_CLI_PKG_CHANGE=$(git log -1 --format=%h -- cli/package.json 2>/dev/null || echo "")
|
||||
LAST_CLI_SRC_CHANGE=$(git log -1 --format=%h -- cli/src 2>/dev/null || echo "")
|
||||
if [ -n "$LAST_CLI_SRC_CHANGE" ] && [ "$LAST_CLI_SRC_CHANGE" != "$LAST_CLI_PKG_CHANGE" ]; then
|
||||
info "cli/src 最後變動($LAST_CLI_SRC_CHANGE)晚於 package.json($LAST_CLI_PKG_CHANGE)→ 確認是否需 bump version"
|
||||
fi
|
||||
fi
|
||||
|
||||
# ── 3. cypher-executor 線上健康 ────────────────────────────────────────
|
||||
echo ""
|
||||
echo "【cypher-executor(API 本體)】"
|
||||
if command -v curl >/dev/null 2>&1; then
|
||||
CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 8 https://cypher.arcrun.dev/health 2>/dev/null || echo "000")
|
||||
if [ "$CODE" = "200" ]; then
|
||||
ok "https://cypher.arcrun.dev/health → 200"
|
||||
else
|
||||
warn "https://cypher.arcrun.dev/health → $CODE(部署中或不可達?)"
|
||||
fi
|
||||
else
|
||||
info "無 curl,跳過線上健康檢查"
|
||||
fi
|
||||
|
||||
# ── 4. MCP server(已搬進主庫 arcrun/mcp/)──────────────────────────────
|
||||
echo ""
|
||||
echo "【MCP server(arcrun/mcp/,已進主庫)】"
|
||||
if [ -d mcp ] && [ -f mcp/wrangler.toml ]; then
|
||||
MCP_NAME=$(grep '^name' mcp/wrangler.toml | head -1 | sed -E 's/^name[[:space:]]*=[[:space:]]*"([^"]*)".*/\1/')
|
||||
ok "arcrun/mcp/ 存在(worker: $MCP_NAME);由 local-deploy.sh 一併 wrangler deploy"
|
||||
info "薄殼一致性:MCP 工具集應對齊 cypher-executor 最新 API(rule 07)"
|
||||
info "用戶連哪台 MCP 由 .mcp.json 決定(acr mcp-setup 依 config mcp_url 產)"
|
||||
else
|
||||
warn "找不到 arcrun/mcp/(應已搬進主庫)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "═══ 完成。⚠ = 需注意;· = 資訊;✗ = 失敗 ═══"
|
||||
echo ""
|
||||
+82
-10
@@ -49,7 +49,11 @@ done
|
||||
# 排除 node_modules、wrangler.test.toml、Pages 專案
|
||||
echo "🔍 Scanning worker directories..."
|
||||
|
||||
mapfile -t ALL_DIRS < <(
|
||||
# bash 3.2(macOS 內建)沒有 mapfile → 用 while read 相容寫法
|
||||
ALL_DIRS=()
|
||||
while IFS= read -r d; do
|
||||
[ -n "$d" ] && ALL_DIRS+=("$d")
|
||||
done < <(
|
||||
find . -type f -name 'wrangler.toml' \
|
||||
-not -path '*/node_modules/*' \
|
||||
-not -name 'wrangler.test.toml' \
|
||||
@@ -93,19 +97,22 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mapfile -t CHANGED < <(git diff --name-only "$BASE_REF" HEAD)
|
||||
CHANGED=()
|
||||
while IFS= read -r f; do
|
||||
[ -n "$f" ] && CHANGED+=("$f")
|
||||
done < <(git diff --name-only "$BASE_REF" HEAD)
|
||||
echo "Changed files (${#CHANGED[@]}):"
|
||||
for f in "${CHANGED[@]}"; do echo " $f"; done
|
||||
for f in ${CHANGED[@]+"${CHANGED[@]}"}; do echo " $f"; done
|
||||
|
||||
for d in "${ALL_DIRS[@]}"; do
|
||||
hit=0
|
||||
for f in "${CHANGED[@]}"; do
|
||||
for f in ${CHANGED[@]+"${CHANGED[@]}"}; do
|
||||
if [[ "$f" == "$d"/* ]]; then hit=1; break; fi
|
||||
done
|
||||
# 連動:改 registry/components/{name}/ 也要 deploy .component-builds/{name}/
|
||||
if [[ $hit -eq 0 && "$d" == .component-builds/* ]]; then
|
||||
name="${d#.component-builds/}"
|
||||
for f in "${CHANGED[@]}"; do
|
||||
for f in ${CHANGED[@]+"${CHANGED[@]}"}; do
|
||||
if [[ "$f" == "registry/components/$name"/* ]]; then hit=1; break; fi
|
||||
done
|
||||
fi
|
||||
@@ -132,9 +139,9 @@ done
|
||||
echo ""
|
||||
echo "📦 Deploy plan:"
|
||||
echo " Tier 1 (components, ${#TIER1[@]}):"
|
||||
for t in "${TIER1[@]}"; do echo " - $t"; done
|
||||
for t in ${TIER1[@]+"${TIER1[@]}"}; do echo " - $t"; done
|
||||
echo " Tier 2 (orchestration, ${#TIER2[@]}):"
|
||||
for t in "${TIER2[@]}"; do echo " - $t"; done
|
||||
for t in ${TIER2[@]+"${TIER2[@]}"}; do echo " - $t"; done
|
||||
echo ""
|
||||
|
||||
if [[ "$DRY_RUN" == true ]]; then
|
||||
@@ -198,10 +205,10 @@ deploy_one() {
|
||||
}
|
||||
|
||||
FAILED=()
|
||||
for d in "${TIER1[@]}"; do
|
||||
for d in ${TIER1[@]+"${TIER1[@]}"}; do
|
||||
deploy_one "$d" || FAILED+=("$d")
|
||||
done
|
||||
for d in "${TIER2[@]}"; do
|
||||
for d in ${TIER2[@]+"${TIER2[@]}"}; do
|
||||
deploy_one "$d" || FAILED+=("$d")
|
||||
done
|
||||
|
||||
@@ -211,6 +218,71 @@ if [[ ${#FAILED[@]} -eq 0 ]]; then
|
||||
echo "✅ All ${#TARGETS[@]} workers deployed successfully"
|
||||
else
|
||||
echo "⚠️ ${#FAILED[@]}/${#TARGETS[@]} workers failed:"
|
||||
for f in "${FAILED[@]}"; do echo " ❌ $f"; done
|
||||
for f in ${FAILED[@]+"${FAILED[@]}"}; do echo " ❌ $f"; done
|
||||
fi
|
||||
|
||||
# ── 6. CLI npm publish(壓測報告第 3 點:deploy 不只推 worker,npm CLI 也要同步)──
|
||||
# 「推送 = 全部 publish target 到位」(tests/release.feature)。worker 走 wrangler,
|
||||
# CLI 走 npm。只有 cli/ 在本次 diff 內 + 版本比 npm 新時才 publish(同版跳過,不假失敗)。
|
||||
# 不在 --dry-run 時跑。需 npm login(npm whoami 確認)。
|
||||
if [[ "${DRY_RUN:-false}" != "true" ]]; then
|
||||
CLI_CHANGED=false
|
||||
for t in "${TARGETS[@]:-}"; do [[ "$t" == "cli" || "$t" == "cli/" ]] && CLI_CHANGED=true; done
|
||||
# --all 或 diff 含 cli/ 都算
|
||||
if git diff --name-only "${BASE_REF}"..HEAD 2>/dev/null | grep -q '^cli/'; then CLI_CHANGED=true; fi
|
||||
if [[ "${DEPLOY_ALL:-false}" == "true" ]]; then CLI_CHANGED=true; fi
|
||||
|
||||
if [[ "$CLI_CHANGED" == "true" ]]; then
|
||||
echo ""
|
||||
echo "▶ CLI npm publish ..."
|
||||
LOCAL_V=$(node -p "require('./cli/package.json').version" 2>/dev/null || echo "?")
|
||||
REMOTE_V=$(npm view arcrun version 2>/dev/null || echo "none")
|
||||
|
||||
# 自動昇版(richblack:deploy 時自動 bump,避免忘了改):
|
||||
# 若本機版本 == npm 上版本(= 改了 cli 但沒 bump)→ 自動 patch +1。
|
||||
# 留版本記錄:把本次 commit subject 寫進 cli/CHANGELOG.md。
|
||||
if [[ "$LOCAL_V" == "$REMOTE_V" ]]; then
|
||||
echo " · 版本未 bump($LOCAL_V 已在 npm),自動 patch +1 ..."
|
||||
NEW_V=$(cd cli && npm version patch --no-git-tag-version 2>/dev/null | tr -d 'v')
|
||||
LOCAL_V="$NEW_V"
|
||||
# CHANGELOG:prepend 新版本 + 本次 commit subject(無 commit 則標 manual deploy)
|
||||
COMMIT_SUBJ=$(git log -1 --format='%s' 2>/dev/null || echo 'manual deploy')
|
||||
COMMIT_DATE=$(git log -1 --format='%ad' --date=short 2>/dev/null || echo '')
|
||||
CHANGELOG="cli/CHANGELOG.md"
|
||||
TMP_CL=$(mktemp)
|
||||
{
|
||||
echo "# arcrun CLI Changelog"
|
||||
echo ""
|
||||
echo "## $NEW_V — $COMMIT_DATE"
|
||||
echo "- $COMMIT_SUBJ"
|
||||
echo ""
|
||||
if [[ -f "$CHANGELOG" ]]; then tail -n +2 "$CHANGELOG"; fi
|
||||
} > "$TMP_CL"
|
||||
mv "$TMP_CL" "$CHANGELOG"
|
||||
echo " · 已 bump → $NEW_V,並記錄進 $CHANGELOG(記得 commit 這兩個檔)"
|
||||
fi
|
||||
|
||||
if ! npm whoami >/dev/null 2>&1; then
|
||||
echo " ⚠ 未 npm login(npm whoami 失敗),跳過 publish。手動:cd cli && npm publish"
|
||||
FAILED+=("cli:npm-publish(未登入)")
|
||||
else
|
||||
echo " 📦 publish arcrun $REMOTE_V → $LOCAL_V ..."
|
||||
if (cd cli && npm run build >/dev/null 2>&1 && npm publish --access public 2>&1 | tail -3); then
|
||||
echo " ✅ npm publish 完成(arcrun@$LOCAL_V)"
|
||||
else
|
||||
echo " ❌ npm publish 失敗"
|
||||
FAILED+=("cli:npm-publish")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "════════════════════════════════════════════════════════════"
|
||||
if [[ ${#FAILED[@]} -eq 0 ]]; then
|
||||
echo "✅ 全部 publish target 到位(worker + 必要時 CLI npm)"
|
||||
else
|
||||
echo "⚠️ ${#FAILED[@]} 項失敗(誠實回報,未假綠):"
|
||||
for f in ${FAILED[@]+"${FAILED[@]}"}; do echo " ❌ $f"; done
|
||||
exit 1
|
||||
fi
|
||||
|
||||
Reference in New Issue
Block a user