fix(deploy): #2129 watchtower 自动部署兜底幂等 alembic 迁移 #2129

Merged
xiaoxia merged 1 commits from fix/2129-watchtower-auto-migrate into develop 2026-10-01 20:12:49 +08:00
Owner

根因

staging 爆款视频 analyze-images/history 返回 500 INTERNAL_ERROR 的根因:watchtower 自动部署只 restart 容器,不跑 CI deploy 脚本里的 alembic upgrade head;而 staging/prod 关闭了 AUTO_CREATE_SCHEMA,启动时 _ensure_viral_video_columns 不会执行,导致 PR #2124 (v1.6) 新增的 5 列(copy_result / voice_id / voice_source / video_ratio / video_model)在 DB 里缺失,任何 SQLAlchemy 读写 viral_video_jobs 都会 500。

同时 GET /api/v1/tts/presets 401 是前端 ViralVideoPage.tsx 用裸 fetch('/api/v1/tts/presets', { credentials: 'include' }) 没带 Authorization Bearer,后端该接口需要登录态;已在 PR #2128 (5226680) 改为通过 apiClient 调用 voices/presets。

修复

  1. 新增 API 容器 entrypoint-api.sh:容器启动先幂等执行 alembic upgrade head,失败仅告警不阻塞 uvicorn(已有列不受影响)。支持显式 CMD 透传:CI 用 docker run/ compose run ... sh -c '...' 时仍先跑迁移再执行传入命令,行为与现有脚本兼容。
  2. Worker 容器 entrypoint-worker.sh 同步加 alembic 步骤:避免 worker 先于 API 启动时 Celery task 读新列报错。
  3. 修复 worker.Dockerfile 遗漏 COPY alembic/:之前只 COPY 了 alembic.ini 和 migrations/,缺 alembic/env.py 与 alembic/versions/,容器内 alembic 命令根本无法执行。
  4. api.Dockerfile:用 ENTRYPOINT 替换原 CMD,entrypoint 内部 exec uvicorn ...。

验证

  • 本地 bash -n 检查两个 entrypoint 语法通过
  • 幂等:Alembic upgrade head 多次执行无副作用
  • 不影响 CI deploy:现有 docker run ... sh -c 'cd /app && alembic upgrade head' 会在 entrypoint 里再跑一次(幂等),然后 exec sh -c 继续走老流程
  • CI 现有 RUN_MIGRATIONS=1 路径也会多跑一次 alembic(幂等,不报错)

测试计划

  • PR CI 绿后合并,watchtower 自动拉镜像,容器启动 entrypoint 自动补列
  • 部署后回归 POST /viral-video/analyze-images、GET /viral-video/history 应返回 200
  • tts/presets 随 #2128 前端修复一并生效,弹窗不再 401
## 根因 staging 爆款视频 analyze-images/history 返回 500 INTERNAL_ERROR 的根因:**watchtower 自动部署只 restart 容器,不跑 CI deploy 脚本里的 `alembic upgrade head`**;而 staging/prod 关闭了 `AUTO_CREATE_SCHEMA`,启动时 `_ensure_viral_video_columns` 不会执行,导致 PR #2124 (v1.6) 新增的 5 列(`copy_result` / `voice_id` / `voice_source` / `video_ratio` / `video_model`)在 DB 里缺失,任何 SQLAlchemy 读写 `viral_video_jobs` 都会 500。 同时 `GET /api/v1/tts/presets` 401 是前端 ViralVideoPage.tsx 用裸 `fetch('/api/v1/tts/presets', { credentials: 'include' })` 没带 Authorization Bearer,后端该接口需要登录态;已在 PR #2128 (5226680) 改为通过 apiClient 调用 `voices/presets`。 ## 修复 1. **新增 API 容器 `entrypoint-api.sh`**:容器启动先幂等执行 `alembic upgrade head`,失败仅告警不阻塞 uvicorn(已有列不受影响)。支持显式 CMD 透传:CI 用 `docker run/ compose run ... sh -c '...'` 时仍先跑迁移再执行传入命令,行为与现有脚本兼容。 2. **Worker 容器 `entrypoint-worker.sh` 同步加 alembic 步骤**:避免 worker 先于 API 启动时 Celery task 读新列报错。 3. **修复 worker.Dockerfile 遗漏 COPY alembic/**:之前只 COPY 了 `alembic.ini` 和 `migrations/`,缺 `alembic/env.py` 与 `alembic/versions/`,容器内 `alembic` 命令根本无法执行。 4. **api.Dockerfile**:用 `ENTRYPOINT` 替换原 `CMD`,entrypoint 内部 `exec uvicorn ...`。 ## 验证 - 本地 bash -n 检查两个 entrypoint 语法通过 - 幂等:Alembic upgrade head 多次执行无副作用 - 不影响 CI deploy:现有 `docker run ... sh -c 'cd /app && alembic upgrade head'` 会在 entrypoint 里再跑一次(幂等),然后 exec sh -c 继续走老流程 - CI 现有 `RUN_MIGRATIONS=1` 路径也会多跑一次 alembic(幂等,不报错) ## 测试计划 - PR CI 绿后合并,watchtower 自动拉镜像,容器启动 entrypoint 自动补列 - 部署后回归 `POST /viral-video/analyze-images`、`GET /viral-video/history` 应返回 200 - tts/presets 随 #2128 前端修复一并生效,弹窗不再 401
xiaoxia added 1 commit 2026-10-01 19:42:48 +08:00
fix(deploy): #2129 watchtower 自动部署兜底幂等执行 alembic 迁移
CI/CD Pipeline / Dedup Check - skip PR tests when covered by push pipeline (pull_request) Successful in 1s
CI/CD Pipeline / Check push changed paths (pull_request) Has been skipped
CI/CD Pipeline / Check if frontend-only change (pull_request) Successful in 2s
Preview Deploy / Deploy Preview Environment (pull_request) Successful in 1m4s
PR Automation / Auto Approve on CI Green (pull_request) Successful in 2m47s
CI/CD Pipeline / Frontend Lint (pull_request) Has been skipped
CI/CD Pipeline / Frontend Unit Tests (pull_request) Has been skipped
CI/CD Pipeline / PR Build API Image (pull_request) Successful in 22s
CI/CD Pipeline / PR Build Web Image (pull_request) Has been skipped
AI Code Review / AI Code Review (pull_request) Successful in 6m46s
CI/CD Pipeline / Build Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging API Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Web Image (pull_request) Has been skipped
CI/CD Pipeline / Retag skipped Staging Worker Image (pull_request) Has been skipped
CI/CD Pipeline / PR Build Worker Image (pull_request) Successful in 2m27s
CI/CD Pipeline / Deploy Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / ACR Image Cleanup (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Validate - Style (pull_request) Successful in 9m18s
CI/CD Pipeline / Integration Tests (pull_request) Successful in 12m27s
CI/CD Pipeline / Validate - Python (mypy + alembic) (pull_request) Successful in 16m22s
PR Automation / Auto Merge on CI Green + Approved (pull_request) Successful in 11m14s
CI/CD Pipeline / Unit Tests (pull_request) Successful in 20m50s
ACR Cleanup / ACR Image Cleanup (pull_request_target) Successful in 36s
Preview Cleanup / Cleanup Preview Environment (pull_request) Successful in 2m28s
CI/CD Pipeline / Validate - Security (pull_request) Successful in 38m0s
CI/CD Pipeline / Build Production API Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Web Image (pull_request) Has been skipped
CI/CD Pipeline / Build Production Worker Image (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Canary Release to Production (pull_request) Has been skipped
CI/CD Pipeline / CI Gate (pull_request) Successful in 2s
45f98b269a
根因: watchtower 拉取新镜像后只 restart 容器,不会跑 deploy 脚本里的
`alembic upgrade head`;staging/prod 关闭了 AUTO_CREATE_SCHEMA,
_ensure_viral_video_columns 不会执行,导致新列(copy_result/voice_id/
video_ratio/video_model)缺失,POST analyze-images 与 GET history 全部 500。

修复:
- 新增 API 容器 entrypoint-api.sh:容器启动先幂等 alembic upgrade head,
  失败仅告警不阻塞 uvicorn;支持显式 CMD 透传(CI 用 docker run/
  compose run 传 sh -c '...' 时行为不变)。
- Worker 容器 entrypoint-worker.sh 同步加 alembic 步骤,避免 worker 先
  于 API 启动时 Celery task 读新列报错。
- 修复 worker.Dockerfile 漏 COPY alembic/(只有 alembic.ini 没有 env.py/
  versions,alembic 命令无法执行)。
- api.Dockerfile 用 ENTRYPOINT 替换原 CMD,entrypoint 内部 exec uvicorn。

tts/presets 401 由前端裸 fetch 未带 Bearer token 导致,已在 #2128
(5226680) 改为通过 apiClient 调用 voices/presets,一并随本次部署生效。

🚀 预览环境已部署

项目 详情
PR号 #2129
预览链接 https://pr-2129.preview.xiaoxiajianji.com
API环境 staging

💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。

🔄 每次提交新代码后预览环境会自动更新。

🗑️ PR 关闭或合并后,预览环境会自动清理。

🚀 **预览环境已部署** | 项目 | 详情 | |------|------| | PR号 | #2129 | | 预览链接 | [https://pr-2129.preview.xiaoxiajianji.com](https://pr-2129.preview.xiaoxiajianji.com) | | API环境 | staging | > 💡 预览环境使用 staging API 数据,请勿在预览环境中操作重要数据。 > > 🔄 每次提交新代码后预览环境会自动更新。 > > 🗑️ PR 关闭或合并后,预览环境会自动清理。
xiaoxia merged commit 61142c0936 into develop 2026-10-01 20:12:49 +08:00

🗑️ 预览环境已清理

PR #2129 已关闭或合并,对应的预览环境已被清理。

如有需要,可以重新打开 PR 来重新生成预览环境。

🗑️ **预览环境已清理** PR #2129 已关闭或合并,对应的预览环境已被清理。 > 如有需要,可以重新打开 PR 来重新生成预览环境。
Sign in to join this conversation.