# PROGRESS · staging 部署自动先迁移(2026-09-15) 工作树:`.worktrees/staging-auto-migrate-on-deploy-20260915` 分支:`codex/staging-auto-migrate-on-deploy-20260915` 任务书基线:`de47c06d`;开工时 `origin/staging` = **`1a73f64e`**(已含 SHA 留空自动解析)。 本机 Windows。 未开 BUG 号。未改 `CHANGELOG.md`。未改 `deploy-production.yml` / `migrate-production-database.yml` / `deploy-staging.yml`。质量门禁未加入 `staging-mutation`。回滚部署仍不触发迁移。 ## 任务状态 | 任务 | 状态 | 说明 | | --- | --- | --- | | 1 gate 先触发迁移再部署 | 完成 | dispatch 段:先 migrate,等成功(20 分钟),再 deploy。失败/超时不部署,gate 这一步红 | | 2 日志说清有没有迁移 | 完成 | `run-staging-migration.sh` 应用前跑 `migration-check`;0=「无待应用迁移」,3=列出文件名。退出码 3 **不**阻断随后的 migrator | | 3 AGENTS §7.6 + README | 完成 | 向后兼容纪律已写入;staging 正常推送不用手点 | ## 相对任务书 §4.1 的必要偏离 任务书写「只改 quality-gate 的 dispatch 段、不得改 migrate 的校验」。按字面做会死锁: - 迁移 workflow 原来要求「已经成功的精确 SHA 门禁 run」 - 自动触发时,那次门禁 **还在跑**(正在等迁移),查 `status=success` 必然失败 - 若迁移再去等门禁成功,而门禁又在等迁移,两边一起超时 因此 migrate 增加了 **可选** `gate_run_id`(与 deploy-staging 同名、同语义): - 自动路径:gate 把自己的 run id 传进去。迁移只核验这是 `backend-quality-gate.yml`、SHA/branch/event 对得上、结论不是失败;**不等**整次 run 结束。artifact 在 dispatch 之前已经上传,可以接着下载。 - 手动路径:不传 `gate_run_id`,仍走原来的「必须找到成功门禁 run」。 没有走让步 2(改成迁移成功后再 dispatch 部署),因为门禁里等待做得到,且硬红线 3 要求迁移失败时 **gate 自己变红**。 ## 既有断言改动 | 文件 | 原值 | 新值 | 原因 | | --- | --- | --- | --- | | `staging-backend-workflows.test.ts` 门禁 dispatch | 只锁 `deploy-staging.yml/dispatches` | 先 migrate 再 deploy,并锁超时/失败文案 | 本单任务 1 | | 同上,手动迁移输入 | 只有 `deploy_sha` | 加上可选 `gate_run_id` | 自动路径需要给还在跑的门禁做背书 | | 同上,`run-staging-migration.sh` 顺序 | postgres → roles SQL → migrator | 中间加 `migration-check` | 任务 2 应用前打印待应用文件 | 未弱化生产两个 workflow 的 `required: true`。未弱化手动迁移的精确 SHA 门禁查找。 ## 验证 | 命令 | 结果 | | --- | --- | | `python -c "import yaml; yaml.safe_load(...)"` 两份 workflow | **yaml-ok** | | `npx tsx --test tests/staging-backend-workflows.test.ts` | **43 / 37 pass / 6 fail**。本单改动的断言(门禁先 migrate 再 deploy、可选 `gate_run_id`、migration-check 日志、AGENTS 纪律)全部通过。失败 6 条为既有 Windows 缺口(`python3` 9009、bash/rsync),与上一单同一清单。 | 真人:这次推送会触发门禁,应走出「迁移 → 部署」。Gitea 上三个 workflow 都应还在,手动迁移表单仍能打开。