HA 阶段 1:worktree_host + 跨主机 /pr 队列化 (#50)
* 部署自动化:唯一发布链路 deploy.py + host_deploy.sh,sha/commit 双重验真,失败回滚 旧链路三次栽过的坑:通用 tar 路径导致旧包误部署、传输不验 sha、 主机脚本多份漂移、health 通过不等于新代码上线。本单把四点变硬门禁: - 产物唯一命名 codex-app-server-<commit>.tar.gz + .sha256,远端唯一路径 - git archive 产物 + DEPLOYED_COMMIT 清单,默认拒绝脏工作区 - 传输链 scp -> scp_run -> chunk 分片,每路传完远端验 sha,不符删掉重来 - 主机侧唯一脚本:先验 sha/清单,staging 解包 + 编译检查,换目录上线, work/ 原样保留,health + 上线 commit 不符即回滚并退出非零 - deploy.py 成功后独立 ssh 再读一次 live 清单二次核对 - CI:host-verify 加 deploy/tests;release.yml 只在手动/tag + production environment 审批时部署,主干推送绝不自动部署生产 - deploy.sh 标记为旧链路弃用 - health 的 commit 字段已在父提交 HA 阶段 0 里随 server.py 落地, 本分支整体包含它;commit 为空时只靠文件核对,门禁同样成立 测试:host 32、cloud 487(4 跳过)、deploy 9,全部通过; host_deploy.sh 仿真覆盖成功/坏 sha/清单不符/health commit 不符回滚。 生产实机部署未做,等确认后再用新链路推。 * HA stage 1: worktree_host + queued cross-host PR jobs --------- Co-authored-by: host <host@test.local>
This commit is contained in:
1 parent
455513dd33
commit
fc8e337d0f
14 files changed
+1639
-67
No files matched your search
+62
-1
@@ -4,7 +4,68 @@
|
||||
传代码、备份、重启、验证,不改任务逻辑;运维脚本只负责检查与演练,
|
||||
不跑模型、不推代码。
|
||||
|
||||
## 部署:deploy.sh
|
||||
## 发布链路(新,默认用这个):deploy.py + host_deploy.sh
|
||||
|
||||
VM 侧运行,一条命令走完构建、传输、验真、部署、回滚核对:
|
||||
|
||||
```sh
|
||||
python3 deploy/deploy.py <host> [user]
|
||||
# 干跑(只构建、不传输、不动主机):
|
||||
python3 deploy/deploy.py <host> --dry-run
|
||||
# 只构建发布包(给 CI artifact / 手动检查用):
|
||||
python3 deploy/deploy.py --build-only --out-dir work/external-install/releases
|
||||
# 部署已有发布包(CI release 作业就是这么调的):
|
||||
python3 deploy/deploy.py <host> --tarball <包> --skip-tests
|
||||
```
|
||||
|
||||
它修掉的正是旧手工链路三次栽过的坑:
|
||||
|
||||
- **产物唯一命名,旧包无法冒充新包。** 发布包是
|
||||
`codex-app-server-<commit>.tar.gz` + `.sha256`,远端路径是
|
||||
`/tmp/codex-app-server-releases/<commit>.tar.gz`,不再用
|
||||
`/tmp/codex-app-server-code.tar.gz` 这种通用路径。scp 断了、
|
||||
旧包残留,都不可能被下一步误当成新包。
|
||||
- **传输、主机、二次核对三道 sha/commit 门。** 传输链自动
|
||||
fallback:scp(SSH_PROXY_CMD)→ ssh-helpers/scp_run.py(此前
|
||||
实测最稳)→ ssh-helpers/chunk_send.py(base64 分片);每路
|
||||
传完都在远端跑 `sha256sum` 比对,不符就删掉该次产物再试
|
||||
下一路,绝不把错包交给主机脚本。主机侧只用
|
||||
`deploy/host_deploy.sh` 这一份(VM 侧随包一起传过去,不依赖
|
||||
主机旧代码里的版本),它先验 tar sha、再验包内
|
||||
`DEPLOYED_COMMIT`、再 staging 解包 + 编译检查,任何一步
|
||||
不符都直接退出、旧代码原地不动。
|
||||
- **换目录代替原地 rm + 解包。** 主机侧先停服务,再把 live
|
||||
换成 old、staging 换成 live,`work/` 与
|
||||
`host-config-real.json`(如有)原样搬回;中途失败不会留
|
||||
半解包的 live。备份名含旧 commit + 时间戳,留最近 5 份。
|
||||
- **health 通过不再等于上线。** 主机脚本要求 health
|
||||
`ok=true` 且 `backend=postgres` 且 `db_ok=true`,且 live 的
|
||||
`DEPLOYED_COMMIT` 等于期望 commit;deploy.py 成功后还要
|
||||
独立 ssh 再读一次 live 清单核对,两处都对上才打印成功。
|
||||
旧链路“health 通过但跑的是旧代码”在新链路里会触发回滚
|
||||
并退出非零。health 的 `commit` 字段已在父提交 HA 阶段 0
|
||||
里随 server.py 一起落地(`_deployed_commit`,无文件时为
|
||||
null);本单不依赖它也能成立,commit 为空时只靠文件核对。
|
||||
- **产物来自 git archive,默认拒绝脏工作区。** 部署的永远是
|
||||
已提交的 HEAD,不是工作区里没提交的临时改动;`--allow-dirty`
|
||||
也只告警,部署的仍是 HEAD,不会把脏文件偷偷带上去。
|
||||
- **CI 发布与手工发布同一套脚本。** `.github/workflows/release.yml`
|
||||
只在手动 workflow_dispatch 或打 `v*` tag 时触发,走
|
||||
`environment: production` 审批;主干推送绝不自动部署生产。
|
||||
Actions 里没配 `DEPLOY_HOST` / `DEPLOY_SSH_KEY` 时,build
|
||||
作业仍产出发布包 artifact,deploy 作业明确失败并提示改走
|
||||
VM 侧 deploy.py,绝不静默跳过又报成功。
|
||||
|
||||
多机滚动(HA 阶段 2 的前置):当前 deploy.py 一次只推一台
|
||||
主机,多机时按主机逐台跑、每台 health + commit 都通过再推
|
||||
下一台,第一台失败就停,不要并行推两台。`--hosts` 批量滚动
|
||||
是后续一单,不在本轮做。
|
||||
|
||||
密钥规则与旧脚本一致:deploy.py 绝不接受密码参数、不读
|
||||
env 文件、不打印密钥;SSH 走 key,或调用方已有的
|
||||
ssh-helpers pty 通道(密码只走 `SSH_PASSWORD` 环境变量)。
|
||||
|
||||
## 部署:deploy.sh(旧链路,已弃用,新发布不要再用)
|
||||
|
||||
VM 侧运行:
|
||||
|
||||
|
||||
Reference in new issue
Block a user