fix(deploy): staging 拷贝失败必须当场 exit 2(这次实测打出了假的 [ OK ])+ 登记同类未堵点
一次在沙箱里跑的 `bash deploy/redeploy-plugin.sh pi`(本意是修生产缺文件)被权限拒绝,
结果暴露出脚本自己的一个假绿:
mkdir: cannot create directory '…/.20260914-201204.staging': Permission denied
cp: cannot create directory '…' : Permission denied
[ OK ] 已拷入 node_modules(生产不借用仓库的依赖) ← 一个字节都没拷
[FAIL] staging 里没有入口 src/index.mjs
**一段输出里两个互相矛盾的信号,而且 OK 在前** —— 这正是本仓库反复记录的那个病
("从失败里产出一份看着正常的报告"),这次是部署脚本自己得上了。
改动:`mkdir`/`cp` 当场判失败并按约定 exit 2(环境/权限问题,不是检查问题);
`node_modules` 那一份**拷失败就不再打 OK**(依赖进不了 staging 会在重启时才炸,
而那时旧版已经被换掉了)。实测同一路径:现在**立刻** exit 2、零个假 `[ OK ]`。
成功路径未受影响(脚本其余部分与 `[ OK ]`/`[FAIL]` 约定不变)。
`docs/DEBTS.json` 登记同类未堵点 `redeploy-script-unguarded-steps`:
`deploy/redeploy-gateway.sh:84` 的 `run "cp -r …"` 无守卫,而该脚本只有
`set -uo pipefail`(**无 `-e`**)、`run()` 内部 `eval` 的失败既不中断也不被调用点接收
⇒ 前端产物没拷进去也继续往下走。**没有当场改那个文件**:另一条会话正在改它,
改它等于把冲突塞给一条我看不见的路径(`install.sh` 已有 `set -euo pipefail`,无需处理)。
登记的 `due` 就是"下次改任一 deploy 脚本时"。
验证:`npm test` 463/463、`check-shared-libs.sh` exit 0、`--self-check` 全过、`bash -n` OK。
This commit is contained in:
@ -116,7 +116,14 @@ fi
|
||||
# ── 3. staging 拷贝(仓库外的快照)──────────────────────────────
|
||||
mkdir -p "$DEST"
|
||||
rm -rf "$STAGING"
|
||||
mkdir -p "$STAGING"
|
||||
# ★ 这两步必须**当场判失败**,不能靠后面"staging 里没有入口"来兜。
|
||||
# 2026-09-14 实测(一次在沙箱里跑的部署):`mkdir`/`cp` 因权限被拒之后,
|
||||
# 脚本照样往下走,于是先打出 `[ OK ] 已拷入 node_modules`(**其实一个字节都没拷**),
|
||||
# 再打出 `[FAIL] staging 里没有入口 src/index.mjs` —— 一段输出里两个互相矛盾的信号,
|
||||
# 而且"OK"在前。这正是本仓库反复记录的那个病:**从失败里产出一份看着正常的报告**。
|
||||
# 权限/磁盘这类问题的确不属于"检查器的问题",所以按仓库约定用 2(环境问题)退出。
|
||||
mkdir -p "$STAGING" || { bad "建不了 staging 目录: $STAGING(权限/磁盘?)"; exit 2; }
|
||||
cp -a "$SRC/." "$STAGING/" || { bad "拷贝到 staging 失败: $SRC → $STAGING(权限/磁盘?)"; exit 2; }
|
||||
|
||||
# 整包复制,再剔除开发用目录。
|
||||
#
|
||||
@ -128,14 +135,18 @@ mkdir -p "$STAGING"
|
||||
#
|
||||
# 白名单的失败模式天生如此:漏一个就等着启动时炸,而启动时旧版本已经被换掉了。
|
||||
# 黑名单反过来 —— 默认带走,只排除明确不需要的。
|
||||
cp -a "$SRC/." "$STAGING/"
|
||||
rm -rf "$STAGING/test" "$STAGING/.git" "$STAGING/node_modules/.cache" \
|
||||
"$STAGING/.DS_Store" "$STAGING/dist.old" 2>/dev/null
|
||||
find "$STAGING" -maxdepth 1 -name '*.log' -delete 2>/dev/null
|
||||
# 依赖必须进快照:仓库外没有 node_modules 可借,缺了它入口根本起不来。
|
||||
if [ -d "$SRC/node_modules" ]; then
|
||||
cp -a "$SRC/node_modules" "$STAGING/"
|
||||
ok "已拷入 node_modules(生产不借用仓库的依赖)"
|
||||
if cp -a "$SRC/node_modules" "$STAGING/"; then
|
||||
ok "已拷入 node_modules(生产不借用仓库的依赖)"
|
||||
else
|
||||
# 拷不动就别打 OK:依赖进不了 staging,生产启动时才会炸,而那时旧版已被换掉。
|
||||
bad "node_modules 拷不进 staging(生产不借用仓库的依赖,缺了入口起不来)"
|
||||
exit 2
|
||||
fi
|
||||
else
|
||||
warn "源目录没有 node_modules —— 若入口依赖外部包,启动时会失败"
|
||||
fi
|
||||
|
||||
@ -77,6 +77,13 @@
|
||||
"kind": "scope",
|
||||
"due": "**策略已定、只剩\"有人拍一下\"**(提案见 docs/ALIGN-REFS.json 的 radius.policy):语义配对成立 ⇒ 数值按两端各自成立,默认**以 WebUI 为准**(除非鸿蒙平台规范要求系统档)。**设备只做验证(并排看是否感知不一致),不做决策** —— 本工作区起不了模拟器,把决策挂在设备上这笔账就永远不还。**实现者不能自己拍**(同 `unknown-preset-approval`):追认或驳回即闭合;若真机并排看出感知不一致,则改为反向并登记成决定",
|
||||
"where": "docs/ALIGN-REFS.json 的 radius 段(含两侧数值:WebUI 14px/8px;鸿蒙侧本工作区只能读到资源 ID 125829709 / 125829702,读不到 vp 值 —— 实体值在系统资源包里)"
|
||||
},
|
||||
{
|
||||
"id": "redeploy-script-unguarded-steps",
|
||||
"count": 1,
|
||||
"kind": "scope",
|
||||
"due": "**下一次改 `deploy/` 下任一脚本时**必须一并堵(`redeploy-gateway.sh` 正在被另一条会话改 ⇒ 本条目就是给它接手时的入口)。堵法:给每个副作用步骤加 `|| { bad …; exit 2; }`,或在脚本上开 `set -e`;两者都要与既有的 2=环境 / 1=检查 约定对齐。",
|
||||
"where": "`deploy/redeploy-gateway.sh:84` 的 `run \"cp -r '$REPO/client/electron/dist/.' ...\"` —— 脚本只有 `set -uo pipefail`(**无 `-e`**),`run()` 内部 `eval` 的失败既不中断也不被调用点接收 ⇒ 前端产物没拷进去也继续往下走。同类已在 `deploy/redeploy-plugin.sh` 修掉(2026-09-14):那次的实测形状是 `mkdir`/`cp` 被拒后仍打出 `[ OK ] 已拷入 node_modules`,再打出 `[FAIL] staging 里没有入口` —— **一段输出里两个矛盾信号,且 OK 在前**。该文件现已在 `mkdir`/`cp`/`node_modules` 三处判失败并 exit 2。"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user