AI 代码审查怎么接进 PR 流程:上手前先确认这几件事

编程狮(w3cschool.cn) 2026-10-21 07:06:54 浏览数 (22)
反馈

先给结论:把 AI 代码审查接进 PR,核心不是写提示词,而是三件工程活——拿到干净的 diff、把 diff 截断到模型能吃的长度、把结果以评论形式回写到正确的位置。提示词只决定审查质量的上限,这三件决定它能不能稳定跑起来。

AI 代码审查怎么接进 PR?

很多人第一次接的时候把精力全放在"让 AI 挑出更多问题"上,结果线上跑起来才发现:大 PR 直接超限失败、每次推送都刷一遍重复评论、误报太多没人看。这些都不是提示词能解决的。

本文给一份能直接放到仓库里跑的 workflow,逐个说明四个必须提前确认的点,以及五类常见偏差的处理办法。示例基于 GitHub Actions,思路换到其它 CI 上同样成立。

先看结论

  • 触发条件用 pull_request 事件,不要用在 push 上,否则每次推送都会重复审查。
  • 只把新增行的 diff 喂给模型,并且按字符数截断,超过就分段或跳过。
  • 结果以评论回写,绝不自动合并也不自动关闭——AI 的意见是输入,不是结论。

一、前置环境与适用范围

先把环境和边界说清楚,避免照抄之后跑不起来。

需要的东西只有三样:一个有 PR 权限的仓库、一个可用的模型 API 凭据(存进仓库的 Secrets)、以及 push 权限之外的 pull-requests: write,因为要回写评论。不同平台的令牌申请方式略有差异,Monkeycode Access Token For GIT Platform 教程 里有逐步说明。

适用范围要说清楚:这套方案适合"给人工审查提个醒",不适合当质量闸门。它会被绕过、会误报、也会漏掉架构层面的问题。把它定位成辅助,团队才不会对它产生错误预期。

判断标准很简单:如果你们的流程里 AI 的意见能直接决定合并,那这套方案不该上;如果它只是让人工审查少看几眼低级问题,那它很划算。

二、完成主流程:一个能跑的 workflow

name: ai-code-review
on:
  pull_request:
    types: [opened, synchronize]

permissions:
  contents: read
  pull-requests: write

jobs:
  review:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: 取出本次 PR 的 diff
        run: |
          git diff origin/${{ github.base_ref }}...HEAD > /tmp/pr.diff
          wc -c /tmp/pr.diff

      - name: 调用模型做审查
        env:
          API_KEY: ${{ secrets.MODEL_API_KEY }}
        run: |
          python3 scripts/ai_review.py /tmp/pr.diff > /tmp/review.md

      - name: 把结果写成 PR 评论
        env:
          GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          gh pr comment ${{ github.event.pull_request.number }} \
            --body-file /tmp/review.md

这份配置做的是:在 PR 打开与更新时触发,先完整拉取历史以便比较基线分支,然后用三点语法取出本次改动对应的 diff,再交给脚本调模型,最后把结果以评论形式回写。

用三点语法 origin/base...HEAD 而不是两点,是因为三点比较的是"从共同祖先到 HEAD"的改动,不会把主分支上别人的新提交算进来。这一点直接决定审查结果里有没有大量无关代码。

取 diff 的脚本是整套方案里唯一需要自己写的部分,核心逻辑只有三件事:

import sys, os, json, urllib.request

MAX_CHARS = 12000

def read_diff(path):
    text = open(path, encoding="utf-8", errors="replace").read()
    if len(text) > MAX_CHARS:
        text = text[:MAX_CHARS] + "\n...(diff 过长,已截断)"
    return text

def ask_model(diff):
    prompt = (
        "你是代码审查助手。只针对下面 diff 中新增的行给意见,"
        "按【必须改】【建议改】【可以讨论】三档输出,每条给出文件名与行号。"
        "不确定的地方标注不确定,禁止评论 diff 之外的代码。\n\n" + diff
    )
    body = json.dumps({"model": "gpt-4o-mini", "input": prompt}).encode()
    req = urllib.request.Request(
        os.environ["API_ENDPOINT"],
        data=body,
        headers={"Content-Type": "application/json",
                 "Authorization": "Bearer " + os.environ["API_KEY"]},
    )
    with urllib.request.urlopen(req, timeout=60) as resp:
        return json.load(resp)["output_text"]

if __name__ == "__main__":
    print(ask_model(read_diff(sys.argv[1])))

这段做的是:读 diff 并截断到一万两千字符以内,把"只审新增行、按三档输出、给出文件名与行号、禁止评论 diff 之外"写进提示词,再调用模型接口拿到结果。截断是必需的——大 PR 的 diff 动辄几十万字符,不截断会被接口直接拒绝。

提示词里"禁止评论 diff 之外的代码"这一句不能省。没有它,模型经常会对着上下文里没出现的文件编造意见,评审区里就会多出一堆无法定位的建议。

PR 触发到评论回写的完整链路

三、四个必须提前确认的点

3.1 费用

每个 PR 一次调用,按 diff 长度计费。日均二十个 PR、每个一万两千字符,一个月就是不小的开销。控制手段有三个:只在 opened 时审(去掉 synchronize)、设置 diff 上限、对 draft PR 跳过。workflow 的运行机制可以看 AI 编程 Claude Code Github Actions 教程。

3.2 数据去向

diff 会离开你的仓库去到模型厂商。涉密仓库要么改用私有部署的模型,要么直接不上。这一条和代码审查的质量无关,属于合规红线。

3.3 误报率

先在小范围跑两周,统计"被采纳的意见 / 总意见"这个比值。低于三成就说明提示词或截断策略有问题,继续放量只会消耗团队信任。

3.4 失败时怎么办

审查失败不应该阻塞合并。把这一步设成允许失败,或者只在脚本非零退出时留一条提示评论。质量判断交给人,CI 只负责提供信息。

四、常见偏差与验证清单

4.1 评论刷屏

触发条件里加了 synchronize 之后,每次 push 都会新增一条评论,一个大 PR 能刷几十条。修复办法是改成"更新已有评论":用 gh api 先查是否已有本机器人的评论,有就 PATCH,没有才 POST。

4.2 diff 里有大量无关改动

用了两点语法,或者基线分支取错。修复办法是确认三点语法与 github.base_ref 是否配套,并在本地用同样的命令手动跑一遍对比结果。

4.3 模型对着不存在的文件提意见

提示词没有约束范围。修复办法是补上"禁止评论 diff 之外的代码",并在输出格式里强制要求带文件名与行号,便于人工核对。

4.4 权限报错 403

workflow 缺 pull-requests: write。修复办法是在仓库设置里把 GITHUB_TOKEN 的权限改成读写,或在 workflow 顶层显式声明 permissions。

4.5 验证清单

  • 检查:仓库 Secrets 里已有模型凭据,workflow 声明了 pull-requests: write
  • 运行:开一个只改一行的测试 PR
  • 预期:CI 跑完,PR 下出现一条带文件名与行号的评论
  • 失败:403 → 补权限;超限报错 → 调小 MAX_CHARS
  • 修复:改完再开一个测试 PR,不要在原 PR 上反复试
  • 验证:连续推送两次,确认评论是被更新而不是新增

上面这些步骤做的是确认权限、跑通最小 PR、验证评论幂等。预期结果(未在本机执行)是两次推送只留一条评论;若变成两条,说明还没改成更新逻辑。

四个必须提前确认的点与验证命令

总结

AI 代码审查接进 PR 的关键是工程三件事:用三点语法取干净的 diff、按字符数截断、把结果幂等地回写成评论。触发用 pull_request 事件,失败不阻塞合并,AI 的意见只作输入。

四条要点带走:

  • 三点语法决定 diff 干不干净,别用两点;
  • 截断是必需的,大 PR 不截断一定超限失败;
  • 提示词要显式约束"只审新增行、禁止评论 diff 之外";
  • 评论要更新而不是新增,否则大 PR 会刷屏。

下一步建议先统计两周的意见采纳率,再决定要不要扩大触发范围。流程细节记不清时,翻 Git 教程 最快。

常见问题

Q:能不能让 AI 审查直接决定要不要合并?

A:不建议。它会误报也会漏报,架构层面的问题基本看不出来。定位成给人工审查提个醒更合适。

Q:为什么每次 push 都多一条评论?

A:触发条件里有 synchronize,每次推送都会跑一遍并新增评论。改成先查后更新,让评论保持幂等。

Q:大 PR 总是超限失败怎么办?

A:调小截断上限,或者在超限时跳过并在评论里说明"改动过大已跳过"。分段送审容易出现前后矛盾的意见。

Q:模型对着 diff 里没有的文件提意见,怎么处理?

A:提示词里补上"禁止评论 diff 之外的代码",并要求每条都带文件名与行号,方便人工核对与过滤。

Q:CI 报 403 是什么原因?

A:GITHUB_TOKEN 没有写 PR 评论的权限。在 workflow 顶层显式写 permissions: pull-requests: write,或在仓库设置里放开。

延伸学习

想把这条自动化链路补完整,可以按这个顺序来:

  1. 想系统学一遍 AI 编程工具的落地方式,可以跟一遍 AI 编程技能教程;
  2. 读一篇相关笔记 Git 合并分支,把 PR 与合并的关系看清;
  3. 再读一篇 Git 修改提交信息的方式,补上提交环节的常见操作。

0 人点赞