mcpField
S
setup-semantic-release

setup-semantic-release

github.com/antjanus开发274 次安装1 周前更新
代码仓库

关于 setup-semantic-release

为 Node.js 仓库配置发布流水线的技能,组合 Conventional Commits、commitlint、Husky 和 semantic-release。涵盖提交校验、版本管理、变更日志、GitHub 发布及 Actions 工作流,并检查是否已有冲突的发布配置。

主要功能

  1. 01配置 Conventional Commits 校验
  2. 02设置 Husky 提交钩子
  3. 03自动管理语义化版本
  4. 04生成并提交变更日志
  5. 05创建 GitHub Actions 发布工作流
  6. 06检查冲突的发布工具配置

适用场景

  1. 01为 Node.js 仓库添加自动发布
  2. 02在提交前拒绝格式错误的提交主题
  3. 03根据提交生成变更日志
  4. 04配置 GitHub Actions 发布自动化

安装

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

$npx skills add https://github.com/antjanus/skillbox --skill setup-semantic-release

安装后在 Claude Code 中输入/setup-semantic-release确认已加载。

附带文件references/EVAL.mdreferences/REFERENCE.md

详细介绍

设置 Semantic Release 和 Conventional Commits

概述

配置端到端的自动版本管理:Conventional Commits → commitlint → husky → semantic-release。版本号、CHANGELOG.md、Git 标签和 GitHub 发布均根据提交消息生成,因此人工需要填写的唯一发布信息就是提交主题。在编写提交时强制执行格式,其余流程便可自动完成。

如果仓库已有 .releaserc*、使用了其他发布工具(changesets、release-it、standard-version),或没有 package.json,请停止并说明情况——在现有发布流水线之上再叠加一条,会产生重复标签和重复的变更日志条目。

前置条件:package.json、GitHub 远程仓库、Node ≥22.14——或 24.x 系列中的 ≥24.10(这是 semantic-release@^25 的最低引擎版本要求;该版本不再支持 Node 20/21/23;@commitlint/*@^21 需要 ≥22.12)——以及 GitHub Actions。

设置工作流

阶段 1:安装
npm install --save-dev \
  @commitlint/cli@^21.0.0 @commitlint/config-conventional@^21.0.0 \
  semantic-release@^25.0.0 @semantic-release/changelog@^6.0.0 \
  @semantic-release/git@^10.0.0 husky@^9.0.0
软件包用途
@commitlint/cli + config-conventional根据 Conventional Commits 规则验证提交消息
semantic-release自动处理版本升级、变更日志和发布
@semantic-release/changelog生成/更新 CHANGELOG.md
@semantic-release/git将发布产物提交回仓库
husky管理 Git 钩子

检查:上面列出的每个软件包都出现在 devDependencies 中,并且 npm install 以 0 退出。

阶段 2:Commitlint

创建 commitlint.config.js——当 package.json 不包含 "type": "module" 时,使用 module.exports = {...},而不是 export default:

export default {
  extends: ['@commitlint/config-conventional'],
  rules: {
    'type-enum': [2, 'always', [
      'feat', 'fix', 'docs', 'style', 'refactor',
      'perf', 'test', 'build', 'ci', 'chore', 'revert',
    ]],
    'subject-case': [2, 'always', 'lower-case'],
    'header-max-length': [2, 'always', 100],
    'body-max-line-length': [0], // disable — conflicts with semantic-release notes
  },
};

检查:根目录存在 commitlint.config.js,且其模块语法与 package.json 中的 "type" 相匹配。

阶段 3:Semantic-release

创建 .releaserc.json。插件顺序就是执行顺序,且 branches 必须指定仓库实际使用的默认分支:

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

预发布版本和多分支配置请参阅 references/REFERENCE.md。

检查:根目录存在 .releaserc.json,branches 指定默认分支,且插件顺序为 analyzer → notes-generator → changelog → git → github。

阶段 4:Husky 钩子
npx husky init                                                # creates .husky/, adds "prepare": "husky"
echo 'npx --no -- commitlint --edit $1' > .husky/commit-msg    # validate every commit message

根据项目自身的 package.json 脚本选择提交前检查,无需询问——按顺序采用第一个匹配项:存在 lint 和 test → npm run lint && npm test;否则选 test;再否则选 lint;最后选 build。

echo 'npm run lint && npm test' > .husky/pre-commit   # substitute the matched command

如果这些脚本都不存在,运行 rm .husky/pre-commit——钩子运行不存在的脚本会导致每次提交都失败,而空钩子则会掩盖实际上没有任何检查这一事实。

确认 package.json 脚本中已添加 "prepare": "husky";如果 husky init 没有添加,就手动补上。它会在每次 npm install 时重新安装钩子;没有它,新克隆的仓库提交时将完全没有验证。

检查:.husky/commit-msg 包含 commitlint 命令,.husky/pre-commit 已设置或删除,并且 package.json 脚本中包含 "prepare": "husky"。

阶段 5:初始 CHANGELOG
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

Semantic-release 会将每次发布的内容添加到此标题上方。

检查:根目录存在 CHANGELOG.md。

阶段 6:CI 工作流

创建 .github/workflows/release.yml:

name: Release
on:
  push:
    branches: [main]
permissions:
  contents: write
  issues: write
  pull-requests: write
jobs:
  release:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
        with:
          fetch-depth: 0          # required — semantic-release needs full history
      - uses: actions/setup-node@v4
        with:
          node-version: 'lts/*'
      - run: npm ci
      - run: npx semantic-release
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          NPM_TOKEN: ${{ secrets.NPM_TOKEN }}   # drop unless you added @semantic-release/npm

Actions 会自动提供 GITHUB_TOKEN。如果默认分支不是 main,请同时更新此处和 .releaserc.json 中的 branches。

检查:存在 .github/workflows/release.yml,其中的 branches 与 .releaserc.json 相匹配,并且只有在插件列表中包含 @semantic-release/npm 时才设置 NPM_TOKEN。

快速参考

提交类型 → 发布版本:

提交发布版本
feat: …次要版本
fix: …补丁版本
feat!: … 或 BREAKING CHANGE: 页脚主要版本
docs style refactor perf test build ci chore revert无

创建: commitlint.config.js · .releaserc.json · .husky/commit-msg · .husky/pre-commit(或删除)· CHANGELOG.md · .github/workflows/release.yml,以及 package.json 中的 devDependencies 和 prepare 脚本。

冒烟测试: echo "feat: test" | npx commitlint 以状态码 0 退出;echo "bad" | npx commitlint 以非零状态码退出。

示例

✅ 可以顺利触发发布的主题——类型前缀、可选范围、小写:

feat(auth): add OAuth login          # minor bump
fix(api): handle null response       # patch bump
feat!: drop the v1 endpoints         # major bump

❌ 会被拒绝,或会发布功能却不生成任何版本的主题:

updated auth stuff        # no type prefix — commitlint rejects the commit
feat: Add OAuth login     # capitalized — the subject-case rule rejects it
chore: add OAuth login    # accepted, but chore never releases; the feature ships unversioned

✅ 在页脚声明破坏性变更,以便生成的说明解释该变更:

feat(api): add pagination

Adds offset/limit to all list endpoints.

BREAKING CHANGE: removed `page` in favor of `offset`

✅ commitlint.config.js 语法与包的模块系统匹配:

// package.json has no "type": "module"
module.exports = { extends: ['@commitlint/config-conventional'] };

❌ 同一个包中的同一个文件——commitlint 在加载配置时抛出错误,导致每次提交都会在任何规则运行前失败:

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

注意事项

  • 显式的 plugins 数组会替换默认项,而不是扩展默认项。 semantic-release 的默认列表包含 @semantic-release/npm;Phase 3 配置省略了它,因此不会向 npm 发布任何内容。如果包需要发布,请在 "@semantic-release/github" 前添加 "@semantic-release/npm"——否则请从工作流中移除 NPM_TOKEN,因为它不会发挥作用。(文档)
  • @semantic-release/changelog 必须位于 @semantic-release/git 之前。 如果顺序颠倒,git 插件会提交尚未写入的 CHANGELOG.md。
  • body-max-line-length: [0] 是有意设置的,并非疏忽。 semantic-release 会将完整的发布说明写入它自己的发布提交正文,这会超出默认的 100 字符限制,导致发布提交无法通过自身的钩子检查。
  • subject-case: lower-case 会拒绝首字母大写的主题。 feat: Add feature 会失败;feat: add feature 会通过。这是最常见的“但我的消息看起来没问题”式拒绝。
  • CI 中必须设置 fetch-depth: 0。 Actions 默认会浅克隆,导致 semantic-release 无法获取标签历史记录——并因 ENOGITHEAD 或 EGITNOBRANCH 而失败。
  • 在 git 插件的 message 中加入 [skip ci] 可避免无限循环。 发布提交会进入发布分支,否则会再次触发工作流。
  • 让 commitlint.config.js 与包的模块系统匹配——参见最后一组示例;不匹配会导致每次提交都在任何规则运行前失败。

深入参考

预发布分支配置和故障排查(husky 钩子未运行、重复的变更日志条目、CI 循环、ENOGITHEAD)位于 references/REFERENCE.md 中——当某个阶段的 Check 行失败时再加载,不要预先加载。

参考资料

Conventional Commits · SemVer · semantic-release · commitlint · Husky。当设置跨越多个时段时,可与 track-session 搭配使用。

评论

支持 Markdown