fix(deploy)!: --dry-run 会真的写入安装根(建 bin/ + 装 21KB 脚本)

文件头把 `--dry-run` 定义为"只打印将执行的动作",但第 1 节那两条 `install`
**无守卫**,于是 dry-run 真的落地:

    AGENTMAIL_PREFIX=/tmp/fp2 bash deploy/redeploy-gateway.sh --dry-run
    ⇒ /tmp/fp2/bin/service-failure-notify.mjs   21453 字节   ← 不该出现
    ⇒ /tmp/fp2/bin/                             新建

`run()` 的既有口径是"dry-run 只打印",其它写操作都走它并因此被拦下;
这两条恰好是 2026-09-14 为修"通知脚本不装"(af42a08)而从 if 分支里**挪出来**的,
挪出来时没补守卫 —— 修 A 引入了 B。

同节 1b(am-sandbox)也一样:dry-run 会**真跑一次 go build + 19 项内核判据**
并 install。一并包进 DRY_RUN 分支。

## 判据

    rm -rf /tmp/fpX && mkdir -p /tmp/fpX
    AGENTMAIL_PREFIX=/tmp/fpX bash deploy/redeploy-gateway.sh --dry-run
    修前:残留 bin/ + bin/service-failure-notify.mjs(21453B) + .deploy.lock
    修后:残留 .deploy.lock(0 字节)  ← flock 载体,非"落地"

`bash -n` 通过;dry-run rc=0。

⚠️ 这与本仓"部署要一次做对"直接相关:`--dry-run` 是上线前的预览动作,
它若自己会写目标目录,就等于**在预览阶段动了生产**,而输出看起来完全正常。
This commit is contained in:
2026-09-25 06:16:03 +08:00
parent 77d70b1241
commit 7a65b270bb

View File

@ -163,12 +163,22 @@ fi
# 后果是"改了仓库里的通知脚本、用 --skip-web 部署 ⇒ 生产还是旧的那份", # 后果是"改了仓库里的通知脚本、用 --skip-web 部署 ⇒ 生产还是旧的那份",
# 而判据 ③ 只判"在不在、有没有执行位",不判**是哪一份** ⇒ 全绿。 # 而判据 ③ 只判"在不在、有没有执行位",不判**是哪一份** ⇒ 全绿。
# (已把 ③ 一并改成比内容。) # (已把 ③ 一并改成比内容。)
install -d "$PREFIX/bin" || { bad "建不了 $PREFIX/bin"; exit 2; } # ★ `--dry-run` 的语义是"只打印将执行的动作"(见文件头用法),但下面两条 `install`
if ! install -m 0755 "$REPO/deploy/service-failure-notify.mjs" "$PREFIX/bin/service-failure-notify.mjs"; then # 原先**无守卫**:`--dry-run` 会真的建目录、真的把一个 21KB 脚本写进安装根。
# 实测(AGENTMAIL_PREFIX=/tmp/fp2 bash deploy/redeploy-gateway.sh --dry-run):
# /tmp/fp2/bin/service-failure-notify.mjs 21453 字节 ← 不该出现的文件
# 这与 `run()` 的既有口径也不一致(其它写操作都走 run 并被 DRY_RUN 拦下)。
# ⇒ 用 run() 包住;`--dry-run` 只剩打印。
run "install -d '$PREFIX/bin'" || { bad "建不了 $PREFIX/bin"; exit 2; }
if [ "$DRY_RUN" = 1 ]; then
printf ' [dry-run] install -m 0755 %s %s\n' \
"$REPO/deploy/service-failure-notify.mjs" "$PREFIX/bin/service-failure-notify.mjs"
elif ! install -m 0755 "$REPO/deploy/service-failure-notify.mjs" "$PREFIX/bin/service-failure-notify.mjs"; then
bad "装不了故障通知脚本" bad "装不了故障通知脚本"
exit 2 exit 2
else
ok "故障通知脚本已装到 /opt/agentmail/bin/"
fi fi
ok "故障通知脚本已装到 /opt/agentmail/bin/"
# 边界工具 am-sandbox(Landlock)—— 只有**本机真的能建立边界**时才装。 # 边界工具 am-sandbox(Landlock)—— 只有**本机真的能建立边界**时才装。
# #
@ -180,6 +190,12 @@ ok "故障通知脚本已装到 /opt/agentmail/bin/"
# 不把判据失败当致命错误:它可能只是内核老 —— 那种机器仍然可以部署网关, # 不把判据失败当致命错误:它可能只是内核老 —— 那种机器仍然可以部署网关,
# 只是沙箱接线会在运行时 fail closed(那一步自己会叫)。 # 只是沙箱接线会在运行时 fail closed(那一步自己会叫)。
say "1b. 边界工具(Landlock 沙箱)" say "1b. 边界工具(Landlock 沙箱)"
if [ "$DRY_RUN" = 1 ]; then
# 同 1. 的理由:`--dry-run` 不该真的构建、更不该真的 install。
# 这里原来会**真跑一次 go build + 19 项内核判据**(数秒)并写入 $PREFIX/bin。
printf ' [dry-run] go build -o %s ./cmd/am-sandbox && check-sandbox.sh && install -m 0755 → %s/bin/am-sandbox\n' \
"/tmp/am-sandbox-build-$TS" "$PREFIX"
else
SANDBOX_STAGE="/tmp/am-sandbox-build-$TS" SANDBOX_STAGE="/tmp/am-sandbox-build-$TS"
rm -f "$SANDBOX_STAGE" rm -f "$SANDBOX_STAGE"
if ( cd "$REPO/server" && go build -trimpath -o "$SANDBOX_STAGE" ./cmd/am-sandbox ); then if ( cd "$REPO/server" && go build -trimpath -o "$SANDBOX_STAGE" ./cmd/am-sandbox ); then
@ -193,6 +209,7 @@ else
warn "am-sandbox 构建失败(不影响网关本身)" warn "am-sandbox 构建失败(不影响网关本身)"
fi fi
rm -f "$SANDBOX_STAGE" rm -f "$SANDBOX_STAGE"
fi
# ---------------------------------------------------------------- 2 静态检查与测试 # ---------------------------------------------------------------- 2 静态检查与测试
say "2. 构建前检查" say "2. 构建前检查"