文件
hyb-oa/.trellis/tasks/09-05-existing-deploy-db-lifecycle-isolation/design.md
T
wangsli f223bfb72f
ci-e2e / e2e (push) Canceled after 0s
ci-minimal / check-minimal (push) Canceled after 0s
fix: 隔离既有发布的数据库容器生命周期(09-05-existing-deploy-db-lifecycle-isolation)
2026-09-05 21:02:58 +08:00

6.3 KiB

既有环境发布的数据库容器隔离设计(待审)

调用链与最小修改点

production-identity-bootstrap.mjs → deploy-existing.sh(固定 existing,身份与迁移预检)→ deploy.sh(本地校验/同步 → SSH 远端段 → Compose)。修改真正执行命令的远端段,而非仅在 wrapper 中增加一个无消费者的参数。直接调用 deploy.sh 也必须遵守相同模式约束。

容器执行合同

阶段 existing initialize
数据路径 维持 existing 检查,不补建 PGDATA 维持现有初始化检查与目录准备
db 仅只读查询/就绪检查,不执行 up 显式 up db 后有界等待健康
init build init;run --rm --no-deps,保留 -T、entrypoint 与原命令 同样隔离依赖,数据库已在上一阶段就绪
server build server → 健康检查 → up -d --no-build --no-deps server 同样显式指定服务与隔离依赖
worker(启用时) 检查现有镜像,必要时先 build worker → 健康检查 → up -d --no-build --no-deps worker 同左
可选 MinIO 保留既有功能,显式限定服务;检查其有效依赖集合不得触达 db 保留既有功能

模式分支包围显式 db 操作本身;不以日志、注释或上游约定代替。不要在本任务新增“绕过隔离”的开关。已有 MinIO 初始化的依赖需要保留,测试按真实图判定,不将所有依赖无差别禁止。

就绪与失败

通过已确定的 Compose project/service 查询 db 容器并只读检查运行和就绪状态,不能用历史固定容器名。就绪检查采用总时限,沿用既有健康语义;同一检查函数复用于初始阶段、build init 后、init 后、build server 后、worker 准备前后,避免耗时阶段后沿用过期健康快照。existing db 不可用时停止,不运行 up/restart 作为恢复手段;initialize 创建后等待就绪。init 失败沿现有 set -e/受控日志传播,不切换应用。

只读 review 发现初稿单次提前检查不足以替代各阶段 service_healthy,现将 server build 与启动拆开,启动使用 --no-build 避免检查后的隐式构建。worker 不一律重建:在 server 切换之前通过 Compose 解析现有 worker 容器,读取其 Config.Image 并确认对应镜像引用可用;仅有旧镜像 ID 不足以证明标签存在。无容器或引用缺失时显式构建后检查健康;无容器但有缓存镜像的情况可能多一次命中缓存的构建,接受此有界兼容差异以消除隐式构建窗口。当前 Compose worker 没有显式 image 覆盖,本任务不改镜像配置、Compose 拓扑或 init 命令内容;未来修改镜像来源需单独验证所需引用与配置一致,不能以已有容器引用代表新配置。MinIO 显式选择 minio/minio_init 并隔离其他依赖,保留初始化容器自己的已有就绪重试。

此保护只隔离容器生命周期。迁移和 seed 会访问数据库内容;保留原有授权、预检和备份约束,不能声称 --no-deps 能代替数据库备份或迁移审查。

命令捕获与行为判定

复用现有 Vitest 临时目录、假二进制模式,新建专用测试,避免继续堆叠静态 contains 断言。优先以 fake SSH 在隔离目录执行生产脚本发送的原始远端 shell,或从当前源码提取唯一 REMOTE heredoc 执行并另外覆盖 wrapper 模式传递;不得手抄一份发布流程作为测试对象。

  • fake 记录 JSON 参数数组,区分 compose 全局选项、子命令、服务参数与 init 容器内命令,不把 shell 命令中的词误判为服务。
  • 由仓库 Compose 服务依赖生成受测依赖图,不能硬编码一份与实际声明脱节的图。解析未知或含糊命令时失败;测试辅助依赖仅使用项目现有工具,必要新增依赖须再确认。
  • 对 up/run 等有依赖传播的操作计算有效服务集合;对 down 或无服务名的项目级生命周期操作按整个项目判定;stop/start/restart/rm/create/kill 等显式触达 db 的操作也拒绝。运行 init --rm 仅清理一次性 init 容器,不误判为删除 db。
  • existing 断言 db 生命周期事件列表为空,同时断言 init/server/预期 worker 出现,执行順序正确,入口成功完成目标阶段;initialize 断言 db 启动在 init 之前且健康检查生效。
  • 源码变异只作用于临时副本:恢复无条件 up db,移除 init/server/worker 各自隔离。每个变异须命中预期修改点并导致具体 db 违规测试失败,禁止 needle 未命中却算失败探针通过。
  • 拦截所有外部命令并清理继承敏感环境;未知外部调用直接失败,不允许落到真实 PATH 工具或网络。

兼容、复核与回滚

就绪循环的总时限固定 120 秒,轮询间隔 2 秒;用受限子进程强制截止,包含 Compose/inspect 调用卡住的情况,不仅限制循环次数。超时、查询错误、缺失/停止/不健康/无健康检查均失败退出,不继续 init。测试 fake 在专用 mkdtemp 目录,子进程传入白名单环境与独立 PATH,不更改 process.env、共享 shell 配置或生产文件。

首次真实执行前的工具恢复参考:保留 05d2a3f 的 deploy/trialrun/deploy.sh(可用 git show 05d2a3f:deploy/trialrun/deploy.sh 只读提取)。其原命令序列为 up -d db → 可选 MinIO → build init → run --rm -T --entrypoint sh init ...migrate...seed → up -d --build server → 可选 up -d worker。这是有风险的旧行为证据,不是获准执行的恢复脚本;禁止盲目复制整段运行。首次生产验证需人工在场,确认 Compose 身份、既有 db 健康、已知可用应用镜像及恢复指令;若新工具失败,先停并区分工具/应用/数据库故障,人工恢复应用也应显式隔离依赖,不重跑 init/seed 或自动启动 db。应用镜像回滚与部署工具恢复分别准备,执行均另行批准。

覆盖 V2 与 V1 fallback,不改 Compose 拓扑和生产配置。只读 reviewer 不写代码,重点查三条入口、健康时序与 fake 是否掩盖风险。缺独立复核能力时明确待复核,不以主会话自检替代。回滚不得无说明地恢复允许触碰 db 的旧发布路径;若防护使既有发布暂停,保持暂停并单独审查修复,不以紧急发布为由关闭保护。