首页
/ Claude How To 的 /setup-ci-cd 命令实战:用 pre-commit 钩子与 GitHub Actions 搭建双层质量门禁

Claude How To 的 /setup-ci-cd 命令实战:用 pre-commit 钩子与 GitHub Actions 搭建双层质量门禁

2026-09-05 09:13:19作者:幸俭卉

本文以 Claude How To 仓库中的斜杠命令模板 setup-ci-cd.md 为主体,完整讲解 /setup-ci-cd 命令定义的四步工作流——分析项目、配置 pre-commit 钩子、创建 GitHub Actions 工作流、验证流水线。并结合该仓库自身真实落地的 pre-commit 配置.github/workflows 下的四个工作流文件,给出可复制、可验证的 CI/CD 质量门禁方案;读完你可以把这套“本地钩子 + 云端镜像检查”的完整配置直接套用到自己项目中。

/setup-ci-cd 命令是什么

/setup-ci-cd 是 Claude Code 的一个自定义斜杠命令(Skill),用于根据项目类型自动适配并实施一套完整的 DevOps 质量门禁。命令模板位于 01-slash-commands/setup-ci-cd.md,其 frontmatter 定义了命令名与用途:

---
name: setup-ci-cd
description: Implement pre-commit hooks and GitHub Actions for quality assurance
---

使用方式即在 Claude Code 交互会话中输入:

/setup-ci-cd

按照 斜杠命令指南,该模板可安装为 Skill(推荐,复制为 .claude/skills/setup-ci-cd/SKILL.md)或旧式命令(复制为 .claude/commands/setup-ci-cd.md)。命令的核心价值在于:它不是固定脚本,而是一段“适配指令”——让 Claude 先探测你的语言、框架与构建系统,再选择对应的工具链来生成配置,而不是无脑套用模板。

命令的三条总原则

原文档末尾给出了三条约束,它们贯穿整个工作流,是评估生成结果是否合格的标准:

原则 含义
使用免费/开源工具 优先 Prettier、Ruff、Bandit、markdownlint 等开源工具,不引入商业依赖
尊重现有配置 项目已有 .prettierrcpyproject.toml、ruff 配置等时必须沿用,不覆盖、不冲突
保持执行快速 钩子与 CI 都应在可接受时间内完成,避免质量门禁拖慢开发节奏

四步工作流总览

命令文档定义了明确的四步流程,后续所有实操都围绕它展开:

  1. Analyze project(分析项目):检测语言、框架、构建系统和已有工具链
  2. Configure pre-commit hooks(配置 pre-commit 钩子):按语言选择格式、静态检查、安全、类型检查与测试工具
  3. Create GitHub Actions workflows(创建工作流):在 .github/workflows/ 中镜像本地钩子,并加入矩阵、构建验证与部署步骤
  4. Verify pipeline(验证流水线):本地试跑、创建测试 PR、确认所有检查通过

第一步:分析项目,选择语言对应的工具链

命令文档按类别列出了各语言生态的候选工具,这一步的输出直接决定钩子与工作流里装哪些工具:

类别 候选工具(按语言)
格式化 Prettier / Black / gofmt / rustfmt 等
Lint ESLint / Ruff / golangci-lint / Clippy 等
安全扫描 Bandit / gosec / cargo-audit / npm audit
类型检查 TypeScript / mypy / flow(如适用)
测试 运行与语言匹配的相关测试套件

Claude How To 本身就是一个多语言文档型仓库:文档主体是 Markdown,工具脚本是 Python,因此第一步的分析结果自然落在 Markdown 质量工具(markdownlint)+ Python 工具链(Ruff/Bandit/mypy) 上。下面两步就以此为例展开。

第二步:配置 pre-commit 钩子(以本仓库为例)

Claude How To 仓库根目录下的 pre-commit 配置文件 是一份可直接参考的成品。它的关键点如下:

全局 Python 版本锁定

default_language_version:
  python: python3.11

显式锁定钩子使用的 Python 版本,避免不同开发者机器上的版本差异导致同一检查行为不一致。

外部钩子:Ruff、Bandit 与通用检查

repos:
  - repo: https://github.com/astral-sh/ruff-pre-commit
    rev: v0.15.10
    hooks:
      - id: ruff
        name: ruff-lint
        args: [--fix, --exit-non-zero-on-fix]
        types_or: [python, pyi]
        files: ^scripts/
      - id: ruff-format
        name: ruff-format
        types_or: [python, pyi]
        files: ^scripts/

  - repo: https://github.com/PyCQA/bandit
    rev: 1.7.10
    hooks:
      - id: bandit
        name: bandit-security
        args: [-c, scripts/pyproject.toml]
        additional_dependencies: ["bandit[toml]"]
        types: [python]
        files: ^scripts/
        exclude: ^scripts/tests/

三个值得注意的工程细节:

  • files: ^scripts/:Python 检查只作用于 scripts/ 目录,与仓库“文档为主、脚本为辅”的结构匹配,避免无谓开销(呼应“保持执行快速”原则)。
  • args: [--fix, --exit-non-zero-on-fix]:Ruff 先自动修复,修复后仍然失败才以非零码阻断提交——既减少手工操作,又不放行有问题的代码。
  • 配置版本对齐:文件头注释明确提醒,Ruff 的 pin(v0.15.10)必须与 scripts/requirements-dev.txt 中的 ruff>=0.15.10 下限和 CI lint 任务中未锁定的 uv pip install ruff 保持一致。否则会出现“本地 Ruff 重排了文件、CI 新 Ruff 又拒绝”这类双向不一致。这是“尊重现有配置”原则在版本管理上的具体体现。

通用卫生检查来自 pre-commit-hooks 仓库(check-yamlcheck-tomlend-of-file-fixertrailing-whitespacecheck-added-large-files--maxkb=1000)、check-merge-conflict),成本低但能拦住大量低级问题。类型检查则由 mypy 钩子承担,同样指向 scripts/pyproject.toml 中的 [tool.mypy] 配置,并排除了 scripts/tests/

本地钩子:文档质量检查与 CI 互为镜像

该仓库最有特色的一层是 repo: local 的文档质量钩子:

- repo: local
  hooks:
    - id: markdown-lint
      name: markdown-lint
      language: node
      entry: markdownlint
      args: ['--ignore', 'node_modules', '--ignore', '.venv', '--config', '.markdownlint.json']
      types: [markdown]
      additional_dependencies: ['markdownlint-cli']

    - id: cross-references
      name: cross-references
      language: system
      entry: python scripts/check_cross_references.py
      pass_filenames: false
      types: [markdown]

    - id: mermaid
      name: mermaid-syntax
      language: system
      entry: python scripts/check_mermaid.py
      pass_filenames: false
      types: [markdown]

    - id: link-check
      name: link-check
      language: system
      entry: python scripts/check_links.py
      pass_filenames: false
      types: [markdown]

这些检查对应仓库自带的校验脚本 scripts/check_cross_references.pyscripts/check_mermaid.pyscripts/check_links.pyscripts/check_markdown_rendering.py。注释里写明:“Local doc quality hooks (mirrors CI checks — CI is a 2nd pass of these)”——本地钩子是镜像,CI 是第二道兜底。这正是 /setup-ci-cd 文档第 3 步“Mirror pre-commit checks on push/PR”的落地。

此外,配置还为越南语(^vi/.*\.md$)与日语(^ja/.*\.md$)翻译目录单独注册了同构的 lint / cross-references / mermaid / link-check 钩子,保证翻译树与主树执行同等标准。文件中还保留了一段重要注释:EPUB 构建钩子被刻意移除、改为 CI-only,原因是它依赖本地 mmdc 二进制且“没有可用的 arm64 构建”,导致在 arm64 机器上钩子永远无法通过——把平台敏感的构建步骤下沉到 CI,是“尊重现有配置/环境”原则的又一例证

安装与本地验证

按照 CONTRIBUTING.md 的说明安装并激活:

pip install uv
uv venv && source .venv/bin/activate
uv pip install -r scripts/requirements-dev.txt
npm install -g markdownlint-cli
npm install -g @mermaid-js/mermaid-cli
uv pip install pre-commit
pre-commit install

# 验证全量检查
pre-commit run --all-files

第三步:创建 GitHub Actions 工作流

命令文档要求工作流做到四件事:镜像 push/PR 上的 pre-commit 检查、多版本/平台矩阵(如适用)、构建与测试验证、部署步骤(如需).github/workflows/ 目录下的四个文件恰好逐项对应:

工作流 对应命令文档要点
test.yml 镜像 Python 钩子(Ruff/Bandit/mypy)+ 测试矩阵 + 构建验证
docs-check.yml 镜像文档钩子(markdownlint/link/mermaid/cross-references)
pages.yml 部署步骤:构建静态站并部署到 GitHub Pages
release.yml 部署步骤:tag 触发 EPUB 构建并发布 GitHub Release

test.yml:多版本矩阵 + 汇总门禁

test.yml 只在 Python 相关文件变更时触发(paths: scripts/**requirements*.txt 等),并配置了并发取消策略:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

pytest 任务按文档要求的“多版本矩阵”跑三个 Python 版本,fail-fast: false 保证某个版本失败时其余版本仍出结果:

pytest:
  strategy:
    fail-fast: false
    matrix:
      python-version: ['3.10', '3.11', '3.12']

五个任务(pytestlintsecuritytype-checkbuild-epub)与本地钩子逐一对应,其中安全任务将 Bandit 报告上传为产物:

- name: Run Bandit Security Scan
  run: uv run bandit -c scripts/pyproject.toml -r scripts/ --exclude scripts/tests/ -f json -o bandit-report.json

值得学习的是末尾的 summary 任务:它 needs 全部前置任务、if: always() 保证失败时也运行,把每个任务的 result 写入 $GITHUB_STEP_SUMMARY,最后只有 pytestbuild-epub 属于关键门禁(任一失败即 exit 1)——lint、安全扫描的失败会体现在摘要里但不单独硬阻断。这种“分级门禁”的设计让质量信号可见,同时避免次要检查卡死发布。

build-epub 任务则展示了平台矩阵 + 依赖安装的完整形态:按 lang: [en, vi, zh, ja] 四个语言矩阵构建,npm install -g @mermaid-js/mermaid-cli 提供 Mermaid CLI,并通过 puppeteer 无沙箱配置适配 CI 环境:

echo '{"args":["--no-sandbox","--disable-setuid-sandbox"]}' > /tmp/puppeteer-ci.json
uv run scripts/build_epub.py --lang ${{ matrix.lang }} --puppeteer-config /tmp/puppeteer-ci.json

docs-check.yml:文档钩子的云端镜像

docs-check.yml 触发条件是 **.md 或检查脚本变更,四个任务与本地钩子一一对应:markdown-lint(Node 18 + markdownlint-cli,沿用 .markdownlint.json 配置)、link-checkLINK_CHECK_STRICT: "1" 使外部链接检查在 CI 中更严格)、mermaid(安装 Mermaid CLI 后跑 check_mermaid.py)、cross-references。末尾 summary 任务对四个结果做 AND 判定,任一失败即整体失败——文档检查在 CI 中是全量硬门禁。

pages.yml 与 release.yml:部署步骤

  • pages.ymlmain 分支文档/构建脚本变更时构建静态站(scripts/build_website.py)并部署 GitHub Pages。注意点包括:最小权限声明(contents: read / pages: write / id-token: write)、cancel-in-progress: false(部署流水线不做并发取消,防止半成品被中断)、以及对 vendor 资产的 actions/cache 缓存(按 vendor_assets.py 的哈希作 key)。
  • release.ymlv* tag 触发,lang: [en, vi, zh] 矩阵构建 EPUB 后,release 任务用 if: ${{ always() && needs.build.result != 'cancelled' }} 保证部分语言构建失败时仍发布已成功产物,同时防止手动取消时误发布。这是命令文档中“Deployment steps (if needed)”的典型实现。

第四步:验证流水线

按命令文档,验证分三步,结合本仓库的工具链可以具体化:

  1. 本地试跑pre-commit run --all-files,确认所有钩子(含文档钩子)在干净状态通过;
  2. 创建测试 PR:提交一个无关痛痒的改动触发 PR,观察 docs-checktest 两个工作流按 paths 过滤是否正确触发、summary 任务的 Step Summary 是否完整输出;
  3. 确认全绿:检查矩阵各版本、各语言任务的结果,以及产物(覆盖率 XML、Bandit JSON、EPUB)是否成功上传。

对于翻译目录的变更,还要确认对应语言的钩子(如 vietnamese-cross-references)与 CI 检查一致通过——本仓库通过 sync_translations.py 等脚本维护多语言树的一致性,验证时可一并纳入。

小结:把命令文档当作“检查清单”使用

/setup-ci-cd 模板本身只有短短四条步骤,但它的价值在于约束了生成过程:先分析、再本地、后云端、最后验证,且工具选型必须贴合语言生态、必须尊重已有配置、必须保持快速。Claude How To 仓库自身的 pre-commit 配置四个工作流 就是这套方法论的完整样板——本地 repo: local 钩子与 CI 任务互为镜像、paths 过滤减少无效运行、fail-fast: false 保留完整信号、summary 任务分级门禁、平台敏感的构建下沉到 CI。将命令安装为 Skill 后,在目标项目中执行 /setup-ci-cd,即可按同样的骨架生成适配你技术栈的质量门禁,再对照上述真实配置逐项校验即可。

登录后查看全文
热门项目推荐
相关项目推荐