fix(ci): 修复auto-fix在tarball checkout模式下git不可用的问题 #629

Merged
auto-approve-bot merged 4 commits from fix/ci-autofix-git-repo into develop 2026-07-20 12:27:32 +08:00
2 changed files with 62 additions and 14 deletions
+56 -12
View File
@@ -23,6 +23,56 @@ def run(cmd, check=True, capture=True, cwd=None):
return result
def ensure_git_repo(api_url, repo, token, pr_number):
"""确保当前目录是git仓库,并切换到PR源分支。
checkout脚本用tarball方式下载代码(PR merge后的commit),没有.git目录。
这里自动初始化git仓库,fetch PR源分支并强制checkout
使工作区变为PR源分支的代码,确保后续格式化修复基于源分支。
"""
if os.path.exists(".git"):
return
print("检测到tarball checkout(无.git目录),自动初始化git仓库...")
# 构造带认证的远端URL
server_url = api_url.rsplit("/api/v1", 1)[0]
remote_url = f"{server_url.replace('https://', f'https://x-access-token:{token}@')}/{repo}.git"
# 获取PR的源分支
pr_api_url = f"{api_url}/repos/{repo}/pulls/{pr_number}"
req_obj = urllib.request.Request(pr_api_url, headers={"Authorization": f"token {token}"})
with urllib.request.urlopen(req_obj) as resp:
pr = json.loads(resp.read())
head_branch = pr["head"]["ref"]
print(f"PR源分支: {head_branch}")
# 初始化git
run("git init -q")
run(f"git remote add origin {remote_url}")
run('git config user.name "CI Bot"')
run('git config user.email "ci-bot@xiaoxiajianji.com"')
# fetch源分支(浅克隆,只要最新commit)
print("fetch源分支...")
run(f"git fetch --depth=1 origin {head_branch}")
# 强制checkout到源分支(覆盖tarball内容)
# tarball是merge后的commit,源分支才是我们要修改并推送的目标
print("切换到源分支...")
run(f"git checkout -B {head_branch} FETCH_HEAD")
result = run("git status --porcelain")
if result.stdout.strip():
n = len(result.stdout.strip().splitlines())
print(f"⚠️ 工作区有 {n} 个未追踪文件")
else:
print("✅ git仓库就绪,工作区clean")
return head_branch
def get_changed_files(pr_number, api_url, token):
"""获取PR中变更的文件列表"""
url = f"{api_url}/pulls/{pr_number}/files?limit=100"
@@ -91,9 +141,7 @@ def fix_frontend(target_fe_files, scan_mode, repo_root):
if scan_mode == "incremental":
# 增量模式:只格式化变更的前端文件
# 转换为相对于 apps/web 的路径或用绝对路径
target_str = " ".join(target_fe_files)
# 从项目根目录运行,prettier 会找配置文件
cmd = f"{prettier_bin} --write {target_str}"
else:
# 全量模式:格式化整个前端目录
@@ -130,6 +178,10 @@ def main():
repo_root = os.getcwd()
# 确保git仓库可用(tarball checkout模式下自动初始化)
# 返回PR源分支名,供后续推送使用
head_branch = ensure_git_repo(api_url, repo, token, pr_number)
print("=== 检测到代码格式问题,尝试自动修复 ===")
print(f"PR #{pr_number}")
print(f"扫描模式: {scan_mode}")
@@ -149,7 +201,6 @@ def main():
".yaml",
".yml",
)
# Python 文件扩展名
py_extensions = (".py",)
# 确定要修复的文件范围
@@ -160,15 +211,13 @@ def main():
print(f"增量模式: {len(target_py_files)} 个Python文件, {len(target_fe_files)} 个前端文件")
else:
target_py_files = ["alembic", "apps", "packages", "tests", "scripts"]
# 全量模式下 prettier 在前端目录内部运行,无需传文件列表
target_fe_files = ["apps/web"] # 标记为有前端文件需要处理
target_fe_files = ["apps/web"]
print("全量模式,修复所有文件")
# Python 格式化
fix_python(target_py_files, scan_mode)
# 前端格式化
# 全量模式下直接传 web 目录标记
if scan_mode != "incremental":
fix_frontend(["apps/web"], scan_mode, repo_root)
else:
@@ -186,16 +235,11 @@ def main():
for line in result.stdout.strip().split("\n"):
print(f" {line}")
# 配置git
run('git config user.name "CI Bot"')
run('git config user.email "ci-bot@xiaoxiajianji.com"')
# 提交修复
run("git add -A")
run('git commit -m "style: auto-format with black + isort + prettier [ci skip]"')
# 获取来源分支并推送
head_branch = get_pr_head_branch(pr_number, f"{api_url}/repos/{repo}", token)
# 推送head_branch已从ensure_git_repo获取)
print(f"\nPR来源分支: {head_branch}")
run(f'git push origin "HEAD:{head_branch}"')
+6 -2
View File
@@ -100,7 +100,11 @@ if [ "$SCAN_MODE" = "incremental" ]; then
EXISTING_PY_FILES=""
for f in $CHANGED_PY_FILES; do
if [ -f "$f" ]; then
EXISTING_PY_FILES="$EXISTING_PY_FILES $f"
if [ -z "$EXISTING_PY_FILES" ]; then
EXISTING_PY_FILES="$f"
else
EXISTING_PY_FILES="$EXISTING_PY_FILES $f"
fi
fi
done
CHANGED_PY_FILES="$EXISTING_PY_FILES"
@@ -108,7 +112,7 @@ if [ "$SCAN_MODE" = "incremental" ]; then
python3 -m compileall -q $CHANGED_PY_FILES
python3 -m black --check --fast $CHANGED_PY_FILES
python3 -m isort --check-only $CHANGED_PY_FILES
RUFF_FILES=$(echo "$CHANGED_PY_FILES" | tr ' ' '\n' | grep -v '^scripts/' | tr '\n' ' ')
RUFF_FILES=$(echo "$CHANGED_PY_FILES" | tr ' ' '\n' | grep -v '^scripts/' | grep -v '^$' | xargs)
if [ -n "$RUFF_FILES" ]; then
python3 -m ruff check $RUFF_FILES --statistics
else