forked from Gitlink/gitlink-cli
398 lines
11 KiB
Markdown
398 lines
11 KiB
Markdown
# Workflow: PR Review(代码审查辅助)
|
||
|
||
> **前置条件:** 先阅读 [`../../gitlink-shared/SKILL.md`](../../../gitlink-shared/SKILL.md) 了解认证、全局参数和安全规则。
|
||
> **AI Agent 工作流**:此工作流专为 AI Agent 设计,用于辅助代码审查。
|
||
|
||
AI Agent 获取 PR 变更内容,分析代码质量,自动添加 Review 评论,提高代码审查效率。
|
||
|
||
## 工作流概述
|
||
|
||
PR Review 工作流通过分析 Pull Request 的代码变更,自动识别潜在问题、提出改进建议,并生成结构化的审查意见。
|
||
|
||
## 适用场景
|
||
|
||
- **代码审查**:自动化 PR 初步审查
|
||
- **质量检查**:检查代码质量和规范合规性
|
||
- **安全审查**:识别潜在的安全问题
|
||
- **性能分析**:评估性能相关代码变更
|
||
- **文档检查**:验证代码注释和文档完整性
|
||
|
||
## 工作流步骤
|
||
|
||
### 步骤 1:获取 PR 详情
|
||
|
||
```bash
|
||
# 获取 PR 基本信息
|
||
gitlink-cli pr +view --id 42 --format json
|
||
|
||
# 提取关键信息
|
||
PR_INFO=$(gitlink-cli pr +view --id 42 --format json | jq '.data')
|
||
PR_TITLE=$(echo "$PR_INFO" | jq -r '.title')
|
||
PR_AUTHOR=$(echo "$PR_INFO" | jq -r '.author.login')
|
||
SOURCE_BRANCH=$(echo "$PR_INFO" | jq -r '.head_ref')
|
||
TARGET_BRANCH=$(echo "$PR_INFO" | jq -r '.base_ref')
|
||
```
|
||
|
||
### 步骤 2:获取变更文件列表
|
||
|
||
```bash
|
||
# 获取 PR 变更的文件列表
|
||
gitlink-cli pr +files --id 42 --format json
|
||
|
||
# 分析文件变更
|
||
FILES_CHANGED=$(gitlink-cli pr +files --id 42 --format json | \
|
||
jq '.data.files[] |
|
||
{filename: .filename,
|
||
status: .status,
|
||
additions: .additions,
|
||
deletions: .deletions}')
|
||
```
|
||
|
||
### 步骤 3:获取代码差异
|
||
|
||
```bash
|
||
# 获取 PR 的完整代码差异
|
||
gitlink-cli pr +diff --id 42 --format json
|
||
|
||
# 提取特定文件的差异
|
||
gitlink-cli pr +diff --id 42 --format json | \
|
||
jq '.data.diff | split("diff --git")'
|
||
```
|
||
|
||
### 步骤 4:代码质量分析
|
||
|
||
分析代码变更的多个维度:
|
||
|
||
**安全性分析**:
|
||
```bash
|
||
# 检查敏感信息泄露
|
||
if echo "$DIFF" | grep -iE "password|secret|api_key|token"; then
|
||
SECURITY_ISSUES+=("可能包含敏感信息")
|
||
fi
|
||
|
||
# 检查 SQL 注入风险
|
||
if echo "$DIFF" | grep -iE "SELECT.*FROM.*WHERE.*\$"; then
|
||
SECURITY_ISSUES+=("可能的 SQL 注入风险")
|
||
fi
|
||
```
|
||
|
||
**代码规范检查**:
|
||
```bash
|
||
# 检查代码风格
|
||
if echo "$DIFF" | grep -P "\t"; then
|
||
STYLE_ISSUES+=("包含 Tab 字符,建议使用空格")
|
||
fi
|
||
|
||
# 检查长行
|
||
if echo "$DIFF" | grep ".\{120,\}"; then
|
||
STYLE_ISSUES+=("包含超过 120 字符的长行")
|
||
fi
|
||
```
|
||
|
||
**性能分析**:
|
||
```bash
|
||
# 检查可能的性能问题
|
||
if echo "$DIFF" | grep -iE "N\+1|SELECT.*\*|foreach.*query"; then
|
||
PERF_ISSUES+=("可能的 N+1 查询问题")
|
||
fi
|
||
```
|
||
|
||
### 步骤 5:生成 Review 评论
|
||
|
||
```bash
|
||
# 生成结构化的 Review 评论
|
||
REVIEW_BODY="# 🔍 代码审查结果
|
||
|
||
## ✅ 优点
|
||
- 代码结构清晰
|
||
- 逻辑正确
|
||
- 遵循项目规范
|
||
|
||
## ⚠️ 需要改进
|
||
${STYLE_ISSUES[@]+($(printf -- "- %s\n" "${STYLE_ISSUES[@]}"))}
|
||
|
||
## 🔒 安全问题
|
||
${SECURITY_ISSUES[@]+($(printf -- "- %s\n" "${SECURITY_ISSUES[@]}"))}
|
||
|
||
## 🚀 性能建议
|
||
${PERF_ISSUES[@]+($(printf -- "- %s\n" "${PERF_ISSUES[@]}"))}
|
||
|
||
## 📝 总体评价
|
||
代码整体质量良好,建议修改上述问题后合并。"
|
||
|
||
# 添加 Review 评论
|
||
gitlink-cli api POST /:owner/:repo/pulls/42/reviews --body \
|
||
"{\"body\":\"$REVIEW_BODY\",\"event\":\"COMMENT\"}"
|
||
```
|
||
|
||
## 完整工作流示例
|
||
|
||
```bash
|
||
#!/bin/bash
|
||
|
||
# PR Review 自动化脚本
|
||
|
||
PR_ID=$1
|
||
OWNER="myuser"
|
||
REPO="myproject"
|
||
|
||
echo "开始审查 PR #$PR_ID..."
|
||
|
||
# 1. 获取 PR 详情
|
||
PR_INFO=$(gitlink-cli pr +view --owner $OWNER --repo $REPO --id $PR_ID --format json)
|
||
PR_TITLE=$(echo "$PR_INFO" | jq -r '.data.title')
|
||
PR_AUTHOR=$(echo "$PR_INFO" | jq -r '.data.author.login')
|
||
ADDITIONS=$(echo "$PR_INFO" | jq -r '.data.additions')
|
||
DELETIONS=$(echo "$PR_INFO" | jq -r '.data.deletions')
|
||
|
||
echo "PR 标题: $PR_TITLE"
|
||
echo "PR 作者: $PR_AUTHOR"
|
||
echo "代码变更: +$ADDITIONS -$DELETIONS"
|
||
|
||
# 2. 获取变更文件
|
||
FILES=$(gitlink-cli pr +files --owner $OWNER --repo $REPO --id $PR_ID --format json)
|
||
|
||
# 3. 获取代码差异
|
||
DIFF=$(gitlink-cli pr +diff --owner $OWNER --repo $REPO --id $PR_ID --format json | \
|
||
jq -r '.data.diff')
|
||
|
||
# 4. 分析代码
|
||
ISSUES=()
|
||
SUGGESTIONS=()
|
||
|
||
# 安全性检查
|
||
if echo "$DIFF" | grep -iE "password|secret|api_key|token.*="; then
|
||
ISSUES+=("🔒 安全:可能包含硬编码的敏感信息")
|
||
fi
|
||
|
||
# 代码规范检查
|
||
if echo "$DIFF" | grep -P "\t"; then
|
||
SUGGESTIONS+=("📝 规范:建议使用空格代替 Tab")
|
||
fi
|
||
|
||
# 性能检查
|
||
if echo "$DIFF" | grep -iE "SELECT.*\*.*FROM"; then
|
||
SUGGESTIONS+=("🚀 性能:建议明确指定字段而不是使用 *")
|
||
fi
|
||
|
||
# 5. 生成 Review 评论
|
||
if [ ${#ISSUES[@]} -eq 0 ] && [ ${#SUGGESTIONS[@]} -eq 0 ]; then
|
||
REVIEW_BODY="# ✅ 审查通过
|
||
|
||
代码质量良好,没有发现明显问题。可以合并。"
|
||
EVENT="APPROVE"
|
||
else
|
||
REVIEW_BODY="# 🔍 代码审查结果
|
||
|
||
## PR 信息
|
||
- **标题**: $PR_TITLE
|
||
- **作者**: $PR_AUTHOR
|
||
- **变更**: +$ADDITIONS -$DELETIONS 行
|
||
|
||
## ❌ 需要修复
|
||
$(printf -- "- %s\n" "${ISSUES[@]}")
|
||
|
||
## 💡 改进建议
|
||
$(printf -- "- %s\n" "${SUGGESTIONS[@]}")
|
||
|
||
## 📋 后续步骤
|
||
1. 修复上述问题
|
||
2. 确保所有测试通过
|
||
3. 更新相关文档"
|
||
EVENT="REQUEST_CHANGES"
|
||
fi
|
||
|
||
# 6. 提交 Review
|
||
echo "提交 Review 评论..."
|
||
gitlink-cli api POST "/$OWNER/$REPO/pulls/$PR_ID/reviews" --body \
|
||
"{\"body\":\"$REVIEW_BODY\",\"event\":\"$EVENT\"}"
|
||
|
||
echo "审查完成!"
|
||
```
|
||
|
||
## AI Agent 集成示例
|
||
|
||
Claude Code 等 AI Agent 可以深度集成此工作流:
|
||
|
||
```python
|
||
# AI Agent 执行 PR Review
|
||
def pr_review(owner, repo, pr_id):
|
||
"""AI Agent 自动代码审查"""
|
||
|
||
# 1. 获取 PR 信息
|
||
pr_info = get_pr_details(owner, repo, pr_id)
|
||
files_changed = get_pr_files(owner, repo, pr_id)
|
||
diff_content = get_pr_diff(owner, repo, pr_id)
|
||
|
||
# 2. AI 分析代码
|
||
review_results = {
|
||
'security': analyze_security(diff_content),
|
||
'performance': analyze_performance(diff_content),
|
||
'style': analyze_code_style(diff_content),
|
||
'documentation': analyze_documentation(files_changed),
|
||
'testing': analyze_test_coverage(files_changed)
|
||
}
|
||
|
||
# 3. 生成审查意见
|
||
review_comment = generate_review_comment(pr_info, review_results)
|
||
|
||
# 4. 提交 Review
|
||
submit_review(owner, repo, pr_id, review_comment, review_results)
|
||
|
||
def analyze_security(diff_content):
|
||
"""AI 安全性分析"""
|
||
issues = []
|
||
|
||
# 检查常见安全问题
|
||
security_patterns = {
|
||
'hardcoded_secrets': r'password\s*=\s*["\'].*["\']',
|
||
'sql_injection': r'SELECT.*FROM.*WHERE.*\${',
|
||
'xss_risk': r'innerHTML\s*=',
|
||
'command_injection': r'system\(|exec\(.*\$'
|
||
}
|
||
|
||
for issue_name, pattern in security_patterns.items():
|
||
if re.search(pattern, diff_content, re.IGNORECASE):
|
||
issues.append({
|
||
'type': 'security',
|
||
'severity': 'high',
|
||
'issue': issue_name,
|
||
'description': f'检测到 {issue_name} 风险'
|
||
})
|
||
|
||
return issues
|
||
|
||
def generate_review_comment(pr_info, review_results):
|
||
"""AI 生成结构化审查意见"""
|
||
comment = f"""# 🔍 AI 代码审查报告
|
||
|
||
## PR 概览
|
||
- **标题**: {pr_info['title']}
|
||
- **作者**: {pr_info['author']}
|
||
- **变更**: +{pr_info['additions']} -{pr_info['deletions']} 行
|
||
- **文件数**: {len(pr_info['files'])}
|
||
|
||
## 🔒 安全审查
|
||
"""
|
||
|
||
if review_results['security']:
|
||
for issue in review_results['security']:
|
||
comment += f"- ❌ **{issue['issue']}**: {issue['description']}\n"
|
||
else:
|
||
comment += "✅ 未发现安全问题\n"
|
||
|
||
comment += "\n## 🚀 性能审查\n"
|
||
# 类似地添加其他审查结果...
|
||
|
||
return comment
|
||
```
|
||
|
||
## 审查维度
|
||
|
||
### 1. 安全性审查
|
||
- **敏感信息泄露**:检查硬编码的密码、API 密钥
|
||
- **注入攻击**:SQL 注入、命令注入、XSS 风险
|
||
- **权限控制**:检查权限验证逻辑
|
||
- **数据验证**:输入验证和输出编码
|
||
|
||
### 2. 性能审查
|
||
- **数据库查询**:N+1 查询、缺少索引
|
||
- **内存使用**:内存泄漏、大对象处理
|
||
- **算法复杂度**:时间复杂度和空间复杂度
|
||
- **缓存策略**:缓存命中率和使用合理性
|
||
|
||
### 3. 代码质量审查
|
||
- **代码规范**:命名规范、格式风格
|
||
- **代码结构**:模块化、可读性、可维护性
|
||
- **错误处理**:异常处理完整性
|
||
- **注释文档**:代码注释和文档质量
|
||
|
||
### 4. 测试审查
|
||
- **测试覆盖**:单元测试和集成测试
|
||
- **测试质量**:测试用例的有效性
|
||
- **边界条件**:边界值和异常情况测试
|
||
|
||
### 5. 文档审查
|
||
- **API 文档**:接口文档完整性
|
||
- **用户文档**:用户指南更新
|
||
- **变更日志**:CHANGELOG 更新
|
||
|
||
## 审查决策
|
||
|
||
基于分析结果做出审查决策:
|
||
|
||
**APPROVE(通过)**:
|
||
- 无严重问题
|
||
- 建议性问题可接受
|
||
- 测试覆盖充分
|
||
|
||
**REQUEST_CHANGES(请求修改)**:
|
||
- 存在严重安全问题
|
||
- 重要功能缺失
|
||
- 测试覆盖不足
|
||
|
||
**COMMENT(评论)**:
|
||
- 一般性建议
|
||
- 文档改进
|
||
- 代码优化建议
|
||
|
||
## 自动化规则
|
||
|
||
常见问题的自动检测规则:
|
||
|
||
```python
|
||
AUTO_REVIEW_RULES = {
|
||
'security': {
|
||
'hardcoded_password': {
|
||
'pattern': r'password\s*=\s*["\'][^"\']{8,}["\']',
|
||
'severity': 'high',
|
||
'message': '检测到硬编码密码,请使用环境变量或配置文件'
|
||
},
|
||
'sql_injection': {
|
||
'pattern': r'SELECT.*FROM.*WHERE.*\$[a-z_]+',
|
||
'severity': 'high',
|
||
'message': '可能的 SQL 注入风险,请使用参数化查询'
|
||
}
|
||
},
|
||
'performance': {
|
||
'n_plus_one': {
|
||
'pattern': r'for\s+\$.*\{\s*.*SELECT',
|
||
'severity': 'medium',
|
||
'message': '可能的 N+1 查询问题,考虑使用预加载'
|
||
},
|
||
'missing_index': {
|
||
'pattern': r'WHERE.*LIKE.*%.*%',
|
||
'severity': 'low',
|
||
'message': '前缀模糊搜索可能无法使用索引'
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
## 最佳实践
|
||
|
||
1. **逐步审查**:先检查严重问题,再检查一般问题
|
||
2. **建设性反馈**:提供具体的改进建议
|
||
3. **平衡严格**:平衡代码质量和开发效率
|
||
4. **学习改进**:从审查中学习,提高代码质量
|
||
5. **团队协作**:与开发者沟通,达成共识
|
||
|
||
## 质量保证
|
||
|
||
确保审查质量:
|
||
|
||
1. **双重检查**:重要 PR 进行二次审查
|
||
2. **审查标准**:建立统一的审查标准
|
||
3. **审查培训**:培训审查人员
|
||
4. **反馈收集**:收集对审查质量的反馈
|
||
5. **持续改进**:优化审查流程和规则
|
||
|
||
## References
|
||
|
||
- [workflow-issue-triage](workflow-issue-triage.md) — Issue 分类工作流
|
||
- [workflow-release-notes](workflow-release-notes.md) — Release Notes 生成
|
||
- [gitlink-workflow](../SKILL.md) — 工作流总览
|
||
- [gitlink-shared](../../gitlink-shared/SKILL.md) — 认证和全局参数
|
||
- [pr +view](../../gitlink-pr/references/gitlink-pr-view.md) — 查看 PR
|
||
- [pr +files](../../gitlink-pr/references/gitlink-pr-files.md) — 查看 PR 文件变更
|