ci: freeze applied migrations behind a sha256 manifest

sqlx re-validates applied-migration checksums on every startup, so any byte
change to a released migration file locks existing deployments out of
starting with no automatic recovery. Record the released migrations in
backend/migrations/.frozen-sha256 and fail CI when a frozen file changes or
a new migration lands without being enrolled. Document the freeze rule and
the local test-database environment in backend/migrations/README.md. The
migration files themselves stay byte-identical: adding even a header
comment would trip the same startup validation this guard protects.

Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
zyycn
2026-07-26 23:20:38 +08:00
co-authored by Claude
parent 495c19b5e4
commit 720eb0c227
3 changed files with 47 additions and 0 deletions
+15
View File
@@ -65,6 +65,21 @@ jobs:
with:
ref: ${{ inputs.ref }}
# 已应用迁移的字节被 sqlx 启动校验钉死:改动已发布迁移会让所有
# 存量部署重启即失败。冻结清单保证旧文件不被改、新文件必须入册。
- name: Migration freeze check
working-directory: backend/migrations
shell: bash
run: |
set -euo pipefail
sha256sum --check --strict .frozen-sha256
for file in *.sql; do
if ! awk '{print $2}' .frozen-sha256 | grep -Fxq "$file"; then
echo "::error file=backend/migrations/$file::migration $file is not frozen; append its sha256 to backend/migrations/.frozen-sha256"
exit 1
fi
done
- name: Setup Rust
uses: dtolnay/rust-toolchain@1a3a6d54512beeaffd394f8d516ca16f2c506a20 # 1.97
with:
+2
View File
@@ -0,0 +1,2 @@
b3b5e7a9b46460c2f0f4a4248768c68ff5fd09d90f902078b38bf707b9609cae 0001_initial.sql
886c1acad435c61f4b29a45762daf922923aec845b11955f452950c4de351932 0002_retention_delete_indexes.sql
+30
View File
@@ -0,0 +1,30 @@
# 数据库迁移
sqlx 在服务启动时(`serve` 监听之前)按编号顺序执行本目录的迁移,并把每个
文件的 checksum 记入 `_sqlx_migrations`。此后每次启动都会重新校验:**已应用
迁移的文件字节与记录不一致时,服务直接拒绝启动**。
## 冻结规则
- 已合入 main 的迁移文件**永久冻结**,一个字节都不能改——包括注释和空白。
任何改动都会让所有已部署实例(含自更新链路上的存量用户)在下次重启时
因 checksum 失配而无法启动,且没有自动恢复路径。
- schema 变更一律新增编号迁移(`0003_...`、`0004_...`),永远不回改旧文件。
- `.frozen-sha256` 是冻结清单(`sha256sum` 格式)。CI 会校验:清单内文件
字节未变,且目录里每个 `*.sql` 都已入册。新增迁移时在同一提交里执行
`sha256sum 000N_xxx.sql >> .frozen-sha256` 入册。
- 若确需修正已冻结迁移里的错误,用新迁移做补偿性变更(`alter` / 回填),
不要动原文件。
## 本地测试库
`gateway-store` 的 PG/Redis 集成测试需要以下环境变量,未设置时在本地
静默跳过(CI 缺失则直接失败):
```bash
export CPR_TEST_DATABASE_URL='postgres://<user>:<password>@127.0.0.1:5432/<db>'
export CPR_TEST_REDIS_URL='redis://:<password>@127.0.0.1:6379'
```
测试自建随机 schema / key 前缀做隔离,可安全指向开发库;凭据按本地部署
实际值填写(`docker inspect` 对应容器可查)。