在GitHub Actions中使用Claude和Gemini进行AI代码审查

3 分钟阅读·Matthieu·ci-cdgeminiclaudeai-code-reviewgithub-actions|

配置Claude Code Action和Gemini实现自动化Pull Request审查。多模型工作流与角色分离、在发现严重问题时阻止合并的质量门禁,以及针对提示注入的安全加固。

AI代码审查已经从实验阶段进入了生产工具阶段。Claude Code Action和Gemini Code Assist可以自动审查每个Pull Request,捕获linter和静态分析完全遗漏的逻辑错误、安全漏洞和缺失的错误处理。

本教程在同一个仓库中配置两个模型。Claude负责逻辑和安全审查。Gemini负责代码风格和文档审查。质量门禁(quality gate)解析两个审查的严重级别,在发现严重问题时阻止合并。

VPS上的AIOps:使用开源工具实现AI驱动的服务器管理

AI代码审查能发现哪些linter发现不了的问题?

Linter检查语法和格式。Semgrep等静态分析工具匹配已知模式。AI代码审查做的事情不同:它们在上下文中阅读diff,推理代码的实际行为。它们能标记竞态条件、缺失的错误处理路径、不安全的默认配置,以及基于模式匹配的工具无法检测的业务逻辑错误。

Milvus的一项研究在生产PR中测试了五个AI模型的真实bug检测能力。最优秀的单个模型检测到53%的bug。当多个模型审查同一个PR并在多轮中讨论发现时,检测率跃升至80%。最难的bug——那些需要系统级理解调用链和错误传播的bug——在多模型辩论模式下达到了100%的检测率。

这项研究正是本教程使用两个模型而非一个的原因。

AI审查能捕获的具体示例:

  • 未验证的用户输入经过三个函数调用后到达数据库查询
  • 缺失的空值检查——函数返回Optional<T>但调用方假设它总是成功
  • 硬编码的密钥在配置文件中看起来像占位值但实际上是真实凭据
  • 错误处理缺口——try/catch捕获通用异常并静默吞掉
  • 竞态条件——并发代码中共享状态在没有同步的情况下被修改

如何配置Claude Code Action进行Pull Request审查?

Claude Code Action是Anthropic维护的GitHub Action,在你的GitHub runner上运行Claude。它读取PR diff、发布行内评论,还可以实现修复。配置大约需要五分钟。

安装Claude GitHub App

前往github.com/apps/claude,将其安装到你的仓库或组织。授权它访问你想要审查的仓库。该应用需要以下权限:

  • Contents: Read
  • Pull Requests: Read & Write
  • Issues: Read & Write(可选,用于issue分类)

添加API密钥

在你的仓库中,前往Settings > Secrets and variables > Actions,创建一个新的仓库密钥:

  • Name: ANTHROPIC_API_KEY
  • Value: 你的Anthropic API密钥(以sk-ant-开头)

永远不要将API密钥提交到仓库。如果需要组织级别的访问,使用环境密钥而不是仓库密钥。

创建工作流

创建.github/workflows/claude-review.yml

name: Claude Code Review

on:
  pull_request:
    types: [opened, synchronize]
    paths:
      - "src/**"
      - "lib/**"
      - "app/**"
      - "config/**"
    paths-ignore:
      - "**/*.md"
      - "**/*.txt"
      - "docs/**"

concurrency:
  group: claude-review-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  review:
    runs-on: ubuntu-latest
    timeout-minutes: 15
    permissions:
      contents: read
      pull-requests: write
      id-token: write

    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1

      - uses: anthropics/claude-code-action@v1
        with:
          anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }}
          prompt: |
            REPO: ${{ github.repository }}
            PR NUMBER: ${{ github.event.pull_request.number }}

            Review this pull request. Focus on:
            1. Security: injection flaws, auth bypass, hardcoded secrets, insecure defaults
            2. Logic errors: off-by-one, null dereference, race conditions, resource leaks
            3. Error handling: swallowed exceptions, missing retries, unclear error messages
            4. Performance: N+1 queries, unbounded loops, unnecessary allocations

            Skip cosmetic issues (formatting, naming style). Another reviewer handles those.

            Rate each finding as CRITICAL, HIGH, MEDIUM, or LOW.

            Use inline comments for specific code issues.
            Use a summary PR comment for overall assessment.

          claude_args: |
            --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"

paths过滤器将审查限制在源代码更改上。仅修改文档的PR会跳过此工作流,节省API费用。concurrency块在新commit推送到同一PR时取消进行中的审查,避免为审查过时代码付费。

--allowedTools限制是一项安全措施。它将Claude限制为只能读取diff和发布评论。它不能修改文件、执行任意命令或访问其他仓库。

如何在同一仓库中添加Gemini代码审查?

Gemini审查有两个选择:Gemini Code Assist GitHub App(由Google管理,零YAML)或run-gemini-cli GitHub Action(自管理,完全控制)。本教程使用GitHub Action,因为它能控制prompt并与质量门禁工作流集成。

获取Gemini API密钥

在Google AI Studio创建密钥。将其添加为仓库密钥:

  • Name: GEMINI_API_KEY
  • Value: 你的Gemini API密钥

如需使用Vertex AI认证的企业用途,请参阅run-gemini-cli文档了解Workload Identity Federation配置。

创建Gemini工作流

创建.github/workflows/gemini-review.yml

name: Gemini Code Review

on:
  pull_request:
    types: [opened, synchronize]
    paths:
      - "src/**"
      - "lib/**"
      - "app/**"
      - "config/**"
    paths-ignore:
      - "**/*.md"
      - "**/*.txt"
      - "docs/**"

concurrency:
  group: gemini-review-${{ github.event.pull_request.number }}
  cancel-in-progress: true

jobs:
  review:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    permissions:
      contents: read
      pull-requests: write

    steps:
      - uses: actions/checkout@v6
        with:
          fetch-depth: 1

      - uses: google-github-actions/run-gemini-cli@main
        with:
          gemini_api_key: ${{ secrets.GEMINI_API_KEY }}
          prompt: |
            Review this pull request. Focus on:
            1. Code style: naming conventions, function length, complexity
            2. Documentation: missing docstrings, outdated comments, unclear variable names
            3. Test coverage: untested edge cases, missing assertions, test quality
            4. Maintainability: code duplication, tight coupling, violation of SOLID principles

            Skip security and logic analysis. Another reviewer handles those.

            Rate each finding as CRITICAL, HIGH, MEDIUM, or LOW.

            Post your review as a single PR comment with structured sections.

run-gemini-cli action目前处于beta阶段,所以工作流指向@main。在生产环境中,请固定到特定的commit SHA(例如@abc1234),以避免main分支更新时出现意外变更。

为什么使用两个独立的工作流?

将Claude和Gemini放在不同的工作流文件中意味着它们并行执行。一个失败不会阻塞另一个。你也可以临时禁用一个模型而不影响另一个工作流。

角色分离是有意为之的。Claude倾向于从上到下追踪调用链,擅长发现错误处理缺口和安全漏洞。Gemini在代码风格、文档完整性和结构模式方面表现出色。重叠是正常的。模型之间的一致性会增加对发现结果的信心。

Claude和Gemini的多模型审查如何运作?

上述双工作流配置已经实现了多模型审查。两个模型独立审查同一个PR并发布各自的评论。这是最简单的模式,适用于大多数团队。

如果团队需要统一视图,可以添加一个聚合步骤。第三个工作流在两个审查完成后运行,发布合并摘要:

name: AI Review Summary

on:
  workflow_run:
    workflows: ["Claude Code Review", "Gemini Code Review"]
    types: [completed]

jobs:
  aggregate:
    if: github.event.workflow_run.event == 'pull_request'
    runs-on: ubuntu-latest
    timeout-minutes: 5
    permissions:
      pull-requests: write
      actions: read

    steps:
      - name: Collect review comments
        id: collect
        uses: actions/github-script@v7
        with:
          script: |
            const pr_number = context.payload.workflow_run.pull_requests[0]?.number;
            if (!pr_number) return;

            const comments = await github.rest.issues.listComments({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: pr_number,
            });

            const aiComments = comments.data.filter(c =>
              c.body.includes('CRITICAL') ||
              c.body.includes('HIGH') ||
              c.body.includes('MEDIUM')
            );

            const critical = aiComments.filter(c => c.body.includes('CRITICAL')).length;
            const high = aiComments.filter(c => c.body.includes('HIGH')).length;

            const summary = `## AI Review Summary\n\n` +
              `| Severity | Count |\n|----------|-------|\n` +
              `| CRITICAL | ${critical} |\n` +
              `| HIGH | ${high} |\n\n` +
              (critical > 0 ? '⛔ **Merge blocked:** Critical findings require human review.\n' :
               high > 0 ? '⚠️ High-severity findings detected. Review recommended before merge.\n' :
               '✅ No critical or high-severity findings.\n');

            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: pr_number,
              body: summary,
            });

            core.setOutput('critical_count', critical);

      - name: Set status check
        if: steps.collect.outputs.critical_count > 0
        run: exit 1

这是一个起点。根据你的prompt产生的具体格式调整评论解析逻辑。审查prompt中的严重级别关键词(CRITICAL、HIGH、MEDIUM)使解析变得简单直接。

如何在AI审查发现严重问题时阻止合并?

上述聚合工作流在存在严重发现时设置退出码为1。要将其变为合并阻止器,配置分支保护:

  1. 前往Settings > Branches > Branch protection rules
  2. 选择或创建主分支的规则
  3. 启用Require status checks to pass before merging
  4. 搜索并添加"AI Review Summary"作为必需的状态检查
严重级别 操作 是否阻止合并?
CRITICAL 状态检查失败
HIGH 摘要中的警告 否(建议性)
MEDIUM 列在摘要中
LOW 从摘要中省略

**注意事项:**AI审查器会产生误报(false positives)。如果你将状态检查设为必需,开发者偶尔需要驳回错误的发现。保持CRITICAL作为唯一的阻止级别。如果同时阻止HIGH级别,预期会产生摩擦。

要覆盖被阻止的合并,维护者可以使用分支保护规则的管理员绕过,或者添加一个/dismiss-ai-review评论处理器,用强制通过标志重新运行摘要工作流。

如何减少AI代码审查中的误报?

误报是使用AI代码审查的团队最主要的抱怨。嘈杂的审查会快速侵蚀信任。三种技术可以帮助解决。

精确限定prompt范围

上述prompt已经做到了这一点:Claude审查安全和逻辑,Gemini审查风格和文档。要求模型"审查一切"会比给予特定职责产生更多噪声。

添加项目特定的上下文以进一步减少误报。在仓库根目录创建CLAUDE.md文件(Claude Code Action会自动读取):

# Project Context

This is a Django REST API. Python 3.12. PostgreSQL.

## Review Guidelines
- We use `rest_framework.exceptions` for all error handling. Do not flag bare `except` blocks in middleware.
- `settings.py` contains environment variable references, not hardcoded secrets. Do not flag `os.environ.get()` calls.
- We intentionally use `Any` type hints in the serializer layer. Do not flag these.
- Test files use `pytest` fixtures. Do not flag unused function parameters in test files.

对于Gemini,在仓库根目录创建等效项目上下文的GEMINI.md文件。

过滤文件

工作流YAML中的pathspaths-ignore过滤器防止审查会产生噪声的文件:

paths-ignore:
  - "**/*.md"
  - "**/*.txt"
  - "**/*.lock"
  - "**/*.generated.*"
  - "migrations/**"
  - "vendor/**"
  - "dist/**"
  - "__snapshots__/**"

Lock文件、生成的代码、vendor依赖和迁移文件会产生误报,因为它们是机器生成的或遵循模型在上下文中无法理解的模式。

设置严重级别阈值

如果你只在摘要中显示CRITICAL和HIGH发现,MEDIUM和LOW的噪声永远不会到达开发者。这比显示所有内容然后要求开发者忽略噪声是更好的默认设置。

AI代码审查在Pull Request上有哪些安全风险?

AI代码审查器处理不受信任的输入。PR diff、commit消息、issue标题和文件内容在开源仓库或接受外部贡献时都由攻击者控制。这创造了提示注入(prompt injection)风险。

Clinejection攻击

2026年2月,攻击者通过间接提示注入利用了Cline issue分类机器人。攻击很简单:一个恶意的GitHub issue标题包含伪装成错误消息的指令。AI代理的工作流将issue标题直接插入prompt中。代理执行了注入的指令,对恶意包运行npm install,并从CI环境中窃取了ANTHROPIC_API_KEY

在恶意包被移除之前,该攻击已影响约4,000台开发者机器。

加固你的工作流

**限制工具权限。**上述Claude工作流中的--allowedTools标志限制了Claude的能力。它可以读取diff和发布评论。它不能运行任意shell命令、写入文件或访问密钥。这是最有效的缓解措施。

claude_args: |
  --allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"

没有这个限制,精心构造的PR diff可以指示Claude在runner上执行命令。

**永远不要将不受信任的输入插入prompt。**不要在prompt字段中使用${{ github.event.issue.title }}${{ github.event.pull_request.body }}。传递仓库和PR编号,让action通过GitHub API获取内容。

**谨慎处理fork PR。**Fork PR默认以降低的GITHUB_TOKEN权限运行,但如果通过pull_request_target触发,你的密钥仍然对工作流可用。对AI审查工作流使用pull_request(而非pull_request_target)。这样fork PR无法访问你的API密钥,审查不会运行,这是安全的默认行为。

on:
  pull_request:        # Safe: fork PRs cannot access secrets
    types: [opened, synchronize]
  # pull_request_target:  # Dangerous: fork PRs CAN access secrets

**轮换API密钥。**如果密钥通过CI日志或被入侵的runner泄露,影响范围仅限于轮换间隔内。至少每季度轮换一次。

**审计工作流运行记录。**定期检查Actions标签页,查看异常运行时间或意外的工具调用。审查耗时45分钟而非通常的3分钟,可能表明模型正在被操控。

AI代码审查每个Pull Request的成本是多少?

成本随PR大小而变化。Claude和Gemini都按处理的token收费。输入token包括PR diff、文件上下文和你的prompt。输出token是审查评论。

PR大小 典型diff(行数) 估计输入token
50-100 2,000-5,000
200-500 8,000-20,000
500-1,500 20,000-60,000

Token数量因编程语言而异。200行Python diff比200行Java diff消耗更少的token,因为Java更冗长。

使用两个模型会使token成本翻倍,但不会使欧元成本翻倍,因为不同提供商的定价不同。查看Anthropic定价页面和Google AI定价页面上的当前每token费率。两者都使用按token定价,输入和输出token费率不同。

要估算月度预算:将平均PR大小(token数)乘以每月PR数量,再乘以每个模型的每token费率。每周合并50个中等大小diff的PR的团队可以这样计算:

weekly_cost = 50 * avg_tokens_per_pr * (claude_input_rate + gemini_input_rate)
              + 50 * avg_output_tokens * (claude_output_rate + gemini_output_rate)

降低成本

  • 路径过滤器阻止审查文档、lock文件和生成的代码。这是最大的节省。
  • 并发取消在新push到达时停止审查过时的commit。
  • 跳过草稿PR——不在触发器类型中包含ready_for_review,只在需要审查草稿转就绪的转换时添加。
  • **对风格审查使用较小的模型。**Gemini Flash比Gemini Pro便宜,适用于不需要深度推理的风格和文档检查。

对比:AI代码审查工具

特性 Claude Code Action Gemini Code Assist CodeRabbit GitHub Copilot
配置方式 GitHub Action(YAML) GitHub App或Action GitHub App 内置
定价模式 按token(API) 按token或免费层 按仓库订阅 按席位订阅
行内评论
自定义prompt 完全控制 完全控制(Action) 配置文件 有限
自托管runner 是(Action)
多模型支持 可组合 可组合 单模型 单模型
开源 是(MIT) 是(Action)

Claude Code Action和Gemini CLI Action是开源的,运行在你自己的runner上。你的代码除了对模型提供商的API调用外,永远不会离开你的基础设施。CodeRabbit和Copilot是托管服务,代码在它们的基础设施上处理。

AI代码审查有哪些局限性?

AI代码审查不能替代人工审查。它是第一遍扫描,发现常见问题并让人工审查者专注于架构、设计和业务逻辑决策。

**上下文窗口限制。**大型PR(超过1,500行更改)可能超过模型的上下文窗口,或产生浅层审查,因为模型无法在上下文中保持整个diff。将大型PR拆分为较小的。这是独立于AI审查的良好实践。

**没有运行时理解。**AI审查器看到的是静态代码。它们无法检测只在运行时表现出的问题:负载下的内存泄漏、时序依赖的竞态条件或大规模下的性能退化。

**误报不可避免。**即使有精确的prompt和项目上下文文件,模型仍会标记正确的代码。预计10-20%的发现是误报。如果比率更高,收紧prompt并在CLAUDE.mdGEMINI.md中添加更多上下文。

**没有组织知识。**模型不知道团队的不成文约定、历史决策或领域特定模式,除非你在上下文文件中记录它们。投入时间编写好的CLAUDE.mdGEMINI.md文件。这项投资会在每次未来的审查中得到回报。

**确定性。**同一个PR审查两次可能产生不同的发现。AI审查是概率性的。不要把"没有发现"当作"没有bug"。

故障排除

Claude审查工作流从未触发。 检查paths过滤器。如果你的源代码不在src/lib/app/中,调整路径以匹配你的项目结构。同时验证Claude GitHub App已安装在仓库中。

Gemini返回空审查。 确认GEMINI_API_KEY密钥已设置且有效。在本地测试:

curl -s "https://generativelanguage.googleapis.com/v1beta/models?key=YOUR_KEY" | head -20

如果你看到模型列表,说明密钥有效。

审查耗时过长。 timeout-minutes: 15设置会在超过15分钟时终止工作流。超过1,000行的大型PR可能需要5-10分钟。如果超时频繁,收紧paths过滤器以减小diff大小。

误报过多。CLAUDE.mdGEMINI.md中添加项目上下文。具体说明模型应忽略的模式。"不要标记X"比"宽松一些"更有效。

状态检查一直待处理。 聚合工作流在workflow_run完成时触发。如果两个审查工作流中的一个被跳过(因为没有匹配的文件变更),聚合可能不会触发。在聚合工作流中添加覆盖两个审查工作流并集的paths过滤器,或使用一个始终运行的独立状态检查。


版权所有 2026 Virtua.Cloud。保留所有权利。 本内容为 Virtua.Cloud 团队原创作品。 未经书面许可,禁止复制、转载或再分发。

准备好亲自尝试了吗?

几秒内部署您自己的服务器。支持 Linux、Windows 或 FreeBSD。

查看 VPS 方案