mcpField
A
arc-conventional-commits

arc-conventional-commits

github.com/andysolomon开发144 次安装8 周前更新
代码仓库

关于 arc-conventional-commits

arc-conventional-commits 是一项技能,用于在仓库中配置 Conventional Commits 和 semantic-release。它指导版本管理、可选的提交校验与 CI 设置,并先检查现有工具,破坏性修改须经确认。

主要功能

  1. 01检测现有发布工具
  2. 02配置 semantic-release
  3. 03可选设置 commitlint 和 husky
  4. 04可选创建 GitHub Actions 工作流
  5. 05通过试运行验证

适用场景

  1. 01为仓库添加自动版本管理
  2. 02迁移现有发布工具
  3. 03强制遵循提交消息规范
  4. 04准备 CI 检查和发布工作流

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/andysolomon/arc-skills --skill arc-conventional-commits

安装后在 Claude Code 中输入/arc-conventional-commits确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

evals/
evals.json
evals/files/clean-repo/
package.json
evals/files/monorepo/
package.json
evals/files/monorepo/packages/
.gitkeep
evals/files/standard-version/
.versionrc.json
package.json
references/
conventional-commits-spec.md
scripts/
pre-commit
protect-main.sh

详细介绍

Conventional Commits + Semantic Release

此技能使用 Conventional Commits v1.0.0 规范和 semantic-release,设置由 CI 驱动的自动版本管理。

整个工作流采用对话方式进行——在执行删除现有工具等破坏性更改前,务必先向用户确认。

请按顺序完成以下五个阶段。


阶段 1 — 检测现有版本管理工具

在安装任何内容之前,扫描代码仓库中现有的版本管理基础设施。 这可以避免冲突,并让用户有机会顺利迁移。

使用 Glob 和 Read 检查以下工具:

工具文件 / 模式
semantic-release.releaserc、.releaserc.json、.releaserc.yml、.releaserc.yaml、release.config.js、release.config.cjs
standard-version.versionrc、.versionrc.json、.versionrc.js
changesets.changeset/ 目录
lernalerna.json
release-pleaserelease-please-config.json、.release-please-manifest.json

同时读取 package.json 并检查:

  • devDependencies 中是否包含:semantic-release、standard-version、@changesets/cli、@changesets/changelog-github、lerna、release-please、conventional-changelog-cli、np、publish-please
  • scripts 中是否有键或值包含 version、release 或 publish(忽略 dev、start、build)

向用户汇报检查结果,以摘要列表的形式呈现。例如:

我在此代码仓库中发现以下版本管理工具:

  • standard-version — .versionrc.json、devDependencies 中的 standard-version
  • 发布脚本 — package.json scripts 中的 "release": "standard-version"

是否要先删除这些工具,再设置 semantic-release?

如果没有发现任何内容,告知用户代码仓库中没有现有工具,然后跳到阶段 3。


阶段 2 — 移除现有工具(按需执行)

只有在阶段 1 检测到现有工具且用户确认移除后,才执行此阶段。

针对每个检测到的工具:

  1. 删除配置文件 — 移除阶段 1 中识别出的所有配置文件
  2. 卸载软件包 — 对 devDependencies 中检测到的每个软件包运行 npm uninstall <package>
  3. 清理脚本 — 从 package.json 中移除与版本管理或发布相关的脚本
  4. 移除目录 — 如果检测到 changesets,则删除 .changeset/

移除完成后,确认已清理的内容:

已移除:

  • 已删除 .versionrc.json
  • 已卸载 standard-version
  • 已从 package.json 中移除 "release" 脚本

阶段 3 — 安装 semantic-release

步骤 1:安装核心软件包
npm install --save-dev semantic-release \
  @semantic-release/commit-analyzer \
  @semantic-release/release-notes-generator \
  @semantic-release/changelog \
  @semantic-release/npm \
  @semantic-release/github \
  @semantic-release/git \
  conventional-changelog-conventionalcommits
步骤 2:确定发布分支

检查代码仓库的默认分支:

git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null || git branch --show-current

将结果(通常为 main 或 master)作为发布分支。如不确定,请与用户确认。

步骤 3:创建 .releaserc.json

插件顺序很重要——每个插件都会依次运行,后续插件依赖前面的插件。

{
  "branches": ["main"],
  "plugins": [
    ["@semantic-release/commit-analyzer", {
      "preset": "conventionalcommits"
    }],
    ["@semantic-release/release-notes-generator", {
      "preset": "conventionalcommits"
    }],
    ["@semantic-release/changelog", {
      "changelogFile": "CHANGELOG.md"
    }],
    ["@semantic-release/npm", {
      "npmPublish": false
    }],
    "@semantic-release/github",
    ["@semantic-release/git", {
      "assets": ["CHANGELOG.md", "package.json", "package-lock.json"],
      "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
    }]
  ]
}

调整配置:

  • 如果 package.json 中有 "private": true,则保留 npmPublish: false(上面的默认设置)
  • 如果此软件包应发布到 npm,则设置 npmPublish: true
  • 将 branches 中的 "main" 替换为实际的默认分支名称
步骤 4:添加发布脚本

添加到 package.json 的 scripts 中:

"release": "semantic-release"
步骤 5:询问是否启用提交规范检查

询问用户:

是否要安装 commitlint 和 husky,以强制每次提交都符合 Conventional Commits 格式? 这样可以防止格式错误的提交消息被推送。

如果用户同意:

npm install --save-dev @commitlint/cli @commitlint/config-conventional husky
npx husky init

创建 commitlint.config.js:

export default { extends: ['@commitlint/config-conventional'] };

创建 husky 钩子:

echo 'npx --no -- commitlint --edit $1' > .husky/commit-msg

如果 .husky/ 已存在(由之前的 husky 设置创建),不要运行 npx husky init — 只需在现有钩子旁添加 commit-msg 钩子文件。

第 6 步:询问是否集成 CI

询问用户:

你希望我创建 GitHub Actions 工作流,用于 PR 检查、合并门禁和自动发布吗?

如果是,创建三个工作流文件。将这三个文件中的 main 替换为实际的默认分支。

.github/workflows/release.yml — 合并到 main 后运行 semantic-release
name: Release
on:
  push:
    branches: [main]

permissions:
  contents: write
  issues: write
  pull-requests: write

jobs:
  release:
    name: Release
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4
        with:
          fetch-depth: 0

      - name: Setup Node.js
        uses: actions/setup-node@v4
        with:
          node-version: 'lts/*'

      - name: Install dependencies
        run: npm ci

      - name: Release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
        run: npx semantic-release
.github/workflows/pr.yml — PR 创建或更新时运行检查
name: PR Checks
on:
  pull_request:
    branches: [main]

jobs:
  commitlint:
    name: Validate Commits
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0
      - uses: actions/setup-node@v4
        with:
          node-version: 'lts/*'
      - run: npm ci
      - name: Validate commit messages
        run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose

  lint:
    name: Lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 'lts/*'
      - run: npm ci
      - run: npm run lint --if-present

  test:
    name: Test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 'lts/*'
      - run: npm ci
      - run: npm test --if-present
.github/workflows/merge.yml — 合并门禁(用于分支保护的单一状态检查)

此工作流运行与 pr.yml 相同的检查,但将其作为单个任务运行,生成一个状态检查名称(Merge Gate),可在 GitHub 分支保护设置中将其设为必需项。

name: Merge Gate
on:
  pull_request:
    branches: [main]
    types: [opened, synchronize, reopened]

jobs:
  merge-gate:
    name: Merge Gate
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0

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

      - run: npm ci

      - name: Validate commits
        run: npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose

      - name: Lint
        run: npm run lint --if-present

      - name: Test
        run: npm test --if-present

提醒用户:

  • GitHub Actions 会自动提供 GITHUB_TOKEN
  • 仅在发布到 npm 时才需要 NPM_TOKEN——用户可以在仓库的 Settings > Secrets 中设置
  • Merge Gate 任务名称就是用户要在分支保护中设为必需状态检查的名称
第 7 步:检查是否为 monorepo

如果 package.json 中包含 workspaces 字段,或存在 lerna.json,请提醒用户:

此仓库似乎是一个 monorepo。semantic-release 开箱即用的 monorepo 支持有限。可以考虑使用 semantic-release-monorepo 或 multi-semantic-release 来为各个包分别管理版本。


第 4 阶段 — 验证

安装后:

  1. 试运行(如果仓库有提交):

    npx semantic-release --dry-run --no-ci
    

    此操作会验证配置,但不会发布任何内容。将输出内容分享给用户。

  2. 总结 — 告知用户已完成的设置:

    • 使用 Conventional Commits 预设的 semantic-release
    • 启用的插件
    • 是否添加了 commitlint/husky 强制校验
    • 是否创建了 CI 工作流
  3. 提交示例 — 向用户展示如何立即使用该系统:

    fix: resolve null pointer in user lookup
    → triggers PATCH bump (e.g., 1.0.0 → 1.0.1)
    
    feat(auth): add OAuth2 support
    → triggers MINOR bump (e.g., 1.0.1 → 1.1.0)
    
    feat!: redesign the public API
    → triggers MAJOR bump (e.g., 1.1.0 → 2.0.0)
    
    chore: update dev dependencies
    → no version bump, appears in changelog
    

第 5 阶段 — 分支保护

采用 Conventional Commits 时,最好通过分支和 PR 提交所有更改。 此阶段会设置三层保护,防止直接向 main 提交。

第 1 步:安装 husky 提交前钩子

此钩子会阻止在终端中向 main 执行 git commit。

npm install --save-dev husky
npx husky init

将 .husky/pre-commit 的内容替换为:

#!/bin/sh
branch=$(git rev-parse --abbrev-ref HEAD)
if [ "$branch" = "main" ] || [ "$branch" = "master" ]; then
  echo ""
  echo "  Direct commits to $branch are not allowed."
  echo "  Create a feature branch and open a PR instead:"
  echo ""
  echo "    git checkout -b feat/your-feature"
  echo ""
  exit 1
fi

如果 .husky/ 已存在,请勿运行 npx husky init——只需替换 pre-commit 文件。 如果存在 .husky/commit-msg 钩子(来自第 3 阶段第 5 步),请保留该文件。

第 2 步:安装 Claude Code PreToolUse 钩子

这会阻止 Claude 在 main 上暂存或提交更改。它会提示用户批准,因此用户确有需要时可以覆盖限制。

在目标仓库中创建 .claude/hooks/protect-main.sh:

#!/bin/bash
INPUT=$(cat)
COMMAND=$(echo "$INPUT" | jq -r '.tool_input.command // empty')

if ! echo "$COMMAND" | grep -qE "^git (add|commit)"; then
  exit 0
fi

CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null)

if [ "$CURRENT_BRANCH" = "main" ] || [ "$CURRENT_BRANCH" = "master" ]; then
  if echo "$COMMAND" | grep -qE "^git add"; then
    jq -n '{
      hookSpecificOutput: {
        hookEventName: "PreToolUse",
        permissionDecision: "ask",
        permissionDecisionReason: "You are about to stage files on main. Create a feature branch instead."
      }
    }'
  else
    jq -n '{
      hookSpecificOutput: {
        hookEventName: "PreToolUse",
        permissionDecision: "ask",
        permissionDecisionReason: "You are about to commit directly to main. Create a feature branch instead."
      }
    }'
  fi
  exit 0
fi

exit 0

将其设为可执行文件:

chmod +x .claude/hooks/protect-main.sh

然后创建或更新 .claude/settings.json,以注册此钩子。如果该文件已存在,请将 hooks 键合并到现有配置中——不要覆盖其他设置。

{
  "hooks": {
    "PreToolUse": [
      {
        "matcher": "Bash",
        "hooks": [
          {
            "type": "command",
            "command": ".claude/hooks/protect-main.sh"
          }
        ]
      }
    ]
  }
}
第 3 步:配置 GitHub 分支保护

询问用户:

你希望我在 main 上设置 GitHub 分支保护规则吗? 这需要管理员权限,并会在服务器层面强制要求使用 PR。

如果是,使用 GitHub CLI:

gh api repos/{owner}/{repo}/branches/main/protection \
  -X PUT \
  -H "Accept: application/vnd.github+json" \
  -f "required_pull_request_reviews[dismiss_stale_reviews]=false" \
  -f "required_pull_request_reviews[require_code_owner_reviews]=false" \
  -F "required_pull_request_reviews[required_approving_review_count]=1" \
  -F "enforce_admins=true" \
  -f "restrictions=null" \
  -f "required_status_checks=null"

将 {owner}/{repo} 替换为 gh repo view --json owner,name 返回的实际值。

如果仓库有 CI 工作流(来自第 3 阶段第 6 步),请将 Merge Gate 任务设为必需状态检查,这样只有所有检查都通过后 PR 才能合并:

gh api repos/{owner}/{repo}/branches/main/protection \
  -X PUT \
  -H "Accept: application/vnd.github+json" \
  -f "required_pull_request_reviews[dismiss_stale_reviews]=false" \
  -F "required_pull_request_reviews[required_approving_review_count]=1" \
  -F "enforce_admins=true" \
  -f "restrictions=null" \
  -f "required_status_checks[strict]=true" \
  -f "required_status_checks[contexts][]=Merge Gate"

提醒用户:

  • enforce_admins: true 表示即使仓库管理员也无法绕过这些规则
  • Merge Gate 是 merge.yml 中的任务名称——它会验证提交、运行 lint 并运行测试
  • 用户之后可以在 GitHub 仓库的 Settings > Branches 中调整这些设置

快速参考 — 提交格式

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]
前缀版本升级示例
fix:PATCH (0.0.x)fix: prevent race condition in auth flow
feat:MINOR (0.x.0)feat(api): add pagination to /users endpoint
feat!:MAJOR (x.0.0)feat!: drop support for Node 14
BREAKING CHANGE: 页脚MAJOR (x.0.0)在页脚中包含 BREAKING CHANGE: <desc> 的任意类型

有效类型: feat、fix、build、chore、ci、docs、style、refactor、perf、test

默认情况下,只有 feat 和 fix 会触发版本升级。其他类型会出现在变更日志中,但不会升级版本。


回答规范相关问题

有关 Conventional Commits 规范的详细问题——作用域规则、多行正文、页脚语法和边缘情况——请阅读此技能目录中的 references/conventional-commits-spec.md。其中包含完整的 v1.0.0 规范,包括全部 16 条规则和示例。

评论

支持 Markdown