diff --git a/.gitea/workflows/ci-cd.yml b/.gitea/workflows/ci-cd.yml index af380b82e..1aacb3b99 100644 --- a/.gitea/workflows/ci-cd.yml +++ b/.gitea/workflows/ci-cd.yml @@ -65,6 +65,9 @@ jobs: python -m black --check alembic apps packages tests scripts python -m isort --check-only alembic apps packages tests scripts python -m flake8 apps packages tests --count --statistics + + - name: Run security scan + run: | bandit -r apps packages -q - name: Validate Alembic migrations diff --git a/.github/workflows/ci-cd.yml b/.github/workflows/ci-cd.yml index af380b82e..1aacb3b99 100644 --- a/.github/workflows/ci-cd.yml +++ b/.github/workflows/ci-cd.yml @@ -65,6 +65,9 @@ jobs: python -m black --check alembic apps packages tests scripts python -m isort --check-only alembic apps packages tests scripts python -m flake8 apps packages tests --count --statistics + + - name: Run security scan + run: | bandit -r apps packages -q - name: Validate Alembic migrations diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index b2672e68b..e7a24eae8 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -83,6 +83,7 @@ Staging 当前可以保持 no-op;Production 开启前必须先验证 SMTP/Redi - Staging 未配置 OSS 凭证时,生成视频落盘到 `/var/lib/xiaoxia-saas-staging/generated`,并通过 Nginx `/generated-files/` 公开访问。 - Docker volume host path 由 `GENERATED_FILES_HOST_DIR` 控制,默认仅适用于 staging:`/var/lib/xiaoxia-saas-staging/generated`。 - Production 优先使用 OSS;若临时启用本地 fallback,必须配置独立持久化目录、Nginx 只读公开路径和磁盘告警。 +- OSS lifecycle rule 必须在生产 bucket 上配置并记录 rule id:临时/失败任务产物建议 7 天删除;订单/购买关联产物由业务保留策略单独保护。 - 保留策略建议:staging 生成文件保留 7 天或保留最近 20GB;production 按业务套餐/订单状态定义,禁止无上限增长。 - 清理脚本上线前必须先 dry-run 输出待删列表,再按 workspace/project 维度删除,避免误删仍被 GeneratedVideo 记录引用的文件。 - 当前脚本:`python scripts/cleanup_generated_files.py --dir /var/lib/xiaoxia-saas-staging/generated --days 7` 仅 dry-run;确认后再加 `--apply`。 diff --git a/docs/PHASE7-PROGRESS.md b/docs/PHASE7-PROGRESS.md index ac972e294..42564fb34 100644 --- a/docs/PHASE7-PROGRESS.md +++ b/docs/PHASE7-PROGRESS.md @@ -93,7 +93,18 @@ --- -## 四、遗留后续专项 +## 四、发布/运维完善(2026-06-21) + +- [x] 生产数据库备份 runbook 已脚本化:`scripts/backup_postgres.sh` +- [x] 恢复计划脚本已脚本化且保持非破坏性:`scripts/restore_postgres_plan.sh` +- [x] Staging 临时库恢复演练已完成:backup → restore plan → restore to `xiaoxia_restore_rehearsal` → Alembic preflight → `alembic upgrade head` noop → cleanup +- [x] Bandit 已拆为 CI 独立 security scan quality gate +- [x] Staging strict 外部服务检查已执行:Redis session 通过;SMTP/OSS 因缺少真实凭证保持阻塞,不伪造验收 +- [x] OSS lifecycle / 本地 fallback cleanup 策略已写入生产发布清单 + +--- + +## 五、遗留后续专项 以下问题不阻塞 Phase 7 完成,已纳入后续专项治理清单: @@ -107,7 +118,7 @@ --- -## 五、执行策略总结 +## 六、执行策略总结 Phase 7 执行过程中的关键决策: @@ -118,7 +129,7 @@ Phase 7 执行过程中的关键决策: --- -## 六、验证清单 +## 七、验证清单 如果新会话启动后问: @@ -136,7 +147,7 @@ Phase 7 执行过程中的关键决策: --- -## 七、完成总结 +## 八、完成总结 **Phase 7 已全部完成**,核心视频剪辑业务主链路、P0 部署链路、P1 真实 smoke flow、CI/CD 自动化主链路、真实 FFmpeg 生成与公网成片下载均已打通并验证通过。 diff --git a/docs/PRODUCTION-RELEASE-CHECKLIST.md b/docs/PRODUCTION-RELEASE-CHECKLIST.md index 0f1cd99e9..3956a20fb 100644 --- a/docs/PRODUCTION-RELEASE-CHECKLIST.md +++ b/docs/PRODUCTION-RELEASE-CHECKLIST.md @@ -82,7 +82,50 @@ docker exec xiaoxia-postgres psql -U xiaoxia -d xiaoxia_saas -Atc "select count( 生产首次接入不允许使用 `Base.metadata.create_all()` 或历史 SQL 快照。 -## 5. 发布执行 +## 5. 生产外部服务验证 + +上线前必须完成真实凭证 smoke,不能用 no-op 结果替代: + +```bash +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 +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 smoke:阻塞,缺少 SMTP 环境变量/真实凭证。 +- OSS strict smoke:阻塞,缺少 OSS 环境变量/真实凭证。 + +缺少真实凭证时不得把 `ENABLE_EMAIL_DELIVERY=true` 或 OSS 生产上传作为已验收项。 + +## 6. OSS 生命周期与生成文件保留 + +Production 推荐使用 OSS lifecycle rule 管理生成文件,不建议长期依赖本地 fallback。 + +建议策略: + +- 临时/失败任务产物:7 天后删除。 +- 已完成但未购买/未收藏产物:按产品套餐定义保留期。 +- 已购买/订单关联产物:按订单合规要求保留,不由通用 cleanup 删除。 +- 本地 fallback:每日 dry-run,每周人工复核后 `--apply`,并配置磁盘告警。 + +本地 fallback dry-run: + +```bash +python scripts/cleanup_generated_files.py --dir /var/lib/xiaoxia-saas-production/generated --days 7 +``` + +确认后执行: + +```bash +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。 - 发布期间持续观察 Gitea Actions deploy log。 @@ -94,7 +137,7 @@ docker ps --format '{{.Names}} {{.Status}}' | grep xiaoxia docker exec xiaoxia-postgres psql -U xiaoxia -d xiaoxia_saas -Atc 'select version_num from alembic_version;' ``` -## 6. Smoke 测试 +## 8. Smoke 测试 生产发布后至少验证: @@ -104,7 +147,7 @@ docker exec xiaoxia-postgres psql -U xiaoxia -d xiaoxia_saas -Atc 'select versio - 核心视频生成链路可创建任务。 - 生成文件下载 URL 返回真实文件,不返回前端 HTML fallback。 -## 7. 回滚策略 +## 9. 回滚策略 生成恢复计划(不会自动恢复数据库): @@ -124,7 +167,7 @@ scripts/restore_postgres_plan.sh /root/xiaoxia-backups/ - 恢复前必须二次确认备份路径、目标数据库、停机窗口。 - 恢复步骤必须先由 `scripts/restore_postgres_plan.sh` 生成并复核,不允许紧急状态下即兴拼命令。 -## 8. 发布记录 +## 10. 发布记录 每次生产发布后,在 `docs/PHASE7-PROGRESS.md` 或对应 release note 记录: @@ -133,4 +176,4 @@ scripts/restore_postgres_plan.sh /root/xiaoxia-backups/ - Alembic before/after version - backup path - smoke 结果 -- 回滚是否需要/是否执行 +- OSS lifecycle rule id / 本地 cleanup 结果