开发者的新武器:用Claude Skill把自动化代码审查与单元测试生成接进CI/CD

📅 发布时间:2026/10/3 12:05:29
开发者的新武器:用Claude Skill把自动化代码审查与单元测试生成接进CI/CD
1. 为什么要把 Claude Skill 塞进 CI/CD 流水线先说清楚 Claude Skill 是什么、能做什么、适合谁。Claude Skill 是 Anthropic 在 2025 年 10 月推出的能力封装机制本质是把一段可复用的提示词、工作流程和代码规范写进.claude/skills/目录下的 markdown 文件需要时用skill 技能名调用。它和随手写提示词最大的区别在于Skill 可以进 Git 仓库做版本管理团队共享一套模板不会因为对话轮次变长而失效。适合谁适合那些每天要重复交代“记得加错误处理”“测试要覆盖边界条件”的后端、前端和测试开发同学。但只在本地用 Skill还是得靠人手动触发。真正让这件事产生质变的是把它接进 CI/CD。你想想代码审查和单元测试生成这两件事恰好是“规则明确、重复度高、又必须做”的典型。每次 PR 提交如果能让流水线自动跑一遍 AI 审查、自动生成缺失的单测用例reviewer 打开 PR 时看到的不再是空白而是一份带行号、带修复建议的结构化报告人工 review 就能聚焦在架构和业务逻辑上。我试过在一个中型 Node 项目里落地这套流程最直观的变化是以前 PR 里那些“这里可能空指针”“这个 SQL 拼接有注入风险”的低级问题现在在提交后两分钟内就被自动标出来了。开发者自己就能改掉不用等 reviewer 打回来。这篇文章就按 GitHub Action 场景把 Skill 配置、工作流 YAML、触发规则、结果验证和排错一次讲透中间用 TaoToken 统一 Key 和 API 通道接入避免每个仓库到处散落密钥。2. TaoToken 前置准备统一 Key 与 API 通道在把 Skill 接进 GitHub Action 之前得先解决一个现实问题CI 环境里怎么安全地调用模型。你不可能把某个厂商的原始 Key 硬编码在 workflow 文件里也不希望每个仓库各配一套。TaoToken 在这里扮演的角色是统一入口——一个 Key、一个 Base URL兼容 Anthropic 风格的接口Claude Code、Cline、Codex 这类工具都能接。先注册并拿到 Key。打开官网 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content 完成账号注册后进入控制台。控制台地址是 https://taotoken.net/console?utm_sourcetaotoken_aicg_blog_endutm_contentconsoleutm_campaignrewrite 在左侧找到 API Keys 菜单新建一个 Key。建议给 CI 单独建一个 Key命名成github-action-ci方便后续按用途区分和轮换。API Keys 页面直达https://taotoken.net/api-keys?utm_sourcetaotoken_aicg_blog_endutm_contentapi-keysutm_campaignrewrite 。拿到 Key 之后记住两个地址。官网首页是 https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_mediumcsdnutm_campaignrewriteutm_content API 基址是 https://taotoken.net/api 注意 API 地址后面不加任何 UTM 参数保持干净。这个 Base URL 就是后面所有配置里要填的ANTHROPIC_BASE_URL。关于模型 IDTaoToken 的模型对话页面可以查看当前可用的模型列表地址是 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 。在 CI 里做代码审查和单测生成建议选一个代码能力强的模型把它的 Model ID 记下来后面写进配置。如果你打算长期在多个仓库跑 Agent 类任务可以了解下 Coding Plan地址是 https://taotoken.net/coding-plan?utm_sourcetaotoken_aicg_blog_endutm_contentcoding-planutm_campaignrewrite 它更适合高频、长期的编码场景。接入文档在 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 遇到接口细节问题可以对照查。如果你用的是 Claude Code 作为本地执行器它的接入说明在 https://taotoken.net/claude-code-anthropic?utm_sourcetaotoken_aicg_blog_endutm_contentClaudeCodeAnthropicutm_campaignrewrite 里面写了 Base URL、Key、Model ID 三件套怎么填。这里要强调一个安全原则Key 绝对不能写进 workflow 文件明文。正确做法是存进 GitHub 仓库的 Secrets在 workflow 里用${{ secrets.TAOTOKEN_API_KEY }}引用。下面进入具体配置。3. 可复制配置Skill 文件 GitHub Action 工作流 YAML这一节是全文的核心所有片段都可以直接复制。先建目录结构再写 Skill 文件最后写 workflow。3.1 目录结构在项目根目录下创建如下结构.claude/ skills/ code-review/ SKILL.md test-gen/ SKILL.md .github/ workflows/ ai-review.yml.claude/skills/目录建议加入 Git 仓库团队共享。.github/workflows/是 GitHub Action 的标准位置。3.2 代码审查 Skill 配置创建.claude/skills/code-review/SKILL.md内容如下--- name: code-review description: 对代码变更进行多维度审查涵盖安全、逻辑、性能、代码风格四个维度输出结构化报告 --- # 代码审查专家 Skill 你是一位经验丰富的代码审查专家。收到代码后请按以下标准进行系统化审查。 ## 审查维度 ### 1. 安全性 - SQL 注入风险尤其检查字符串拼接的查询 - XSS 漏洞用户输入是否经过转义 - 敏感信息泄露API 密钥、密码是否硬编码 - 权限校验是否完整 ### 2. 逻辑正确性 - 空指针 / undefined 访问风险 - 边界条件处理数组越界、除零、空集合 - 并发安全问题竞态条件、死锁 - 异常处理是否完善 ### 3. 性能 - 不必要的循环嵌套 - N1 查询问题 - 内存泄漏风险事件监听未移除、定时器未清理 - 大数据量操作是否有分页或流式处理 ### 4. 代码质量 - 命名是否符合项目规范 - 函数是否过长超过 50 行需拆解 - 重复代码是否存在 - 注释是否与代码一致 ## 输出格式 请按以下结构输出审查报告 ### 严重问题P0 - 必须修复 安全漏洞、逻辑错误等会导致线上故障的问题 ### 警告P1 - 建议修复 性能隐患、代码异味、可维护性问题 ### 建议P2 - 可选 优化建议、最佳实践参考 ### 亮点 代码中值得肯定的部分 ## 审查原则 1. 所有判断必须有具体依据引用代码行号 2. 每个问题附带修复建议给出示例代码 3. 宁缺毋滥避免刷屏式输出低质量建议 4. 不确定的地方标注“需要人工确认”3.3 单元测试生成 Skill 配置创建.claude/skills/test-gen/SKILL.md--- name: test-gen description: 为给定函数或模块自动生成单元测试用例覆盖正常路径、边界条件、异常情况 --- # 单元测试生成专家 Skill ## 角色定位 你是一位经验丰富的测试工程师擅长编写高质量、可维护的单元测试。 ## 工作流程 ### Step 1: 分析待测代码 - 识别函数的所有输入参数及其类型 - 识别函数的返回值类型 - 识别函数内部的分支逻辑和依赖 ### Step 2: 设计测试用例 基于等价类划分和边界值分析法覆盖以下场景 | 用例类型 | 覆盖内容 | 最少数量 | |---------|---------|---------| | 正常路径 | 函数设计场景下的典型输入 | 1-2 个 | | 边界条件 | 空值、零值、最大/最小值、数组首尾 | 2-3 个 | | 异常路径 | 无效输入、依赖失败、超时 | 2-3 个 | | 并发场景 | 如有状态考虑竞态 | 按需 | ### Step 3: 生成测试代码 - 使用项目已有的测试框架Jest/Vitest/JUnit/pytest - 遵循 AAA 模式Arrange准备、Act执行、Assert断言 - 每个测试用例独立不依赖执行顺序 - Mock 外部依赖不发起真实网络请求 ### Step 4: 质量自查 - 每个用例是否有明确的预期结果 - 测试命名是否清晰描述场景 - 是否有冗余的测试用例 ## 注意事项 - 不要修改源代码只生成测试文件 - 不确定的地方添加 todo 注释标注 - 如果待测代码难以测试在报告末尾给出重构建议3.4 GitHub Action 工作流 YAML创建.github/workflows/ai-review.yml。这里用 TaoToken 的 Base URL 和 Key通过环境变量注入name: AI Code Review and Test Gen on: pull_request: types: [opened, synchronize, reopened] branches: - main - develop permissions: contents: read pull-requests: write jobs: ai-review: runs-on: ubuntu-latest env: ANTHROPIC_BASE_URL: https://taotoken.net/api ANTHROPIC_API_KEY: ${{ secrets.TAOTOKEN_API_KEY }} ANTHROPIC_MODEL: ${{ secrets.TAOTOKEN_MODEL_ID }} steps: - name: Checkout code uses: actions/checkoutv4 with: fetch-depth: 0 - name: Setup Node uses: actions/setup-nodev4 with: node-version: 20 - name: Install Claude Code CLI run: npm install -g anthropic-ai/claude-code - name: Get PR diff id: diff run: | git fetch origin ${{ github.base_ref }} git diff origin/${{ github.base_ref }}...HEAD /tmp/pr.diff echo diff_size$(wc -l /tmp/pr.diff) $GITHUB_OUTPUT - name: Run code review skill if: steps.diff.outputs.diff_size 0 run: | claude -p skill code-review 请审查以下 git diff 内容按 SKILL.md 的输出格式给出报告$(cat /tmp/pr.diff) /tmp/review.md - name: Run test gen skill if: steps.diff.outputs.diff_size 0 run: | claude -p skill test-gen 针对本次变更涉及的核心函数生成单元测试用例使用项目现有测试框架 /tmp/tests.md - name: Post review comment uses: actions/github-scriptv7 with: script: | const fs require(fs); const review fs.readFileSync(/tmp/review.md, utf8); const tests fs.readFileSync(/tmp/tests.md, utf8); const body ## AI 代码审查报告\n\n${review}\n\n---\n\n## 单元测试生成建议\n\n${tests}; await github.rest.issues.createComment({ owner: context.repo.owner, repo: context.repo.repo, issue_number: context.issue.number, body: body });这段 YAML 的关键点ANTHROPIC_BASE_URL指向 TaoToken 的 API 地址ANTHROPIC_API_KEY和ANTHROPIC_MODEL从 Secrets 读取。触发规则是 PR 打开、同步、重新打开时跑目标分支限定 main 和 develop。fetch-depth: 0是为了拿到完整的 git 历史否则 diff 算不出来。3.5 三件套配置对照如果你用的是 Cline、Codex 或 Claude Code 本地调试配置项对照如下配置项值说明Base URLhttps://taotoken.net/api不加 UTM 参数API Key控制台新建的 Key存 Secrets不写明文Model ID模型对话页查看选代码能力强的Codex 的auth.json里对应填base_url和api_keyCline 的 MCP 配置里填baseUrl和apiKey。三件套缺一不可尤其是 Model ID填错会直接报模型不存在。4. 验证请求与成功结果一次提交后的完整链路配置写完得验证它真的能跑。这一节演示从提交到看到审查意见和单测用例的完整过程。4.1 本地先验证 Skill 能跑通在推 CI 之前先在本地确认 Skill 和 TaoToken 通道是通的。设置环境变量export ANTHROPIC_BASE_URLhttps://taotoken.net/api export ANTHROPIC_API_KEY你的Key export ANTHROPIC_MODEL你的ModelID然后写一个故意有问题的函数来测试。创建utils/calculator.tsexport function divide(a: number, b: number): number { return a / b; }这个函数没处理除零正好用来验证审查 Skill 能不能发现问题。运行claude -p skill code-review 请审查 utils/calculator.ts预期输出里应该出现类似这样的内容### 严重问题P0 - 必须修复 - utils/calculator.ts:2 - divide 函数未处理除数为 0 的情况会导致返回 Infinity 或 NaN。 修复建议 if (b 0) { throw new Error(除数不能为0); }如果看到了带行号和修复建议的报告说明 Skill 和 TaoToken 通道都正常。4.2 验证单测生成接着验证 test-genclaude -p skill test-gen 为 utils/calculator.ts 中的 divide 函数生成单元测试使用 Jest 框架预期输出import { divide } from ./calculator; describe(divide, () { it(should return correct result when dividing positive numbers, () { expect(divide(10, 2)).toBe(5); expect(divide(9, 3)).toBe(3); }); it(should handle negative numbers correctly, () { expect(divide(-10, 2)).toBe(-5); expect(divide(10, -2)).toBe(-5); }); it(should handle division by 1, () { expect(divide(100, 1)).toBe(100); }); it(should throw error when dividing by zero, () { expect(() divide(10, 0)).toThrow(除数不能为0); }); });注意最后一条用例——它期望抛错但当前实现并不会抛错。这恰好说明 test-gen 按边界条件设计了用例能暴露实现缺陷。4.3 推 CI 看真实效果本地通了之后把改动推到分支开一个 PR。GitHub Action 会自动触发。在 Actions 标签页能看到AI Code Review and Test Gen这个 workflow 在跑。跑完后回到 PR 页面底部会出现一条机器人评论里面是完整的审查报告和单测建议。实测下来一个改动 200 行左右的 PR从触发到评论出现大约两到三分钟。审查报告会按 P0/P1/P2 分级单测建议会给出可直接粘贴的测试代码。reviewer 打开 PR 时第一眼看到的就是这份报告可以直接在评论里讨论具体问题。4.4 触发规则说明workflow 里的on.pull_request.types决定了什么时候跑。opened是新建 PRsynchronize是 PR 有新提交reopened是重新打开。如果你只想在特定路径变更时跑可以加paths过滤on: pull_request: types: [opened, synchronize] paths: - src/** - utils/**这样只有 src 和 utils 目录下的文件变更才会触发避免改个 README 也跑一遍浪费额度。5. 本篇常见错误排查配置过程中最容易踩的坑集中在认证、代理和输出解析三块。下面按真实报错逐个拆。5.1 401 Unauthorized报错长这样Error: 401 Unauthorized - invalid api key原因通常是 Secrets 没配、名字写错或者 Key 被撤销了。排查步骤进仓库 Settings → Secrets and variables → Actions确认TAOTOKEN_API_KEY存在且值正确。注意 workflow 里引用的是secrets.TAOTOKEN_API_KEY名字必须完全一致大小写敏感。如果 Key 是在控制台新建的确认没有复制时带上多余空格。5.2 local proxy failed / connection refused报错Error: local proxy failed: connect ECONNREFUSED 127.0.0.1:xxxx这是本地调试时常见的。原因是你本地设了某个代理环境变量但代理服务没启动。检查HTTP_PROXY、HTTPS_PROXY、ALL_PROXY这几个环境变量如果指向本地端口而服务没跑就会报这个。解决方法是清掉这些变量或者确保代理服务正常运行。在 CI 环境里一般不会遇到因为 GitHub runner 是干净环境。5.3 reading choices 相关报错报错Error: reading choices of undefined这个通常出现在用 OpenAI 兼容格式调用时响应结构不符合预期。TaoToken 的 API 基址是 https://taotoken.net/api 如果你在代码里手动拼了/v1/chat/completions之类的路径可能和实际接口不匹配。对照接入文档 https://taotoken.net/doc?utm_sourcetaotoken_aicg_blog_endutm_contentdocutm_campaignrewrite 确认请求路径和响应格式。用 Claude Code CLI 的话它会自动处理一般不会碰到这个。5.4 OAuth 相关报错报错Error: OAuth token expired or invalid如果你之前用 OAuth 方式登录过 Claude Code本地可能残留了旧的凭证文件优先级高于环境变量。检查~/.claude/目录下有没有credentials.json之类的文件有的话先备份再删除让环境变量生效。CI 环境里没有这个文件所以不会受影响。5.5 Model ID 填错报错Error: model not found: xxxModel ID 必须和模型对话页列出的完全一致。去 https://taotoken.net/models?utm_sourcetaotoken_aicg_blog_endutm_contentmodelsutm_campaignrewrite 复制准确的 ID注意大小写和连字符。填进 Secrets 的TAOTOKEN_MODEL_ID后workflow 里通过ANTHROPIC_MODEL引用。5.6 diff 为空导致 Skill 不执行workflow 里有个判断if: steps.diff.outputs.diff_size 0如果 diff 为空就跳过。如果发现 Action 跑了但没输出先看Get PR diff这步的日志确认 diff 文件是不是空的。常见原因是fetch-depth没设成 0导致拿不到 base 分支的历史。6. 把这条流水线用起来配置和排错都过了一遍最后说几个实际用下来的经验。Skill 文件一定要进 Git团队共享一套新人拉下来就能用有改进就提 PR。审查和测试生成建议用不同的 Skill 从不同角度跑不要让同一个 Skill 又写又审容易产生盲点。CI 里的 Key 单独建一个方便按用途轮换和审计。如果你还没开始建议先从 code-review 这一个 Skill 接进 CI跑一周感受下 PR 里自动出现审查报告是什么体验。稳定之后再加 test-gen。TaoToken 的 Key 和 Base URL 配一次后面所有仓库都能复用省去到处散落密钥的麻烦。模型对话页面可以随时切换模型对比效果接入文档遇到问题随时查。这条流水线搭好之后代码审查和单测生成这两件苦差事就真的变成提交后自动完成的事了。