fix(ci): 修复integration-tests needs依赖 + push事件auto-fix支持 #766
@@ -395,7 +395,9 @@ jobs:
|
||||
if: always() && needs.check-frontend-only.outputs.skip_backend != 'true'
|
||||
needs:
|
||||
- check-frontend-only
|
||||
- validate
|
||||
- validate-code-quality
|
||||
- validate-type-check
|
||||
- validate-migration
|
||||
env:
|
||||
DATABASE_URL: postgresql+psycopg://postgres:postgres@host.docker.internal:5432/xiaoxia_saas
|
||||
USE_IN_MEMORY_DB: 'false'
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#!/usr/bin/env python3
|
||||
"""CI中自动修复代码格式(Python: black + isort | Frontend: prettier),并推送回PR分支。
|
||||
"""CI中自动修复代码格式(Python: black + isort | Frontend: prettier),并推送回原分支。
|
||||
|
||||
只在PR事件中执行,避免直接修改主干。
|
||||
当code quality检查因格式问题失败时触发,自动修复后push回原分支。
|
||||
- PR事件:自动修复并push回PR源分支(Agent提交的PR自动修,人提交的仅诊断)
|
||||
- Push事件(develop/main):自动修复并push回原分支,保持主干格式永远正确
|
||||
当code quality检查因格式问题失败时触发。
|
||||
"""
|
||||
|
||||
import json
|
||||
@@ -74,6 +75,45 @@ def ensure_git_repo(api_url, repo, token, pr_number):
|
||||
return head_branch
|
||||
|
||||
|
||||
def ensure_git_repo_for_push(api_url, repo, token, branch_name):
|
||||
"""push事件下确保git仓库可用,并切换到目标分支。
|
||||
|
||||
checkout脚本用tarball方式下载代码,没有.git目录。
|
||||
这里自动初始化git仓库,fetch目标分支并checkout。
|
||||
"""
|
||||
if os.path.exists(".git"):
|
||||
# 已有git,确认在正确分支
|
||||
result = run("git rev-parse --abbrev-ref HEAD", check=False)
|
||||
if result.stdout.strip() == branch_name:
|
||||
return
|
||||
# 不在目标分支,切换
|
||||
run(f"git checkout {branch_name}", check=False)
|
||||
return
|
||||
|
||||
print(f"检测到tarball checkout(无.git目录),初始化git仓库(push模式,分支: {branch_name})...")
|
||||
|
||||
server_url = api_url.rsplit("/api/v1", 1)[0]
|
||||
remote_url = f"{server_url.replace('https://', f'https://x-access-token:{token}@')}/{repo}.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"')
|
||||
|
||||
print(f"fetch {branch_name} 分支...")
|
||||
run(f"git fetch --depth=1 origin {branch_name}")
|
||||
|
||||
print(f"切换到 {branch_name} 分支...")
|
||||
run(f"git checkout -f -B {branch_name} FETCH_HEAD")
|
||||
|
||||
result = run("git status --porcelain")
|
||||
if result.stdout.strip():
|
||||
n = len(result.stdout.strip().splitlines())
|
||||
print(f"⚠️ 工作区有 {n} 个未追踪文件")
|
||||
else:
|
||||
print("✅ git仓库就绪,工作区clean")
|
||||
|
||||
|
||||
def get_changed_files(pr_number, api_url, token):
|
||||
"""获取PR中变更的文件列表"""
|
||||
url = f"{api_url}/pulls/{pr_number}/files?limit=100"
|
||||
@@ -155,43 +195,11 @@ def fix_frontend(target_fe_files, scan_mode, repo_root):
|
||||
|
||||
|
||||
def main():
|
||||
# 只在PR事件中执行
|
||||
event_name = os.environ.get("GITHUB_EVENT_NAME", "")
|
||||
if event_name != "pull_request":
|
||||
print("非PR事件,跳过自动修复")
|
||||
return
|
||||
|
||||
github_ref = os.environ.get("GITHUB_REF", "")
|
||||
pr_number = github_ref.split("/")[2] if github_ref.startswith("refs/pull/") else ""
|
||||
if not pr_number:
|
||||
print("无法获取PR号,跳过自动修复")
|
||||
return
|
||||
|
||||
api_url = os.environ.get("GITHUB_API_URL", "")
|
||||
repo = os.environ.get("GITHUB_REPOSITORY", "")
|
||||
token = os.environ.get("REVIEW_TOKEN", "") or os.environ.get("GITHUB_TOKEN", "")
|
||||
|
||||
# 获取PR作者信息,判断是人还是Agent提交的
|
||||
pr_info_url = f"{api_url}/repos/{repo}/pulls/{pr_number}"
|
||||
req_pr = urllib.request.Request(pr_info_url, headers={"Authorization": f"token {token}"})
|
||||
with urllib.request.urlopen(req_pr) as resp:
|
||||
pr_info = json.loads(resp.read())
|
||||
pr_author = pr_info.get("user", {}).get("login", "")
|
||||
print(f"PR作者: {pr_author}")
|
||||
|
||||
# 判断是否为Agent提交的PR
|
||||
# Agent账号:actions, auto-approve-bot 等bot用户
|
||||
# 人提交的PR(如xiaoxia):只诊断不自动修
|
||||
agent_authors = {"actions", "auto-approve-bot", "gitea-actions"}
|
||||
is_agent_pr = pr_author in agent_authors or "bot" in pr_author.lower()
|
||||
|
||||
if is_agent_pr:
|
||||
print(f"检测到Agent提交的PR(作者: {pr_author}),将自动修复并推送")
|
||||
fix_mode = "auto_fix_and_push"
|
||||
else:
|
||||
print(f"检测到人提交的PR(作者: {pr_author}),仅诊断不自动修改")
|
||||
print("(如需自动修复,请用Agent账号提交PR,或手动运行格式化脚本)")
|
||||
fix_mode = "diagnose_only"
|
||||
scan_mode = os.environ.get("SCAN_MODE", "full")
|
||||
changed_files_env = os.environ.get("CHANGED_FILES", "")
|
||||
|
||||
@@ -201,13 +209,67 @@ def main():
|
||||
|
||||
repo_root = os.getcwd()
|
||||
|
||||
# 确保git仓库可用(tarball checkout模式下自动初始化)
|
||||
# 返回PR源分支名,供后续推送使用
|
||||
head_branch = ensure_git_repo(api_url, repo, token, pr_number)
|
||||
# ====== Push事件处理(develop/main等受保护分支) ======
|
||||
if event_name == "push":
|
||||
# 从 refs/heads/xxx 提取分支名
|
||||
if not github_ref.startswith("refs/heads/"):
|
||||
print(f"push事件但refs格式异常: {github_ref},跳过")
|
||||
return
|
||||
branch_name = github_ref.replace("refs/heads/", "")
|
||||
|
||||
print("=== 检测到代码格式问题,尝试自动修复 ===")
|
||||
print(f"PR #{pr_number}")
|
||||
print(f"扫描模式: {scan_mode}")
|
||||
# 只在受保护分支(develop/main)上自动修复并推送
|
||||
protected_branches = {"develop", "main", "master"}
|
||||
if branch_name not in protected_branches:
|
||||
print(f"push事件,分支 {branch_name} 不是受保护分支,跳过自动修复")
|
||||
return
|
||||
|
||||
print("=== Push事件:检测到格式问题,自动修复并推送回原分支 ===")
|
||||
print(f"分支: {branch_name}")
|
||||
print(f"扫描模式: {scan_mode}")
|
||||
|
||||
# 初始化git仓库
|
||||
ensure_git_repo_for_push(api_url, repo, token, branch_name)
|
||||
head_branch = branch_name
|
||||
fix_mode = "auto_fix_and_push"
|
||||
|
||||
# ====== PR事件处理 ======
|
||||
elif event_name == "pull_request":
|
||||
pr_number = github_ref.split("/")[2] if github_ref.startswith("refs/pull/") else ""
|
||||
if not pr_number:
|
||||
print("无法获取PR号,跳过自动修复")
|
||||
return
|
||||
|
||||
# 获取PR作者信息,判断是人还是Agent提交的
|
||||
pr_info_url = f"{api_url}/repos/{repo}/pulls/{pr_number}"
|
||||
req_pr = urllib.request.Request(pr_info_url, headers={"Authorization": f"token {token}"})
|
||||
with urllib.request.urlopen(req_pr) as resp:
|
||||
pr_info = json.loads(resp.read())
|
||||
pr_author = pr_info.get("user", {}).get("login", "")
|
||||
print(f"PR作者: {pr_author}")
|
||||
|
||||
# 判断是否为Agent提交的PR
|
||||
agent_authors = {"actions", "auto-approve-bot", "gitea-actions"}
|
||||
is_agent_pr = pr_author in agent_authors or "bot" in pr_author.lower()
|
||||
|
||||
if is_agent_pr:
|
||||
print(f"检测到Agent提交的PR(作者: {pr_author}),将自动修复并推送")
|
||||
fix_mode = "auto_fix_and_push"
|
||||
else:
|
||||
print(f"检测到人提交的PR(作者: {pr_author}),仅诊断不自动修改")
|
||||
print("(如需自动修复,请用Agent账号提交PR,或手动运行格式化脚本)")
|
||||
fix_mode = "diagnose_only"
|
||||
|
||||
print("=== 检测到代码格式问题,尝试自动修复 ===")
|
||||
print(f"PR #{pr_number}")
|
||||
print(f"扫描模式: {scan_mode}")
|
||||
|
||||
# 确保git仓库可用(tarball checkout模式下自动初始化)
|
||||
head_branch = ensure_git_repo(api_url, repo, token, pr_number)
|
||||
|
||||
# ====== 其他事件跳过 ======
|
||||
else:
|
||||
print(f"事件 {event_name} 不支持自动修复,跳过")
|
||||
return
|
||||
|
||||
# 前端文件扩展名
|
||||
fe_extensions = (
|
||||
|
||||
Reference in New Issue
Block a user