fix(ci): 修复数据库安全闸门误报,改为只对比main检查新增迁移
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (push) Failing after 15h3m16s
CI/CD Pipeline / Frontend Lint (push) Failing after 15h5m54s
CI/CD Pipeline / Validate Code Quality And Tests (push) Failing after 15h5m54s
CI/CD Pipeline / Staging E2E Tests (push) Failing after 1673h37m47s
CI/CD Pipeline / Deploy Production (push) Failing after 1673h39m19s
CI/CD Pipeline / Build Production Runtime Images (push) Failing after 1673h39m21s
CI/CD Pipeline / Production Browser E2E (push) Failing after 1674h10m45s

- check_migration_safety.py 新增 --diff-against 参数,支持通过 git diff 只检查新增迁移
- CI 中 prepare git 环境并 fetch origin/main,安全闸门对比 main 分支
- 避免历史已执行迁移的破坏性操作导致误报
This commit is contained in:
lingying
2026-07-08 21:48:37 +08:00
parent 537eea06b7
commit 3d4cb554b5
2 changed files with 71 additions and 8 deletions
+24 -1
View File
@@ -129,11 +129,34 @@ jobs:
grep -q "Running upgrade" /tmp/alembic-upgrade.sql
python3 scripts/check_schema_metadata.py
- name: Prepare git for migration diff
shell: sh
env:
GITHUB_TOKEN: ${{ github.token }}
run: |
set -eu
if command -v git >/dev/null 2>&1; then
git init -q
git config user.email "ci@localhost"
git config user.name "CI"
git add .
git commit -q -m "current"
REPO_URL="https://x-access-token:${GITHUB_TOKEN}@${GITHUB_SERVER_URL#https://}/${GITHUB_REPOSITORY}.git"
git remote add origin "$REPO_URL"
git fetch origin main --depth=1 -q 2>/dev/null || echo "WARN: cannot fetch main, will check all migrations"
else
echo "WARN: git not available, will check all migrations"
fi
- name: Check migration safety
shell: sh
run: |
set -eu
python3 scripts/check_migration_safety.py --allow-medium-risk
if git rev-parse origin/main >/dev/null 2>&1; then
python3 scripts/check_migration_safety.py --allow-medium-risk --diff-against origin/main
else
python3 scripts/check_migration_safety.py --allow-medium-risk
fi
- name: Run unit tests
shell: sh
+47 -7
View File
@@ -11,6 +11,16 @@
忽略 downgrade 函数中的操作(那是回滚逻辑,正常的)。
使用方式:
# 检查所有迁移(不推荐,会扫历史已执行的迁移)
python3 scripts/check_migration_safety.py
# 只检查与目标分支相比新增的迁移(推荐用于CI)
python3 scripts/check_migration_safety.py --diff-against origin/main
# 只检查指定版本之后的迁移
python3 scripts/check_migration_safety.py --since 030_xxx
退出码:
0 - 安全 / 只有非破坏性变更
1 - 检测到高风险破坏性变更
@@ -22,6 +32,7 @@ from __future__ import annotations
import argparse
import os
import re
import subprocess
import sys
from pathlib import Path
from typing import List, Tuple
@@ -60,7 +71,6 @@ def extract_upgrade_content(content: str) -> str:
从迁移文件中提取 upgrade 函数的内容。
只检查 upgrade 中的操作,忽略 downgrade。
"""
# 匹配 def upgrade(): 或 def upgrade() -> None: 等格式
upgrade_match = re.search(r"def upgrade\b[^:]*:", content)
if not upgrade_match:
return ""
@@ -78,12 +88,35 @@ def extract_upgrade_content(content: str) -> str:
return content[upgrade_start:upgrade_end]
def find_new_migrations(since_revision: str | None = None) -> List[Path]:
def get_new_migrations_via_diff(diff_target: str) -> List[Path]:
"""
找出新增的迁移文件。
如果指定了 since_revision,则找出该版本之后的所有迁移;
否则找出所有迁移文件。
通过 git diff 对比目标分支/commit,找出 alembic/versions/ 下新增的迁移文件。
只包含新增文件(A状态),不包含修改或删除的文件。
"""
try:
result = subprocess.run(
["git", "diff", "--name-only", "--diff-filter=A", diff_target, "HEAD", "--", "alembic/versions/"],
cwd=str(REPO_ROOT),
capture_output=True,
text=True,
check=True,
)
files = [line.strip() for line in result.stdout.strip().split("\n") if line.strip()]
return [REPO_ROOT / f for f in files]
except subprocess.CalledProcessError as e:
print(f"⚠️ git diff 失败({diff_target}):{e.stderr.strip()}")
print(f" 降级为检查所有迁移文件")
return sorted(ALEMBIC_VERSIONS_DIR.glob("*.py"))
def find_new_migrations(since_revision: str | None = None, diff_against: str | None = None) -> List[Path]:
"""
找出需要检查的迁移文件。
优先级:diff_against > since_revision > 全部
"""
if diff_against:
return get_new_migrations_via_diff(diff_against)
all_migrations = sorted(ALEMBIC_VERSIONS_DIR.glob("*.py"))
if not since_revision:
return all_migrations
@@ -134,6 +167,11 @@ def main() -> int:
default=os.getenv("MIGRATION_SINCE_REVISION"),
help="只检查指定版本之后的迁移(如:030_xxx),不传则检查所有迁移",
)
parser.add_argument(
"--diff-against",
default=os.getenv("MIGRATION_DIFF_AGAINST"),
help="对比指定分支/commit,只检查新增的迁移文件(推荐用于CI,如 origin/main)",
)
parser.add_argument(
"--warn-only",
action="store_true",
@@ -146,13 +184,15 @@ def main() -> int:
)
args = parser.parse_args()
migrations = find_new_migrations(args.since)
migrations = find_new_migrations(args.since, args.diff_against)
if not migrations:
print("✅ 未找到需要检查的迁移文件")
print("✅ 未找到需要检查的新增迁移文件,跳过")
return 0
print(f"🔍 正在检查 {len(migrations)} 个迁移文件的 upgrade 操作...")
if args.diff_against:
print(f" (对比基准:{args.diff_against},仅检查新增迁移)")
print()
all_high = []