Files
AI-Check-Test/.gitea/checker/main.py
dongzi 556f5b8ab6
Some checks failed
API Parameter Change Check / api-param-check (push) Failing after 3s
test
2026-06-03 15:02:21 +08:00

183 lines
5.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
AI-Check 主入口 — Controller 层接口参数变更检测
流程(对齐第一版需求):
1. Git 检出新旧代码
2. JavaParser AST 解析 Controller 方法签名与参数
3. 对比增 / 删 / 改 / 重命名
4. 可选LLM 审核参数变更结果
5. (可选)写入日志
6. 企业微信通知URI + 参数变更明细)
用法:
python .gitea/checker/main.py [--config .gitea/config.yaml] [--repo-root .] [推送人] [推送时间]
"""
import argparse
import sys
import tempfile
from pathlib import Path
import yaml
CHECKER_DIR = Path(__file__).resolve().parent
sys.path.insert(0, str(CHECKER_DIR))
from change_logger import persist_change_log
from comparator import compare_endpoints
from controller_parser import (
endpoints_to_map,
filter_endpoints_by_files,
run_java_parser,
)
from git_utils import (
get_changed_java_controller_files,
get_controller_files_diff,
get_current_commit,
get_previous_commit_sha,
prepare_worktrees,
)
from llm_reviewer import review_parameter_changes
from notifier import send_parameter_change_notification
def load_config(config_path: Path) -> dict:
"""加载 YAML 配置文件。"""
if not config_path.exists():
print(f"[错误] 配置文件不存在: {config_path}")
print("请在 .gitea/config.yaml 中填写配置并提交到仓库。")
sys.exit(1)
with open(config_path, "r", encoding="utf-8") as f:
return yaml.safe_load(f) or {}
def parse_endpoints_for_version(
repo_root: Path,
source_subdir: str,
jar_path: Path,
tmp_dir: Path,
label: str,
) -> dict:
"""对指定版本源码运行 Java AST 解析,提取 Controller 接口参数。"""
source_dir = repo_root / source_subdir
output_json = tmp_dir / f"endpoints_{label}.json"
print(f"[AST] 扫描 {label} 版本: {source_dir}")
endpoints = run_java_parser(source_dir, jar_path, output_json)
print(f"[AST] {label} 版本共 {len(endpoints)} 个 Controller 接口")
return endpoints_to_map(endpoints)
def main() -> int:
"""主流程入口。"""
parser = argparse.ArgumentParser(
description="AI-Check: Controller 接口参数变更检测"
)
parser.add_argument("--config", default=".gitea/config.yaml", help="配置文件路径(相对仓库根目录)")
parser.add_argument("--repo-root", default=".", help="Git 仓库根目录")
parser.add_argument("push_user", nargs="?", default=None, help="推送人CI 传入)")
parser.add_argument("push_time", nargs="?", default=None, help="推送时间CI 传入)")
args = parser.parse_args()
repo_root = Path(args.repo_root).resolve()
config = load_config(repo_root / args.config)
source_subdir = config.get("source_dir", "src/main/java")
jar_path = repo_root / config.get(
"java_parser_jar", ".gitea/java-parser/target/controller-parser-1.0.0.jar"
)
commit_info = get_current_commit()
push_user = args.push_user or commit_info.author
push_time = args.push_time or commit_info.commit_time
print("Controller 接口参数变更检测")
print("=" * 40)
print(f"推送人: {push_user}")
print(f"推送时间: {push_time}")
print(f"LLM 审核: {config.get('llm', {}).get('enabled', True)}")
print(f"记录日志: {config.get('log', {}).get('enabled', False)}")
print("=" * 40)
prev_sha = get_previous_commit_sha()
if prev_sha is None:
print("[Git] 首次提交,无可对比版本,跳过。")
return 0
changed_files = get_changed_java_controller_files(prev_sha, commit_info.sha)
if not changed_files:
print("[Git] 本次提交未变更 Controller 文件,跳过。")
return 0
print(f"[Git] 变更 Controller 文件 {len(changed_files)} 个:")
for f in changed_files:
print(f" - {f}")
git_diff = get_controller_files_diff(prev_sha, commit_info.sha, changed_files)
current_dir, prev_dir, _ = prepare_worktrees(repo_root)
reports = []
llm_review = None
with tempfile.TemporaryDirectory(prefix="ai-check-") as tmp:
tmp_dir = Path(tmp)
# 1. AST 解析 + 参数对比
new_map = parse_endpoints_for_version(
current_dir, source_subdir, jar_path, tmp_dir, "new"
)
old_map = parse_endpoints_for_version(
prev_dir, source_subdir, jar_path, tmp_dir, "old"
)
new_filtered = endpoints_to_map(
filter_endpoints_by_files(list(new_map.values()), changed_files)
)
old_filtered = endpoints_to_map(
filter_endpoints_by_files(list(old_map.values()), changed_files)
)
reports = compare_endpoints(old_filtered, new_filtered)
print(f"[对比] 检测到 {len(reports)} 个接口存在参数变更")
# 2. LLM 审核接口参数变更(非代码审查)
if reports:
llm_review = review_parameter_changes(
reports, config, changed_files, git_diff
)
if llm_review:
print(f"[LLM] 参数变更审核完成")
# 3. 写日志(开关控制)
persist_change_log(reports, commit_info, config, llm_review)
# 4. 企微通知
notify_cfg = config.get("notify", {})
only_on_change = notify_cfg.get("only_on_change", True)
if only_on_change and not reports:
print("[通知] 无接口参数变更,跳过企微通知。")
return 0
mentioned = notify_cfg.get("mentioned_users", "")
mentioned_list = [u.strip() for u in mentioned.split(",") if u.strip()] or None
wecom_cfg = config.get("wecom", {})
send_parameter_change_notification(
webhook_url=wecom_cfg.get("webhook_url", ""),
reports=reports,
push_user=push_user,
push_time=push_time,
llm_review=llm_review,
mentioned_users=mentioned_list,
)
print("\n完成")
return 0
if __name__ == "__main__":
sys.exit(main())