test
Some checks failed
API Parameter Change Check / api-param-check (push) Failing after 3s

This commit is contained in:
2026-06-03 15:02:21 +08:00
parent 2eacae577c
commit 556f5b8ab6
25 changed files with 2119 additions and 0 deletions

140
.gitea/checker/git_utils.py Normal file
View File

@@ -0,0 +1,140 @@
"""
Git 操作工具模块。
负责在 CI 环境中检出上一版本代码、获取变更文件列表及提交元信息。
"""
import os
import subprocess
from dataclasses import dataclass
from pathlib import Path
from typing import List, Optional
@dataclass
class CommitInfo:
"""单次 Git 提交的元信息。"""
sha: str
author: str
commit_time: str
message: str
def run_git(args: List[str], cwd: Optional[Path] = None) -> str:
"""
执行 git 命令并返回标准输出。
:param args: git 子命令及参数,如 ["log", "-1", "--format=%H"]
:param cwd: 工作目录,默认为当前目录
:return: 命令 stdout 文本(已 strip
:raises RuntimeError: git 命令执行失败时抛出
"""
cmd = ["git"] + args
result = subprocess.run(
cmd,
cwd=cwd,
capture_output=True,
text=True,
encoding="utf-8",
errors="replace",
)
if result.returncode != 0:
raise RuntimeError(f"Git 命令失败: {' '.join(cmd)}\n{result.stderr}")
return result.stdout.strip()
def get_current_commit() -> CommitInfo:
"""
获取当前 HEAD 提交的元信息(推送人、时间等,用于通知模板)。
:return: CommitInfo 对象
"""
sha = run_git(["rev-parse", "HEAD"])
author = run_git(["log", "-1", "--format=%an"])
commit_time = run_git(["log", "-1", "--format=%ci"])
message = run_git(["log", "-1", "--format=%s"])
return CommitInfo(sha=sha, author=author, commit_time=commit_time, message=message)
def get_previous_commit_sha() -> Optional[str]:
"""
获取上一次提交的 SHAHEAD~1
若是首次提交则返回 None。
:return: 上一 commit SHA或 None
"""
try:
return run_git(["rev-parse", "HEAD~1"])
except RuntimeError:
return None
def checkout_commit(sha: str, worktree_dir: Path) -> None:
"""
将指定 commit 的代码检出到独立工作目录(不影响当前工作区)。
:param sha: 目标 commit SHA
:param worktree_dir: git worktree 目录
"""
worktree_dir.parent.mkdir(parents=True, exist_ok=True)
if worktree_dir.exists():
# 已存在则先移除旧 worktree
run_git(["worktree", "remove", "--force", str(worktree_dir)])
run_git(["worktree", "add", str(worktree_dir), sha])
def get_changed_java_controller_files(base_sha: str, head_sha: str) -> List[str]:
"""
获取两次提交之间变更的 Controller 相关 Java 文件路径。
:param base_sha: 基准 commit旧版本
:param head_sha: 目标 commit新版本
:return: 相对路径列表,如 ["src/main/java/.../UserController.java"]
"""
diff_output = run_git(["diff", "--name-only", base_sha, head_sha])
if not diff_output:
return []
changed = []
for line in diff_output.splitlines():
line = line.strip()
if line.endswith(".java") and "Controller" in line:
changed.append(line.replace("\\", "/"))
return changed
def get_controller_files_diff(base_sha: str, head_sha: str, changed_files: List[str]) -> str:
"""
获取变更 Controller 文件的 Git diff供 LLM 审核接口参数变更时参考。
:param base_sha: 旧版本 commit SHA
:param head_sha: 新版本 commit SHA
:param changed_files: 变更文件相对路径列表
:return: diff 文本
"""
if not changed_files:
return ""
try:
return run_git(["diff", base_sha, head_sha, "--"] + changed_files)
except RuntimeError as exc:
print(f"[警告] 获取 Git diff 失败: {exc}")
return ""
def prepare_worktrees(repo_root: Path) -> tuple:
"""
准备新旧两个版本的代码工作目录,供 AST 解析器分别扫描。
:param repo_root: 仓库根目录
:return: (新版本目录, 旧版本目录, 旧版本SHA);首次提交时旧版本目录为 None
"""
prev_sha = get_previous_commit_sha()
current_dir = repo_root
if prev_sha is None:
return current_dir, None, None
prev_dir = repo_root / ".gitea" / ".cache" / "prev-worktree"
checkout_commit(prev_sha, prev_dir)
return current_dir, prev_dir, prev_sha