每日新闻 / 2026-06-22

AI 代码审查 CI/CD 实战:用 Claude Code / Codex 构建自动 PR 注释机器人

XycAi
AI 代码审查 CI/CD 实战:用 Claude Code / Codex 构建自动 PR 注释机器人

为什么人工 Code Review 正在成为瓶颈

一个 10 人工程团队,每周合并 PR 数量通常在 40~80 条之间。按每条 PR 平均需要 20 分钟人工审查计算,光是 Review 就要消耗 800~1600 分钟的工程师注意力——这还不算等待时间造成的上下文切换损耗。

问题不在于工程师不认真,而在于 Code Review 本身有大量机械性工作:检查命名规范、发现潜在的空指针、确认错误处理是否完整。这类工作恰恰是当前 LLM 最擅长的。把它们交给 AI 代码审查 CI/CD 流程处理,人工 Review 就可以专注在架构决策、业务逻辑合理性这些真正需要上下文判断的地方。

下面的配置方案在 GitHub Actions 上均已验证,核心逻辑对 GitLab CI / Bitbucket Pipelines 同样适用。


两条技术路线:Claude Code vs Codex

在构建 AI 审查机器人时,首先要选定底层引擎。目前最常用的两条路线是 Anthropic 的 Claude Code(底层走 Claude Sonnet 4.6 / Opus 4.8)和 OpenAI 的 Codex(底层走 GPT-5.4 系列)。

维度 Claude Code Codex (GPT-5.4)
上下文窗口 200K tokens 128K tokens
代码理解深度 擅长多文件跨引用分析 擅长单文件内精确补全与重构
结构化输出 原生支持 JSON mode 支持 function calling
API 兼容性 标准 REST / OpenAI 兼容格式 OpenAI 标准
适合场景 大 PR、涉及多模块变更 小 PR、聚焦局部逻辑审查

两者并不互斥。一种成熟的做法是用文件变更行数做分流:diff 超过 300 行走 Claude Code(更大上下文),300 行以内走 Codex(响应更快、成本更低)。


核心架构:事件触发 → diff 提取 → LLM 审查 → PR 注释

整个流水线分四个环节:

1. 触发时机

pull_request 事件的 openedsynchronize 类型上触发。synchronize 对应 push 新 commit 到已有 PR,避免遗漏增量变更。

on:
  pull_request:
    types: [opened, synchronize]

2. 提取 diff

只审查本次 PR 变更的内容,不要把整个仓库塞给模型。用 git diff 对比 base 分支:

git fetch origin ${{ github.base_ref }}
git diff origin/${{ github.base_ref }}...HEAD \
  --unified=5 \
  -- '*.ts' '*.py' '*.go' '*.java' \
  > pr_diff.txt

--unified=5 保留 5 行上下文,足够 LLM 理解变更意图。通过 glob 过滤只审查源代码文件,排除 *.lock*.md、构建产物等噪声。

3. 调用 LLM

以 Claude Code 为例,使用 OpenAI 兼容格式(方便后续切换模型):

import os, json, httpx

diff = open("pr_diff.txt").read()[:60000]  # token 预算控制

payload = {
    "model": "claude-sonnet-4-6",
    "messages": [
        {
            "role": "system",
            "content": (
                "你是一个严格但友好的 Code Reviewer。"
                "只输出 JSON 数组,每个元素包含 file、line、severity(info/warning/error)、comment 四个字段。"
                "不要输出任何解释性文字,只输出 JSON。"
            )
        },
        {"role": "user", "content": f"请审查以下 diff:\n\n{diff}"}
    ],
    "temperature": 0.2,
    "response_format": {"type": "json_object"}
}

resp = httpx.post(
    os.environ["LLM_API_BASE"] + "/chat/completions",
    headers={"Authorization": f"Bearer {os.environ['LLM_API_KEY']}"},
    json=payload,
    timeout=60
)
comments = json.loads(resp.json()["choices"][0]["message"]["content"])

temperature=0.2 是关键:太高会让模型发散出不存在的问题,太低则容易漏掉隐蔽 bug。实测 0.2~0.3 区间在准确率和召回率上表现最平衡。

4. 写回 PR 注释

通过 GitHub REST API 创建 review comment,把每条 LLM 输出关联到具体文件和行号:

import requests

gh_headers = {
    "Authorization": f"Bearer {os.environ['GITHUB_TOKEN']}",
    "Accept": "application/vnd.github+json"
}
repo = os.environ["GITHUB_REPOSITORY"]
pr_number = os.environ["PR_NUMBER"]
commit_sha = os.environ["GITHUB_SHA"]

for item in comments:
    if item.get("severity") in ("warning", "error"):
        requests.post(
            f"https://api.github.com/repos/{repo}/pulls/{pr_number}/comments",
            headers=gh_headers,
            json={
                "body": f"**[{item['severity'].upper()}]** {item['comment']}",
                "commit_id": commit_sha,
                "path": item["file"],
                "line": item["line"]
            }
        )

只把 warningerror 级别的问题写成 inline comment,info 级别汇总成一条 PR summary,避免刷屏。


工程细节:避免踩坑

token 预算:单次审查控制在 60K input tokens 以内。超大 PR 建议按文件分批送审,每批独立调用,最后合并结果。

幂等性:每次 synchronize 触发都要先删除上一轮机器人留下的旧 comment,再写入新结果。否则一个 PR 来回修改 5 次,注释区会堆满历史噪声。删除逻辑:

gh api repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/comments \
  --jq '.[] | select(.user.login=="github-actions[bot]") | .id' \
  | xargs -I{} gh api -X DELETE repos/$GITHUB_REPOSITORY/pulls/comments/{}

误报率控制:在 system prompt 中明确要求"只报告确定性问题,对不确定的代码风格偏好保持沉默",可以将误报率从约 30% 降至 10% 以下。

secrets 管理LLM_API_KEY 存 GitHub Secrets,不要硬编码在 workflow 文件里,也不要在日志中 echo。Actions 会自动对 secrets 值做 masking,但主动 echo 仍可能绕过。

成本估算:一条 200 行 diff 的 PR,用 Claude Sonnet 4.6 审查约消耗 3K~5K tokens,按主流 API 定价折算不到 ¥0.05 一次。一个 10 人团队每月 PR 审查的 LLM 成本通常在 ¥20~¥50 之间,和节省的工程师时间相比几乎可以忽略。


把 AI 审查纳入 Review 文化而非替代它

AI 代码审查 CI/CD 集成真正的价值不是"替代人",而是把人工 Review 的起点拉高。机器人在 PR 创建后 90 秒内完成初轮扫描,工程师打开 PR 时已经有一份标注了潜在问题的"预审报告"——这改变的是 Review 的认知负荷,而不是 Review 本身。

一个值得建立的规范:AI 标记为 error 的问题,作者在请求 human review 前必须先处理或明确注释说明不处理的原因。这样既保留了工程师的最终判断权,又防止了"先合再说"的惰性。


我自己在接入上述方案时,在 API 层用的是 XycAi 词元平台(https://www.xyc.ai)——它兼容 OpenAI 格式,意味着上面的 Python 代码只需改一个 LLM_API_BASE 环境变量就能在 Claude Code、Codex、Gemini CLI 之间自由切换,不用动业务逻辑。Claude Sonnet 4.6 和 GPT-5.4 在这里的价格是官方的 1.4 折起,对 CI 这种高频调用场景成本差异相当明显。接入也支持 Claude Code / Codex CLI 一键配置,省去自己搭代理的麻烦。

一个 API 接入 200+ 全球 AI 模型

GPT · Claude · Gemini 官方模型低至 1.4 折起,持大模型算法备案号,CN2 直连低至 5ms,可开全球合规发票。

立即体验 XycAi →