From a4202d282d02b760a345ecf47481d4623935ca4b Mon Sep 17 00:00:00 2001 From: Xiaoxia AI Date: Sun, 21 Jun 2026 07:25:30 +0800 Subject: [PATCH] docs: record alembic staging verification --- docs/DEPLOYMENT.md | 9 ++++++ docs/SCHEMA-MAINLINE.md | 48 +++++++++++++++++++---------- docs/全面代码审计报告-2026-06-21.md | 14 ++++++--- 3 files changed, 50 insertions(+), 21 deletions(-) diff --git a/docs/DEPLOYMENT.md b/docs/DEPLOYMENT.md index c83654082..df3a3cc85 100644 --- a/docs/DEPLOYMENT.md +++ b/docs/DEPLOYMENT.md @@ -55,6 +55,14 @@ WEB_PORT=3001 docker compose -f infra/docker/compose.yml up -d --build infra/docker/deploy-staging.sh ``` +部署脚本会在服务启动前执行 Alembic: + +- 已存在 `alembic_version` 时执行 `alembic upgrade head` +- 已存在业务表但缺少 `alembic_version` 时执行 `alembic stamp head && alembic upgrade head` +- 空库时执行 `alembic upgrade head` + +staging 已在 2026-06-21 验证:`alembic_version = 001`,健康检查通过。 + --- ## Gitea Actions 约定 @@ -74,3 +82,4 @@ infra/docker/deploy-staging.sh - `.env.production` 不要提交真实密钥。 - OSS、数据库、Redis、JWT 密钥必须通过服务器环境文件注入。 - 生产环境必须设置 `DEBUG=false`。 +- staging / production 不允许开启 `AUTO_CREATE_SCHEMA` 绕过 Alembic。 diff --git a/docs/SCHEMA-MAINLINE.md b/docs/SCHEMA-MAINLINE.md index 81c8b0e28..b5fdb7762 100644 --- a/docs/SCHEMA-MAINLINE.md +++ b/docs/SCHEMA-MAINLINE.md @@ -2,12 +2,28 @@ ## 当前结论 -小虾 SaaS 当前运行时数据库结构的唯一主线是: +小虾 SaaS 当前数据库结构主线已经切换为: -- `packages/adapters/sqlalchemy_impl/models.py` -- `packages/adapters/sqlalchemy_impl/session.py::initialize_database()` +- Schema 定义真源:`packages/adapters/sqlalchemy_impl/models.py` +- 迁移执行真源:`alembic/versions/001_current_schema_baseline.py` 及后续 Alembic revisions +- 部署执行入口:`infra/docker/deploy-staging.sh` 中的 `alembic upgrade head` -`initialize_database()` 使用 SQLAlchemy `Base.metadata.create_all()` 创建缺失表,并通过 PostgreSQL advisory lock 避免多实例并发初始化。 +`packages/adapters/sqlalchemy_impl/session.py::initialize_database()` 仍保留为开发/测试兜底函数,但 API 和 Worker 默认不再调用它: + +- `apps/api/app/config.py::AUTO_CREATE_SCHEMA = False` +- `apps/worker/worker_app/core/config.py::auto_create_schema = False` + +staging / production 不允许依赖 `Base.metadata.create_all()` 建表;表结构变更必须进入 Alembic revision。 + +## 已验证状态 + +截至 2026-06-21: + +- Alembic baseline revision 已落地:`001_current_schema_baseline.py` +- staging 已完成 baseline stamp / upgrade +- staging 数据库 `alembic_version` 已确认:`001` +- staging health endpoint 已确认 healthy +- `develop` 部署 job 已确认 succeeded ## 已废弃入口 @@ -23,26 +39,25 @@ - 当前 SQLAlchemy 使用 `assets.asset_library_id/file_url/file_type` - 历史 SQL 文件没有完整覆盖 `generation_tasks/generated_videos/tasks/milestones/task_issues` -## 过渡原则 +## 当前原则 -在正式引入 Alembic 前: - -1. 运行时只允许 SQLAlchemy models 创建表。 -2. 新字段必须先改 `packages/adapters/sqlalchemy_impl/models.py`。 +1. 新字段必须先改 `packages/adapters/sqlalchemy_impl/models.py`。 +2. 每次 schema 变更必须新增 Alembic revision。 3. Repository 映射必须和 SQLAlchemy model 同步。 4. Pydantic schema 只能表达 API 契约,不作为数据库真源。 5. Domain dataclass 只能表达业务实体,不作为数据库真源。 6. 历史 SQL 文件只允许作为参考,不允许部署脚本调用。 +7. staging / production 只允许通过 Alembic 升级 schema。 +8. `AUTO_CREATE_SCHEMA` 只能作为开发/测试兜底,不得在生产环境开启。 -## 下一步:Alembic 化 +## 下一步 -后续应建立 Alembic 正式迁移链: +后续 schema 工作应继续推进: -1. 以当前 staging 数据库实际结构生成 baseline revision。 -2. 以 SQLAlchemy models 作为 autogenerate metadata。 -3. 之后所有 schema 变更必须走 Alembic revision。 -4. CI 增加迁移检查:`alembic upgrade head`。 -5. 停止在生产入口调用 `Base.metadata.create_all()`,只保留开发/测试兜底。 +1. CI 增加迁移检查:`alembic upgrade head`。 +2. 新增 revision drift 检查,防止 models 已改但未生成 migration。 +3. 移除或更严格环境门控 API/Worker 中的 `initialize_database()` 兜底路径。 +4. 对 production 首次接入 Alembic 前,先执行只读 schema/数据备份检查。 ## 禁止事项 @@ -50,3 +65,4 @@ - 不要手工维护和 SQLAlchemy models 平行的 CREATE TABLE 文件。 - 不要让 API schema 或 domain entity 直接驱动数据库 schema。 - 不要在部署脚本中执行历史 SQL 快照。 +- 不要在 staging / production 打开 `AUTO_CREATE_SCHEMA` 绕过 Alembic。 diff --git a/docs/全面代码审计报告-2026-06-21.md b/docs/全面代码审计报告-2026-06-21.md index 84c917094..efaac0e6f 100644 --- a/docs/全面代码审计报告-2026-06-21.md +++ b/docs/全面代码审计报告-2026-06-21.md @@ -233,19 +233,23 @@ **涉及文件**:`init-tables.sql`、`migrations/*.sql`、`packages/adapters/sqlalchemy_impl/models.py`、`docs/SCHEMA-MAINLINE.md` **问题**: -- `init-tables.sql`、`migrations/*.sql`、SQLAlchemy models 同时定义表结构。 +- `init-tables.sql`、`migrations/*.sql`、SQLAlchemy models 曾同时定义表结构。 - 字段已经漂移,例如历史 SQL 使用 `assets.library_id/storage_key/mime_type`,当前 SQLAlchemy 使用 `assets.asset_library_id/file_url/file_type`。 -- 运行时实际由 SQLAlchemy `Base.metadata.create_all()` 建表,但文档仍引用历史 SQL。 +- 旧运行时曾由 SQLAlchemy `Base.metadata.create_all()` 建表,部署缺少正式 migration 主线。 **根因**: - Phase 迁移过程中 SQL 快照没有退役。 -- Alembic 迁移链尚未建立,SQLAlchemy models 临时成为事实真源。 +- Alembic 迁移链曾存在但 revision 已过期,和当前 SQLAlchemy model 不一致。 **修复**: - `init-tables.sql` 改为 deprecated sentinel,误执行会直接失败。 -- 新增 `docs/SCHEMA-MAINLINE.md`,明确当前 schema 唯一主线是 SQLAlchemy models。 +- 新增并更新 `docs/SCHEMA-MAINLINE.md`,明确 SQLAlchemy models 是 schema 定义真源,Alembic 是迁移执行真源。 +- 删除 stale Alembic revisions,新增 `alembic/versions/001_current_schema_baseline.py` 作为当前 schema baseline。 +- `alembic/env.py` 改为从 `DATABASE_URL` 读取连接,并启用 `compare_type=True`。 +- `infra/docker/deploy-staging.sh` 在服务启动前执行 `alembic upgrade head`;已有业务表但无版本表时执行 `alembic stamp head && alembic upgrade head`。 +- API/Worker 默认关闭 `AUTO_CREATE_SCHEMA`,不再默认调用 `Base.metadata.create_all()`。 +- staging 已验证:`alembic_version = 001`,health check healthy,`develop` 部署 job succeeded。 - 架构守卫禁止运行时代码引用 `init-tables.sql` 或历史 `migrations/001_initial_schema.sql`。 -- 明确下一步 Alembic 化路线。 ## 三、已补充测试