使用GitHub Actions + Claude Code CLI构建PR自动审查流水线

使用GitHub Actions + Claude Code CLI构建PR自动审查流水线

在GitHub Actions中直接集成claude -p实现PR审查自动化的实战指南。详解--bare、--dangerously-skip-permissions、--max-budget-usd标志,让Claude Code在CI环境中安全运行的完整YAML示例。

每次PR提交后,手动阅读代码的工作量开始积累。一个审查者每天能处理的PR数量是有限的,特别是对于样板代码变更或重复模式的bug,不禁想到”人类真的需要读这些吗?“于是我将Claude Code CLI直接连接到GitHub Actions,实现了PR审查自动化。

结论是:配置比预期简单得多。Claude Code 2.1新增的--bare--no-session-persistence标志让我们可以在CI环境中干净地运行claude -p,没有任何多余开销。本文分享我实际测试过的工作流YAML和核心CLI标志组合。

前提条件

开始配置前需要确认以下几点。

必须:

  • Anthropic API密钥 (ANTHROPIC_API_KEY) — 在console.anthropic.com获取。在仓库的 Settings → Secrets and variables → Actions 中以ANTHROPIC_API_KEY为名注册
  • 启用了GitHub Actions的仓库
  • Node.js 20+(Actions运行时可自动安装)

强烈建议:

  • 在Anthropic控制台设置月度使用上限。否则遇到异常大的PR或循环时费用可能超出预期
  • .github/CODEOWNERS文件 — 明确区分必须人工审查的文件和Claude可以优先处理的文件

可选(用于本地测试):

npm install -g @anthropic-ai/claude-code
claude --version
# 2.1.123 (Claude Code)

本地安装后可以在上传到Actions之前先测试提示词质量和成本。

理解Claude Code的CI模式

在GitHub Actions中运行claude命令时,最需要了解的是”如何完全关闭交互模式”。本地的Claude Code会加载LSP、保存会话、执行钩子等,这些在CI中完全多余。

2.1.123版本下的CI标志组合如下:

claude -p "这里放提示词" \
  --output-format text \
  --max-budget-usd 0.50 \
  --bare \
  --no-session-persistence \
  --dangerously-skip-permissions

各标志的作用:

标志作用CI必要性
-p非交互模式(输出后退出)必须
--output-format textMarkdown文本输出必须
--max-budget-usd 0.50每次运行的最大费用上限强烈建议
--bare禁用LSP、钩子、内存、CLAUDE.md自动发现建议
--no-session-persistence禁用会话磁盘保存建议
--dangerously-skip-permissions绕过权限检查仅限CI沙盒

--dangerously-skip-permissions名字听起来危险,但在GitHub Actions这样的隔离临时环境中是正确选择。每次都在全新VM上启动,没有持久状态,是安全的。本地机器上绝对不要使用。

--max-budget-usd一开始容易被低估。不设置的话,大diff的PR可能触发多次API调用,费用是预期的数倍。每次PR审查设$0.30〜0.50,夜间审计每文件$0.10,根据团队规模每月$20〜60范围内可控。

Step 1: 构建PR审查工作流

创建.github/workflows/claude-pr-review.yml。核心流程简单:PR打开 → 提取diff → 传给Claude → 将结果作为PR评论发布。

name: Claude Code PR Review

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      pull-requests: write
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0   # 跨分支diff所需

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install Claude Code
        run: npm install -g @anthropic-ai/claude-code

      - name: Generate PR diff
        run: |
          git diff origin/${{ github.base_ref }}...HEAD \
            -- '*.ts' '*.tsx' '*.js' '*.py' '*.go' > pr.diff
          echo "DIFF_SIZE=$(wc -c < pr.diff)" >> $GITHUB_ENV

      - name: Skip if no diff
        if: env.DIFF_SIZE == '0'
        run: echo "无代码变更 — 跳过审查" && exit 0

      - name: Claude Code review
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          DIFF_CONTENT=$(cat pr.diff)
          claude -p \
            "Review this PR diff as a senior engineer. Respond in markdown with sections: ## Bugs, ## Security, ## Performance, ## Style. For each issue, cite file+line and explain why it matters.\n\n${DIFF_CONTENT}" \
            --output-format text \
            --max-budget-usd 0.50 \
            --bare \
            --no-session-persistence \
            --dangerously-skip-permissions \
            > review.md

      - name: Post review to PR
        uses: actions/github-script@v7
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}
          script: |
            const fs = require('fs');
            const body = fs.readFileSync('review.md', 'utf8');
            await github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: `## 🤖 Claude Code Review\n\n${body}`
            });

设计上的几点说明:

fetch-depth: 0: 不设置这个,git diff origin/main...HEAD就无法工作。默认的浅克隆(fetch-depth: 1)没有基础分支历史记录,这是个常见陷阱。

文件扩展名过滤: 明确指定-- '*.ts' '*.tsx' '*.js' '*.py' '*.go'更好。把配置文件、JSON、文档都包含进diff会浪费token,也会降低审查质量。

DIFF_SIZE检查: 避免在只修改类型定义或注释的PR上发起不必要的API调用。

Step 2: 夜间代码健康审计

比PR审查更实用的是夜间审计。每晚UTC时间1点,对过去7天变更的文件进行技术债务和改进点整理,保存为制品。

name: Nightly Code Audit

on:
  schedule:
    - cron: '0 1 * * *'
  workflow_dispatch:
    inputs:
      since_days:
        description: 'Days to look back'
        default: '7'
        type: string

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

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Install Claude Code
        run: npm install -g @anthropic-ai/claude-code

      - name: Collect recently changed files
        run: |
          DAYS="${{ inputs.since_days || '7' }}"
          git log --since="${DAYS} days ago" \
            --name-only --format="" \
            -- '*.ts' '*.tsx' '*.py' | sort -u > changed.txt
          echo "FILES=$(cat changed.txt | wc -l)" >> $GITHUB_ENV

      - name: Claude tech-debt audit
        if: env.FILES != '0'
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
        run: |
          echo "# Code Health Report — $(date +%Y-%m-%d)" > report.md

          while IFS= read -r FILE; do
            [ -f "$FILE" ] || continue
            LINES=$(wc -l < "$FILE")
            [ "$LINES" -gt 500 ] && continue

            echo "## $FILE" >> report.md
            claude -p \
              "In 3 bullet points: main tech debt, dead code, or improvement opportunity. Be specific, not generic." \
              --add-dir . \
              --output-format text \
              --max-budget-usd 0.10 \
              --bare \
              --no-session-persistence \
              --dangerously-skip-permissions \
              "$(cat "$FILE")" >> report.md
            echo "" >> report.md
          done < changed.txt

      - name: Upload report
        uses: actions/upload-artifact@v4
        with:
          name: audit-${{ github.run_number }}
          path: report.md
          retention-days: 90

坦白说:没有项目历史和领域知识、只看整个文件的Claude,其”技术债务”建议往往比较通用——“函数太长”、“缺少错误处理”之类。PR审查因为只看diff所以更精准。全文件审计最好把期望值调低,当作”提供起点的工具”来用。

Step 3: 推送前先本地测试

部署到Actions前用本地脚本测试,方便调整预算设置。

#!/usr/bin/env bash
# scripts/local-review.sh
set -euo pipefail
BASE="${1:-main}"

DIFF=$(git diff "$BASE"...HEAD -- '*.ts' '*.tsx' '*.js' '*.py' 2>/dev/null || echo "")

if [ -z "$DIFF" ]; then
  echo "No changes vs $BASE"
  exit 0
fi

echo "Diff: $(echo "$DIFF" | wc -l) lines"

claude -p \
  "Review this PR diff. Return markdown with Bugs, Security, Performance sections.\n\n${DIFF}" \
  --output-format text \
  --max-budget-usd 0.30 \
  --no-session-persistence \
  --dangerously-skip-permissions

基于Claude Code钩子的代码审查自动化相比:钩子针对提交前的本地检查进行了优化,而GitHub Actions作为团队PR入口使用,两者互补。

通过CLAUDE.md注入项目规则

基本提示词无法让Claude了解项目的编码规范。在仓库根目录创建CLAUDE.md可以自动注入项目规则。

--bare模式下,CLAUDE.md自动发现功能被禁用。需要同时指定--add-dir .才能识别。添加--add-dir .后Claude可以访问整个仓库,diff上下文理解会大幅提升,但预算需要提高到$0.80〜1.00。

成本与现实期望

将这个流水线推广到团队时,最常见的问题是”要多少钱”。

实测估算:

  • PR审查1次(diff 200〜500行):$0.15〜0.35
  • 夜间审计(20个文件):$0.80〜1.50
  • 月度(50个PR + 30次夜间):$20〜60

Anthropic原生Claude Code Review功能每次PR $15〜25相比,要便宜得多。虽然深度不如多代理审查,但用于捕获bug和安全问题已经足够。

--max-budget-usd是最重要的安全网。设置后,即使遇到异常大的diff或意外的重复调用,也会在指定金额时自动停止。

实际审查输出示例

以下是我实际项目收到的Claude审查评论节选(代码已简化):

## 🤖 Claude Code Review

## Bugs
- **src/api/users.ts:47**`user.id`没有null检查。
  `findUser()`可以返回null,但下一行直接访问`user.id`
  正常使用时会产生运行时错误。

## Security
- **src/api/orders.ts:23** — SQL查询通过字符串插值构建。
  `WHERE id = ${orderId}`模式存在SQL注入风险。
  请替换为参数化查询。

## Performance
- **src/components/List.tsx:88** — 每次渲染都创建新数组。
  render函数中没有useMemo的`items.filter().map()`链,
  在100件以上的列表中产生不必要的重计算。

## Style
- None

Security的发现是真实的,确实是SQL注入漏洞,差点通过代码审查进入生产环境。Performance标记是误报——该组件在上一个文件中被memo包裹,但从diff中无法判断。这是只看diff的固有局限。

常见错误与解决方法

Error: unknown flag '--dangerously-skip-permissions'
Claude Code 2.1以下没有这个标志。用claude --version确认,npm install步骤要确保安装最新版本。

git diff: not a git repository
checkout的fetch-depth默认为1(浅克隆)时没有基础分支。必须设置fetch-depth: 0

评论未发布
permissions块需要pull-requests: write。另外仓库的Actions权限设置为”只读”时也会失败。

审查质量太低
添加--add-dir .并使用更具体的提示词。“Review this code”会产生通用输出。明确指定”TypeScript Node.js API,重点检查:输入验证缺失、未处理的Promise、N+1查询模式”才能产生真正有用的结果。

我的结论

用了两周后,坦诚地说:它是一个不错的安全网,而不是人工审查的替代品。它在CI中捕获了一个SQL注入风险和两个async错误处理漏洞,这点让我印象深刻。

架构决策、业务逻辑权衡、领域特定判断仍然需要人工审查。但”null检查是否遗漏”和”是否有硬编码密钥”——Claude处理这些很好。


沙盒实验日志

=== Claude Code CI Sandbox Log — Thu Apr 30 15:27:20 JST 2026 ===

验证的制品:
1. claude-pr-review.yml — 7步PR审查流水线(YAML有效)
2. nightly-audit.yml — 6步代码审计(YAML有效)
3. local-review.sh — 本地测试脚本(bash语法有效)

CLI标志确认来源:claude --help (v2.1.123)
  claude -p [prompt] --output-format text --max-budget-usd N
    --bare --no-session-persistence --dangerously-skip-permissions

阅读其他语言版本

这篇文章有帮助吗?

您的支持能帮助我创作更好的内容。请我喝杯咖啡吧。

关于作者

jw

Kim Jangwook

AI/LLM专业全栈开发者

凭借10年以上的Web开发经验,构建AI代理系统、LLM应用程序和自动化解决方案。分享Claude Code、MCP和RAG系统的实践经验。

返回博客列表