把 Claude Code 接进 CI:一次真实跑通的 PR 审查门禁教程

Claude Code CI/CD 审查门禁教程题图

把 Claude Code 放进 CI/CD 流水线,听起来像个大工程,但核心其实只有一条命令加一个退出码。AI Parabellum 在 11 月 13 日实测了一套完整做法(Claude Code v2.1.322,macOS):用 claude -p 无头模式审 PR 的 diff,返回 JSON 结论,再由 shell 把结论翻成退出码——通过就放行,失败就挡住合并。一次 25 行 diff 的审查大约花 0.08 到 0.18 美元,3 个 turn,10 秒左右跑完。

CI 审查流程图:PR 触发、取 diff、claude -p 审查、判结论、发评论

两条路线:GitHub Action 还是 claude -p 脚本

Anthropic 官方文档给了两条路线。Claude Code GitHub Action 适合在 GitHub 上直接评论 PR:交互模式下等 @claude 触发,自动化模式下按给定的 prompt 直接跑。而 claude -p 无头模式是一条能在任何 CI 系统里跑的脚本,输出 JSON,加一个退出码就能当门禁。本教程走第二条路线,因为它不挑 CI 系统,GitHub Actions、GitLab CI 或一台裸服务器都能用。

第一步:搭一个故意埋了问题的小仓库

教程用了一个很小的 Python 项目做演示。main 分支只有一个能正常工作的 total_price 函数和一个测试;feature/discounts 分支加了折扣、求平均和报表函数,并故意埋了几个问题:源码里硬编码了一枚假支付密钥 PAYMENT_KEY = "sk_live_..."(不是真密钥,专门用来考审查员)、用 os.system 拼接命令的 run_report、折扣能把总价算成负数、空列表求平均会直接崩溃。审查对象就是这两个分支之间的一份 diff。

第二步:写审查脚本 ci-review.sh

整条流水线的核心是一个小 shell 脚本:把分支 diff 存成文件,让 Claude 审,只报真实 bug 和安全问题,用 JSON Schema 固定返回结构,再把 verdict 翻成退出码。

ci-review.sh 脚本截图

#!/usr/bin/env bash

set -euo pipefail

git diff main...HEAD > pr.diff

SCHEMA='{"type":"object","properties":{"verdict":{"type":"string","enum":["pass","fail"]},"issues":{"type":"array","items":{"type":"object","properties":{"severity":{"type":"string"},"file":{"type":"string"},"problem":{"type":"string"}},"required":["severity","file","problem"]}}},"required":["verdict","issues"]}'

claude -p "Review the changes in pr.diff. Report real bugs and security problems only. Use verdict fail if any high severity issue exists." \
  --output-format json \
  --json-schema "$SCHEMA" \
  --permission-mode dontAsk \
  --allowedTools "Read" \
  --max-turns 6 \
  --max-budget-usd 0.50 < /dev/null > review.json

jq -r '.structured_output.issues[] | "\(.severity)\t\(.file)\t\(.problem)"' review.json

VERDICT=$(jq -r '.structured_output.verdict' review.json)

echo "verdict: $VERDICT"

[ "$VERDICT" = "pass" ]

最后一行是关键:shell 的 [ ... ] 测试为真返回 0、为假返回 1,CI 系统把非零退出码当作任务失败,于是 verdict 就成了门禁。几个 flag 各有分工:-p 跑一次提示词就退出,正是 CI 要的;--output-format json 返回带结果、会话 ID 和元数据的结构化 JSON;--json-schema 把答案锁进固定结构,存在 structured_output 字段里;--permission-mode dontAsk 拒绝一切需要人工确认的操作;--allowedTools "Read" 只放行读文件;--max-turns 6 和 --max-budget-usd 0.50 给单次审查上双重上限;< /dev/null 告诉 Claude 没有管道输入,否则第一次测试会卡住等 3 秒 stdin。

第三步:跑一次,看它拦下危险改动

在有问题的分支上跑 ./ci-review.sh; echo "exit code: $?",Claude 找出了 4 个问题:2 个高危——硬编码的支付密钥和 run_report 里的命令注入;2 个中危——折扣算出负总价、空列表求平均崩溃。verdict 是 fail,脚本退出码 1,CI 变红挡住合并。第一次测试整个审查大约 10 秒。

第四步:修掉问题,再跑一次看它放行

作者手工改了 app.py:密钥改成环境变量读取,shell 调用改成 subprocess.run 传参数列表,折扣和求平均加了保护。提交后再跑同一脚本,这次 Claude 只剩 2 条低危提示,verdict 是 pass,退出码 0,任务变绿。通过的那次用了 3 个 turn,约 0.08 美元;失败的那次也是 3 个 turn,约 0.18 美元。

作者提醒了一点:模型两次运行的措辞并不完全相同,通过的那次还多了一条关于折扣与税交互的低危提示。审查是判断,不是单元测试,人的复核不能省。

第五步:搬进 GitHub Actions

上面的脚本本身是可移植的;要在 GitHub 上跑,Anthropic 提供的 Action 是更简单的路。教程按官方文档写了一份 workflow(YAML 能通过解析检查,但作者说明没有在 GitHub 上真正跑过):

name: Claude PR Review
on:
  pull_request:
    types: [opened, synchronize]
jobs:
  review:
    runs-on: ubuntu-latest
    timeout-minutes: 10
    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: "Review this pull request for bugs and security problems. Report only real issues."
          claude_args: |
            --max-turns 6
            --allowedTools "Read,Grep"

要点:prompt 一给就进入自动化模式;id-token: write 是 Action 默认 GitHub App 鉴权所需的权限;timeout-minutes: 10 是 workflow 级超时,防止卡住的任务一直烧钱;密钥只放 Secrets,绝不要写进 workflow 文件。最快的安装方式是在 Claude Code 里跑 /install-github-app。

无人值守的安全规则

CI 任务没人盯着,要当作一个权限很窄的新同事来管:密钥只放 Secrets;只给任务必需的权限和工具,审查员要 Read 就够了,绝不要给 shell 工具;turn、预算、超时三重上限都要设;注意 fork 的 PR 拿不到仓库 secrets,所以审查只对同仓库分支生效;CLAUDE.md 保持精简,因为每次运行都会读它。常见错误还包括盲信 verdict、忘设上限、误传 github_token(用默认 token 的提交不会触发 workflow)。

Claude Code CI 审查速查表

两个实用变体

如果只想在高危问题出现时才失败,可以用 jq 直接按 severity 过滤:jq -e '[.structured_output.issues[] | select(.severity == "high")] | length == 0' review.json,-e 会让结果为假时退出码非零,一行就是一道门。也可以改成定时跑,每天出一份报告;prompt 里还能直接调仓库 .claude/skills/ 下的 skill。

想自己试,先建一个临时 Git 仓库,在 feature 分支里故意放一个明显 bug,跑一遍审查脚本;也可以直接让 Claude 帮你写这个脚本:“Write a shell script named ci-review.sh that saves git diff main…HEAD to pr.diff, runs claude -p to review it with a JSON schema that returns a verdict and a list of issues, allows only the Read tool, caps turns and budget, and exits 1 when the verdict is fail.”

站内相关阅读:本站社区昨天发过这篇教程的短版 把 Claude Code 接进 CI/CD:PR 审查看门实测,硬编码密钥和命令注入直接拦下;想省 token,还可以看看 Claude Code MCP 工具搜索实测:3 个服务器 58 个工具,开局省下 6.2 万 token。

转自 AI Parabellum 的文章《Claude Code CI/CD: A Working Example》,原文链接

© 版权声明
THE END
喜欢就支持一下吧
点赞25 分享