代码审查自动化

本页提供集成 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 的路径(示例 glob)
if: 条件(组合进同一 job)

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 从打开到全绿的中位时间

返回技能库 更多技能入口