现象
合进 main 的改动到不了线上。
线上跑的是哪个提交,没有任何记录可查。
唯一的 Release 是 v0.1.0(08-17 09:57 UTC),之后没有再发过;而线上代码在这之后至少变过一次。08-18 16:40 有人重建了生产容器,线上 GET /api/openapi.json 从 25 条路径变成 30 条。这次部署没有对应的 Release、没有 tag、没有记录,事后只能靠比对接口形状反推它大概来自哪一版。
判据与实测:main 与那条集成分支的 quota 路由数分别是 4 与 5,且 action_preset.py 只在集成分支上。线上实测 quota 4 条、无 action-preset 端点,所以这次部署来自 main。这个结论是逐个端点比出来的,不是查出来的 —— 而部署本该是可查的。
原因
部署为手工执行,且源码不来自 main。
服务器上只有一个源码目录 /root/windup-test,生产容器 windup-backend 与测试容器 windup-test-backend 都从它构建。该目录当前 HEAD 是 5998c27,属于一条集成分支而非 main。生产镜像的构建时间是 08-18 05:07。
/root 下有三十余个手写部署脚本(fe.sh fe2.sh fe3.sh final.sh final2.sh final3.sh final4.sh verify.sh verify2.sh vfy.sh 等),命名带序号,说明每次部署都是一次手工试错。
因此:合并到 main 不产生任何部署动作;除非有人手工进服务器 git pull 再重建,改动不会到达用户。
影响
已在生产库观测到的后果:
character_action 任务 completed 49 / failed 11 / running 3 ,其中 3 条自 08-13、08-14 起卡在 running,无终态无 error_message。用户界面表现为一直等待。
11 条失败里 3 条是 缺少母版:reference_image_urls 为空 —— 提交时不拦、执行阶段才炸。该拦截的实现已完成但未提交。
3 条 522/525 网关错误。fix(providers): 52x 重发按预算封顶 #297 已修重试判据,线上跑的是修复前的版本。
方案
按 #334 第四节「部署只认 Release」建立自动发布链:
阶段
触发
动作
发版
main 上 CI 全绿
按 Conventional Commits 计算下一版本号,打 Tag,生成 Release notes
部署
Release 发布
SSH 到服务器,从 Tag 检出到独立目录,构建并切换容器
校验
部署完成
拉线上 openapi.json 与该 Tag 的 openapi.json 比对,不一致则回滚
生产与测试的源码目录必须分开:生产只从 Tag 检出,测试可以继续跟集成分支。
不包含
验收
main 合入后无需人工介入即可产生新 Release
线上 openapi.json 与最新 Release 的 openapi.json 逐字节一致
生产源码目录的 HEAD 恒等于某个 Tag,不指向任何分支
补充(2026-08-18):自动化写过一次,因缺 Secrets 停摆
.github/workflows/deploy.yml 存在过,在分支 feat/workflow-run(提交 9ad72d5)上,触发模型是 PR 创建/更新 → 预览环境、PR 合并到 main → 正式环境。2026-08-10 跑过一次(run 31360873959)结论 failure,之后这个文件不在 main、也不在任何现存分支上。那次运行日志已过期,无法确认具体报错。
文件头部注明需要五个 Secrets:DEPLOY_HOST、DEPLOY_USER、DEPLOY_SSH_KEY、DEPLOY_PATH、DEPLOY_PORT。仓库 Actions Secrets 里目前只有 CODECOV_TOKEN。
所以缺口分两半:
一、五个 Secrets 需要有 admin 权限的人配置。 服务器凭证不在 Issue 里流转。
二、workflow 重新落到 main 时触发要换成消费 Release。 原版按 PR 合并触发,与本 Issue 第四节「部署只认 Release」冲突:PR 合并那一刻还没经过发版这道关。改成 release: [published] 后与 #387 接成一条链——main 过 CI → 发 Release → 部署该 Release 的 tag。第二步不需要 admin。
预览环境(原版的 deploy-preview)先不做:它要按 PR 号起多套环境,与正式部署是两件事。
现象
合进
main的改动到不了线上。线上跑的是哪个提交,没有任何记录可查。
唯一的 Release 是
v0.1.0(08-17 09:57 UTC),之后没有再发过;而线上代码在这之后至少变过一次。08-18 16:40 有人重建了生产容器,线上GET /api/openapi.json从 25 条路径变成 30 条。这次部署没有对应的 Release、没有 tag、没有记录,事后只能靠比对接口形状反推它大概来自哪一版。判据与实测:
main与那条集成分支的 quota 路由数分别是 4 与 5,且action_preset.py只在集成分支上。线上实测 quota 4 条、无 action-preset 端点,所以这次部署来自main。这个结论是逐个端点比出来的,不是查出来的 —— 而部署本该是可查的。原因
部署为手工执行,且源码不来自
main。服务器上只有一个源码目录
/root/windup-test,生产容器windup-backend与测试容器windup-test-backend都从它构建。该目录当前 HEAD 是5998c27,属于一条集成分支而非main。生产镜像的构建时间是 08-18 05:07。/root下有三十余个手写部署脚本(fe.shfe2.shfe3.shfinal.shfinal2.shfinal3.shfinal4.shverify.shverify2.shvfy.sh等),命名带序号,说明每次部署都是一次手工试错。因此:合并到
main不产生任何部署动作;除非有人手工进服务器git pull再重建,改动不会到达用户。影响
已在生产库观测到的后果:
character_action任务 completed 49 / failed 11 / running 3,其中 3 条自 08-13、08-14 起卡在running,无终态无error_message。用户界面表现为一直等待。缺少母版:reference_image_urls 为空—— 提交时不拦、执行阶段才炸。该拦截的实现已完成但未提交。方案
按 #334 第四节「部署只认 Release」建立自动发布链:
main上 CI 全绿openapi.json与该 Tag 的openapi.json比对,不一致则回滚生产与测试的源码目录必须分开:生产只从 Tag 检出,测试可以继续跟集成分支。
不包含
验收
main合入后无需人工介入即可产生新 Releaseopenapi.json与最新 Release 的openapi.json逐字节一致补充(2026-08-18):自动化写过一次,因缺 Secrets 停摆
.github/workflows/deploy.yml存在过,在分支feat/workflow-run(提交9ad72d5)上,触发模型是 PR 创建/更新 → 预览环境、PR 合并到 main → 正式环境。2026-08-10 跑过一次(run31360873959)结论 failure,之后这个文件不在 main、也不在任何现存分支上。那次运行日志已过期,无法确认具体报错。文件头部注明需要五个 Secrets:
DEPLOY_HOST、DEPLOY_USER、DEPLOY_SSH_KEY、DEPLOY_PATH、DEPLOY_PORT。仓库 Actions Secrets 里目前只有CODECOV_TOKEN。所以缺口分两半:
一、五个 Secrets 需要有 admin 权限的人配置。 服务器凭证不在 Issue 里流转。
二、workflow 重新落到 main 时触发要换成消费 Release。 原版按 PR 合并触发,与本 Issue 第四节「部署只认 Release」冲突:PR 合并那一刻还没经过发版这道关。改成
release: [published]后与 #387 接成一条链——main 过 CI → 发 Release → 部署该 Release 的 tag。第二步不需要 admin。预览环境(原版的
deploy-preview)先不做:它要按 PR 号起多套环境,与正式部署是两件事。