This commit is contained in:
Dang Zerong
2026-03-12 14:42:23 +08:00
parent 9ae55407fc
commit 027cf50759
8 changed files with 225 additions and 52 deletions

76
app.py
View File

@@ -206,41 +206,51 @@ def handle_pull_request(payload: Dict[str, Any]) -> Tuple[Dict, int]:
if web_url:
clone_url = web_url.rstrip('/') + '.git'
# 获取 PR 中变更的文件列表
changed_files = []
try:
if '/' in repo_name:
repo_owner, repo_name_only = repo_name.split('/', 1)
else:
repo_owner = 'Bosch_Demo'
repo_name_only = repo_name
pr_files = gitea_client.get_pull_request_files(repo_owner, repo_name_only, pr_number)
if pr_files:
changed_files = [f.get('filename', '') for f in pr_files if f.get('filename')]
logger.info(f"获取到 PR #{pr_number} 的变更文件: {changed_files}")
except Exception as e:
logger.warning(f"获取 PR 文件列表失败: {e}")
# 执行代码扫描
scan_results = {}
# Python 扫描
if 'python' in config.get('scanner', {}).get('languages', []):
scan_results['python'] = python_scanner.scan(
clone_url, source_sha, source_branch
clone_url, source_sha, source_branch, changed_files
)
# JavaScript/TypeScript 扫描
if any(lang in config.get('scanner', {}).get('languages', [])
for lang in ['javascript', 'typescript']):
scan_results['javascript'] = js_scanner.scan(
clone_url, source_sha, source_branch
clone_url, source_sha, source_branch, changed_files
)
# 安全扫描
scan_results['security'] = security_scanner.scan(
clone_url, source_sha, source_branch
clone_url, source_sha, source_branch, changed_files
)
# AI 代码审查
if config.get('ai', {}).get('enabled', False):
scan_results['ai'] = ai_reviewer.scan(
clone_url, source_sha, source_branch
clone_url, source_sha, source_branch, changed_files
)
# 获取 PR 的代码差异,用于将问题与代码片段关联
pr_diff = None
if '/' in repo_name:
repo_owner, repo_name_only = repo_name.split('/', 1)
else:
repo_owner = 'Bosch_Demo'
repo_name_only = repo_name
try:
pr_diff = gitea_client.get_pull_request_diff(repo_owner, repo_name_only, pr_number)
logger.info(f"已获取 PR #{pr_number} 的 diff长度: {len(pr_diff) if pr_diff else 0}")
@@ -249,6 +259,12 @@ def handle_pull_request(payload: Dict[str, Any]) -> Tuple[Dict, int]:
# 将问题与代码片段关联
scan_details_with_code = merge_issues_with_code(scan_results, pr_diff or '')
logger.info(f"[DEBUG] scan_results keys: {list(scan_results.keys())}")
for k, v in scan_results.items():
if isinstance(v, dict):
issues_cnt = len(v.get('issues', []))
logger.info(f"[DEBUG] scan_results['{k}'] issues count: {issues_cnt}")
logger.info(f"[DEBUG] scan_details_with_code scanners: {[s.get('name') for s in scan_details_with_code.get('scanners', [])] if scan_details_with_code else 'None'}")
# 生成报告
commit_message = f'PR #{pr_number}: {pr_title}'
@@ -580,12 +596,24 @@ def api_get_pr_file_content(pr_id):
# 获取该文件的扫描问题PR 创建时已扫描并存入 scan_details_with_code
scan_issues = []
path_norm = path.replace('\\', '/').strip()
logger.info(f"[DEBUG] 请求文件: path_norm={path_norm}")
scan_details = pr.get('scan_details_with_code')
if isinstance(scan_details, str):
try:
scan_details = json.loads(scan_details)
except Exception:
scan_details = None
if scan_details:
logger.info(f"[DEBUG] scan_details keys: {list(scan_details.keys()) if isinstance(scan_details, dict) else 'not dict'}")
if scan_details.get('scanners'):
logger.info(f"[DEBUG] scanners count: {len(scan_details['scanners'])}")
for scanner in scan_details['scanners']:
scanner_name = scanner.get('name', '')
issues_count = len(scanner.get('issues', []))
logger.info(f"[DEBUG] scanner={scanner_name}, issues_count={issues_count}")
# 打印前几个 issue 的 file 看看
for idx, issue in enumerate(scanner.get('issues', [])[:3]):
logger.info(f"[DEBUG] issue[{idx}] file={issue.get('file')}, line={issue.get('line')}")
if scan_details and scan_details.get('scanners'):
for scanner in scan_details['scanners']:
for issue in scanner.get('issues', []):
@@ -594,6 +622,7 @@ def api_get_pr_file_content(pr_id):
continue
# 匹配:精确相等或一端包含另一端(兼容 basename 或完整路径)
if path_norm == issue_file or path_norm.endswith(issue_file) or issue_file.endswith(path_norm):
logger.info(f"[DEBUG] 匹配成功: issue_file={issue_file}, path_norm={path_norm}")
sev = (issue.get('severity') or 'info')
if isinstance(sev, str):
sev = sev.lower()
@@ -606,8 +635,33 @@ def api_get_pr_file_content(pr_id):
'message': (issue.get('message') or issue.get('description') or '').strip(),
'code_context': issue.get('code_context')
})
logger.info(f"[DEBUG] 最终 scan_issues count: {len(scan_issues)}")
return jsonify({'path': path, 'content': content, 'scan_issues': scan_issues})
# 获取 AI 审查结果
ai_issues = []
if scan_details and scan_details.get('ai'):
ai_data = scan_details['ai']
for issue in ai_data.get('issues', []):
issue_file = (issue.get('file') or '').replace('\\', '/').strip()
if not issue_file:
continue
# 匹配:精确相等或一端包含另一端
if path_norm == issue_file or path_norm.endswith(issue_file) or issue_file.endswith(path_norm):
ai_issues.append({
'scanner': 'AI',
'severity': issue.get('severity', 'info'),
'line': int(issue.get('line') or 1),
'message': issue.get('message', ''),
'category': 'ai',
'code_context': issue.get('code_context')
})
logger.info(f"[DEBUG] AI issues count: {len(ai_issues)}")
# 合并静态扫描问题和 AI 问题
all_issues = scan_issues + ai_issues
return jsonify({'path': path, 'content': content, 'scan_issues': all_issues})
except Exception as e:
logger.error(f'获取文件内容失败: {str(e)}')
return jsonify({'error': str(e)}), 500