代码审查自动化
本页提供集成 AI 审查的完整 GitHub Actions workflow YAML、结构化审查输出 JSON 格式、按文件路径差异化策略代码、reviewdog 集成配置、误报标记格式,以及 enforce/advisory 分层的降噪策略。
SKILL 应列出「必须自动化」项(如 secret 扫描、依赖漏洞、breaking API 检测)与「仅提示」项,并规定失败时是否阻塞合并、是否允许例外标签流程。
Agent 可协助生成或更新 workflow、CODEOWNERS 与审查模板,但须与「代码审查清单」等技能对齐:自动化覆盖已知模式与策略,清单覆盖上下文与产品取舍。
审查流水线(PR → CI → Bot → 人)
[ 打开 / 更新 PR ]
│
▼
┌─────────────┐ 门禁:lint / test / 类型 / 安全扫描
│ CI 工作流 │──── 产物:日志、覆盖率、SBOM(按需)
└─────────────┘
│
▼
┌─────────────┐ 汇总:同一检查一条评论线程;链接文档与本地命令
│ PR Bot │──── 失败可复现:配置文件路径、抑制语法、issue 模板
└─────────────┘
│
▼
┌─────────────┐ 语义:设计、边界情况、命名、演进策略、例外是否合理
│ 人类 / Agent │──── 不重复 Bot 已标出的格式化问题
└─────────────┘
合流顺序:先让 CI 与 Bot 把「可机器判定」的问题清零或显式豁免,再进入人类深度审查;避免人在评论区重复贴 linter 已说过的话。
强制(Enforce)与建议(Advisory)
新检查优先 report-only(或单独 workflow)收集基线,再切到 enforce;同一规则不要在「仅注释」与「阻塞合并」之间来回横跳,除非有数据支撑。
Enforce(阻塞或必修复)
- Secret / 凭据泄漏、已知高危依赖
- 破坏公共 API 契约的检测(团队约定范围内)
- 团队已投票通过的格式与类型门禁
- 合并前必须通过的分支保护规则对应检查
Advisory(提示、仪表盘)
- 复杂度、重复代码、可选风格规则
- 实验性规则、误报率仍高的静态规则
- 需要业务上下文才能判定的「代码异味」
- 仅用于趋势分析的覆盖率细分(不卡单次 PR)
集成 AI 审查的完整 GitHub Actions workflow(可直接粘贴并替换 secrets 名称):
name: AI Code Review
on:
pull_request:
types: [opened, synchronize, reopened]
paths-ignore:
- "**/*.md"
- "dist/**"
- "**/package-lock.json"
jobs:
ai-review:
runs-on: ubuntu-latest
if: >
!github.event.pull_request.draft &&
!contains(github.event.pull_request.title, '[skip-review]')
permissions:
pull-requests: write
contents: read
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Get changed files
id: changed
run: |
git diff --name-only origin/${{ github.base_ref }}...HEAD \
> changed_files.txt
cat changed_files.txt
- name: Run AI review
env:
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PR_NUMBER: ${{ github.event.pull_request.number }}
REPO: ${{ github.repository }}
run: |
# 调用审查脚本,输出 JSON 格式的审查意见
node .github/scripts/ai-review.js \
--changed-files changed_files.txt \
--output review-output.json
- name: Post review comments
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
node .github/scripts/post-comments.js \
--review review-output.json \
--pr ${{ github.event.pull_request.number }}
结构化审查输出的 JSON 格式(review-output.json):
{
"summary": "共发现 2 处 P0,3 处 P1,1 处 P2",
"comments": [
{
"file": "src/api/handlers.ts",
"line": 42,
"severity": "P0",
"message": "用户 ID 直接拼入 SQL,存在 SQL 注入风险",
"suggestion": "改用参数化查询:db.query('SELECT * FROM users WHERE id = $1', [userId])",
"rule": "security/no-sql-injection"
},
{
"file": "src/services/payment.ts",
"line": 87,
"severity": "P1",
"message": "catch 块吞掉了 StripeError,调用方无法区分错误类型",
"suggestion": "将 StripeError 映射为业务错误码后重新 throw",
"rule": "error-handling/no-swallow"
}
]
}
差异化策略:根据文件路径启用不同规则集:
// .github/scripts/ai-review.js 中的差异化策略
function getRulesForFile(filePath) {
if (filePath.endsWith('.env') || filePath.includes('config/secrets')) {
return ['security/no-plaintext-secrets', 'security/no-credentials'];
}
if (filePath.endsWith('.sql') || filePath.includes('migrations/')) {
return ['db/reversible-migration', 'db/no-drop-without-backup'];
}
if (filePath.endsWith('.tsx') || filePath.endsWith('.jsx')) {
return ['react/no-direct-mutation', 'a11y/interactive-aria-roles', 'security/no-dangerouslySetInnerHTML'];
}
return ['general/no-hardcoded-secrets', 'general/error-handling'];
}
与 reviewdog 集成的配置(.reviewdog.yml):
runner:
ai-review:
cmd: node .github/scripts/ai-review.js --format rdjson
format: rdjson
reporter: github-pr-review
level: warning
fail_on_error: true
filter_mode: added
误报标记格式(在源码注释中使用,由 AI 审查脚本识别后跳过该行):
// ai-review-ignore: 此处 hardcoded 是测试环境 mock,非生产 secret
const MOCK_API_KEY = "test-key-not-real";
// ai-review-ignore: legacy code,已在 JIRA-1234 中记录迁移计划
const result = db.query(`SELECT * FROM users WHERE id = ${userId}`);
PR Bot 评论礼仪
- 一条检查一线程:同一工具的多条告警尽量折叠或汇总,避免刷屏。
- 可行动:给出文档链接、可本地复现的一条命令、修复或抑制的官方写法(含文件路径)。
- 误报路径:说明如何开 issue / 加 allowlist,而不是让作者在评论区「求放过」。
- 尊重草稿:Draft PR 默认跑轻量检查或仅 advisory,合流前再跑全量 enforce(与 workflow 实验室中的条件一致)。
噪声与度量
用数据驱动降噪:跟踪「Bot 评论数 / PR」「被标记为误报或无效的评论比例」「同一规则重复触发次数」「从打开 PR 到全绿的中位时间」。
- 合并后回顾:若某规则长期被忽略或大量抑制,改为 advisory 或收紧范围。
- 对生成物目录、锁文件、大资源使用
paths-ignore或独立 job,避免无意义运行。 - 将「评论洪水」与「合并延迟」纳入团队复盘指标,与 enforce 列表一起审议。
人类审查 vs 自动化边界
自动化:语法与策略可穷举的规则、跨仓库一致的风格、安全与许可证基线、可重复构建与测试结果。
人类 / Agent:需求是否被正确实现、抽象是否合适、错误处理与可观测性是否匹配场景、是否引入隐性耦合或过度设计。
分工原则:Bot 说明「违反了哪条规则」;人判断「在业务约束下是否应改规则或豁免」。二者不重复唠叨同一类问题。
Workflow 片段实验室
勾选下方选项,生成可粘贴到 GitHub Actions 的示意片段:paths-ignore 列表与 jobs.<id>.if 条件(表达式需按你仓库的触发事件微调)。
将 paths-ignore 嵌到对应 on.push / on.pull_request 下;if: 贴在 jobs.<id> 与 runs-on 同级。Fork PR 无 head_commit 时需改用 github.event.pull_request 上的字段或拆成多个 job。
---
name: code-review-automation
description: CI 门禁、AI 审查 workflow、reviewdog 集成与误报处理
---
# 步骤 1:分类检查项(enforce vs advisory)
enforce(阻塞合并):
- secret/凭证扫描(gitleaks 或 trufflehog)
- 依赖 CVE ≥ HIGH(dependabot 或 trivy)
- 类型错误(tsc --noEmit)
- 覆盖率未达阈值(nyc / c8)
advisory(上报但不阻塞):
- 圈复杂度 > 20(eslint complexity rule)
- 重复代码(jscpd)
- AI 审查意见中 severity < P1
# 步骤 2:AI 审查 workflow
触发: pull_request [opened, synchronize]
跳过: Draft PR / 标题含 [skip-review]
权限: pull-requests:write + contents:read
输出: JSON with file/line/severity/message/suggestion
# 步骤 3:差异化规则
.env / secrets: 只跑 security 规则集
.sql / migrations: 跑 db/reversible-migration 规则集
.tsx / .jsx: 跑 react + a11y + security/xss 规则集
其他: 跑通用规则集
# 步骤 4:reviewdog 集成
format: rdjson
reporter: github-pr-review
filter_mode: added # 只报 diff 内的新问题
# 步骤 5:误报处理
// ai-review-ignore: # 行内注释跳过该行
审计频率: 每季度检查 ignore 列表,移除不再需要的豁免
# 步骤 6:噪声度量
跟踪指标:
- Bot评论数 / PR(目标: < 5 条 enforce 问题)
- 被标记为误报的比例(目标: < 10%)
- PR 从打开到全绿的中位时间