Files
xiaoxia-saas/docs/PRODUCTION-RELEASE-CHECKLIST.md
T

9.1 KiB
Raw Blame History

Production Release Checklist

小虾 SaaS 生产发布前必须逐项确认。本清单用于首次生产 Alembic 接入和后续 v* tag 发布。

1. 发布前冻结

  • 确认目标 commit 已在 develop 部署到 staging,并完成 smoke。
  • 确认 staging /health healthy。
  • 确认 staging alembic_version 等于当前 head。
  • 确认 CI validate job 通过:format、lint、Bandit、Alembic offline SQL、schema metadata drift、pytest。
  • 确认没有未提交的 schema 变更:models、Alembic revision、schema snapshot 必须一起提交。

2. 生产环境检查

  • /var/lib/xiaoxia-saas-production/.env 存在且权限正确。首次初始化必须使用非部署脚本生成独立 production env
scripts/init_production_env.sh

脚本只创建目录和 .env,不会启动应用容器;生成后必须人工替换 CHANGE_ME_PRODUCTION_DB_PASSWORD,并确认生产 DB/Redis 使用 xiaoxia-postgres-production / xiaoxia-redis-production,不得复用 staging 的 xiaoxia-postgres / xiaoxia-redis

生产基础设施使用独立 compose project 和端口:

  • Postgresxiaoxia-postgres-production,宿主端口 5433

  • Redisxiaoxia-redis-production,宿主端口 6380

  • API 预留端口:8001

  • Web 预留端口:30023000 已被 Gitea 占用)。

  • APP_ENV=production

  • DEBUG=false

  • AUTO_CREATE_SCHEMA=false

  • JWT_SECRET_KEY 已替换为生产强密钥。

  • DATABASE_URL 指向生产数据库。

  • REDIS_URL 指向生产 Redis。

  • OSS 配置已确认或明确保持本地 fallback。

  • GENERATED_FILES_HOST_DIR 生产环境不得指向 staging 目录。

  • 本地校验文件:python scripts/validate_release_env.py /var/lib/xiaoxia-saas-production/.env --strict-externalSMTP 仅在 ENABLE_EMAIL_DELIVERY=true 时强制)。

  • 容器内校验已注入环境:docker exec xiaoxia-api-production python /app/scripts/validate_release_env.py --from-environ --strict-externalSMTP 仅在启用邮件时强制)。

  • 外部服务 smokedocker exec xiaoxia-api-production python /app/scripts/smoke_external_services.py --strict --skip-smtpSMTP 未启用时)。

  • SMTP 真发信 smoke(启用邮件前必须执行):docker exec xiaoxia-api-production python /app/scripts/smoke_external_services.py --strict --send-email-to <测试邮箱>

  • 如开启邮件/session

    • ENABLE_EMAIL_DELIVERY=true 前先验证 SMTP 凭证。
    • ENABLE_REDIS_SESSIONS=true 前先验证 Redis 连通性。

3. 数据库备份

生产 Alembic 升级前必须创建数据库备份。优先使用脚本:

BACKUP_ROOT=/root/xiaoxia-backups \
POSTGRES_CONTAINER=xiaoxia-postgres \
POSTGRES_USER=xiaoxia \
POSTGRES_DB=xiaoxia_saas \
scripts/backup_postgres.sh

脚本会输出备份目录,并写入 manifest.txtalembic_version.txt

手动等价命令:

BACKUP_DIR=/root/xiaoxia-backups/$(date +%Y%m%d-%H%M%S)
mkdir -p "$BACKUP_DIR"
docker exec xiaoxia-postgres pg_dump -U xiaoxia -d xiaoxia_saas -Fc > "$BACKUP_DIR/xiaoxia_saas.dump"
docker exec xiaoxia-postgres psql -U xiaoxia -d xiaoxia_saas -Atc 'select version_num from alembic_version;' > "$BACKUP_DIR/alembic_version.txt" 2>/dev/null || true

确认备份非空:

test -s "$BACKUP_DIR/xiaoxia_saas.dump"
ls -lh "$BACKUP_DIR"

4. 首次 Alembic 接入判断

发布前只读检查生产库状态:

docker exec xiaoxia-api-production python /app/scripts/alembic_preflight.py

也可手动检查:

docker exec xiaoxia-postgres psql -U xiaoxia -d xiaoxia_saas -Atc "select to_regclass('public.alembic_version');"
docker exec xiaoxia-postgres psql -U xiaoxia -d xiaoxia_saas -Atc "select count(*) from pg_tables where schemaname='public' and tablename != 'alembic_version';"

脚本 recommended_action 判断规则:

  • 已存在 alembic_version:执行 alembic upgrade head
  • 有业务表但没有 alembic_version:先执行 alembic stamp head,再执行 alembic upgrade head
  • 空库:执行 alembic upgrade head

生产首次接入不允许使用 Base.metadata.create_all() 或历史 SQL 快照。

5. 生产外部服务验证

上线前必须完成真实凭证 smoke,不能用 no-op 结果替代:

docker exec xiaoxia-api-production python /app/scripts/validate_release_env.py --from-environ --strict-external
docker exec xiaoxia-api-production python /app/scripts/smoke_external_services.py --strict --skip-smtp
docker exec xiaoxia-api-production python /app/scripts/smoke_external_services.py --strict --send-email-to <测试邮箱>

Staging 当前验证状态(2026-06-21):

  • Redis session smoke:通过。
  • SMTP strict smokeMVP 阶段允许 --skip-smtp,但启用 ENABLE_EMAIL_DELIVERY=true 前必须补真实 SMTP 凭证和真发信 smoke。
  • OSS strict smoke:阻塞,缺少 OSS 环境变量/真实凭证。

缺少真实 OSS 凭证时不得把生产上传作为已验收项。SMTP 若暂不启用,必须保持 ENABLE_EMAIL_DELIVERY=false 并在 strict smoke 中显式使用 --skip-smtp

6. OSS 生命周期与生成文件保留

Production 推荐使用 OSS lifecycle rule 管理生成文件,不建议长期依赖本地 fallback。

建议策略:

  • 临时/失败任务产物:7 天后删除。
  • 已完成但未购买/未收藏产物:按产品套餐定义保留期。
  • 已购买/订单关联产物:按订单合规要求保留,不由通用 cleanup 删除。
  • 本地 fallback:每日 dry-run,每周人工复核后 --apply,并配置磁盘告警。

本地 fallback dry-run

python scripts/cleanup_generated_files.py --dir /var/lib/xiaoxia-saas-production/generated --days 7

确认后执行:

python scripts/cleanup_generated_files.py --dir /var/lib/xiaoxia-saas-production/generated --days 7 --apply

OSS 生命周期规则必须在云控制台或 IaC 中绑定到生产 bucket,并在发布记录里写明 rule id。

7. 发布执行

  • 只能通过 v* tag 触发 production deploy。

  • 生产 API/Worker 必须使用预构建 runtime image tar,不允许生产机临时 build。

  • 生产 Web 必须使用预构建 apps/web/dist,不允许生产机运行 npm/Node build。

  • 当前标准链路:

    1. 推送 v* tag。
    2. Gitea build-production-runtime-images job 在 runtime-builder 上运行。
    3. runtime-builder 执行 scripts/build_release_images.sh <tag> 生成 runtime-images-<tag>.tar
    4. runtime-builder 用 Node Docker 容器构建 apps/web/dist
    5. runtime-builder 打包 release-<tag>.tar.gz,必须保留 apps/web/dist/index.html,同时排除根目录 ./dist,避免把 runtime tar 再包进 release tar。
    6. runtime-builder 上传两个产物到生产:
      • /var/lib/xiaoxia-saas-production/runtime-images-<tag>.tar
      • /var/lib/xiaoxia-saas-production/release-<tag>.tar.gz
    7. Gitea deploy-production job 也在 runtime-builder 上运行,通过 SSH 驱动生产机部署。
    8. SSH 部署必须传 HOST_PREFIX=,因为 infra/docker/deploy-production.sh 默认 /host 是给 Docker-in-Docker CI 场景用的。
    9. 生产机只解包 artifact、复制 .envdocker load runtime images、运行 Alembic、重启容器和 health check。
  • 发布期间持续观察 Gitea Actions deploy log。

  • 部署后确认:

curl -fsS http://127.0.0.1:8001/health
docker ps --format '{{.Names}} {{.Image}} {{.Status}}' | grep xiaoxia
docker exec xiaoxia-postgres-production psql -U xiaoxia -d xiaoxia_saas -Atc 'select version_num from alembic_version;'
ls -lh /var/lib/xiaoxia-saas-production/runtime-images-<tag>.tar /var/lib/xiaoxia-saas-production/release-<tag>.tar.gz
  • 缺少 runtime image tar、release tar 或 apps/web/dist/index.html 时,生产部署必须失败,禁止静默复用旧镜像或在生产机补 build。

  • v0.1.6v0.1.7v0.1.8 是 release-chain 修复过程中的失败/中间态 tag,不作为回滚目标;当前可用回滚基准是已验证的 v0.1.5v0.1.9

8. Smoke 测试

生产发布后至少验证:

  • /health 返回 healthy。
  • 注册/登录//auth/me 正常。
  • 创建 workspace 正常。
  • 核心视频生成链路可创建任务。
  • 生成文件下载 URL 返回真实文件,不返回前端 HTML fallback。

9. 回滚策略

生成恢复计划(不会自动恢复数据库):

scripts/restore_postgres_plan.sh /root/xiaoxia-backups/<backup-dir>

应用回滚:

  • 若数据库未发生不可逆迁移,优先回滚到上一稳定 tag 并重新部署。
  • 保留当前失败容器日志后再回滚。

数据库回滚:

  • Alembic downgrade 只有在 revision 明确支持且已验证时才能执行。
  • 首次生产接入阶段默认使用备份恢复作为最终兜底。
  • 恢复前必须二次确认备份路径、目标数据库、停机窗口。
  • 恢复步骤必须先由 scripts/restore_postgres_plan.sh 生成并复核,不允许紧急状态下即兴拼命令。

10. 发布记录

每次生产发布后,在 docs/PHASE7-PROGRESS.md 或对应 release note 记录:

  • tag
  • commit
  • Alembic before/after version
  • backup path
  • smoke 结果
  • OSS lifecycle rule id / 本地 cleanup 结果