semantic-release:把版本号从人的情绪里解放出来
该项目围绕「Fully automated version management and package publishing. semantic-release Fully automated version management and package publishing semantic-release** automates the whole package release workflow including: determining the next version number, generating the release notes, and publishing the package.」构建,适用于实际场景的开源实践,提供可复用的工具链与集成方式。
秒懂
- 它是什么?
- semantic-release 用提交信息自动决定下一个版本号、生成 release notes 并发布包。它把发布流程从手动操作变成 CI 里的一步,但代价是你必须接受一套严格的提交规范。
- 适合谁用?
- 如果你的团队已经用 conventional commits,或者愿意强制推行,并且 CI 环境可控,semantic-release 能省掉每次发版的判断和操作。它适合 npm 包、库作者,也适合多分支发布流程复杂的项目。
- 能商用吗?
- 可以。MIT 是宽松许可证:你可以使用、修改并销售基于它的软件,只需保留版权和许可证声明。
- 还在维护吗?
- 在维护。仓库最近一次提交在 1 天前。
- 用什么语言写的?
- 主要是 JavaScript(依据 GitHub 的语言统计)。
以上回答依据项目的 GitHub 数据(最近同步于 2026年9月14日)和我们的分析,不构成法律意见。
开源项目深度解析
版本号不该由心情决定
大多数项目发版时,版本号由维护者拍脑袋。今天高兴就升 minor,急着修 bug 就发 patch,大改版拖到不能再拖才升 major。semantic-release 要消除这种随意性。它根据提交信息自动决定下一个版本号,并严格按照 SemVer 规范。README 里明确说,这切断了人的情绪和版本号之间的直接联系。它面向的是那些发布频率高、或者发布流程容易出错的库作者。你不需要再记着上次发到哪了,也不需要翻 changelog 决定这次是 1.2.3 还是 2.0.0。
提交信息就是版本决策的输入
semantic-release 的核心机制是解析提交信息。默认使用 Angular Commit Message Conventions。一条 fix 开头的提交会触发 patch 版本,feat 触发 minor,而提交信息里带 BREAKING CHANGE 标记的会触发 major。README 给的例子很具体:fix(pencil): stop graphite breaking 对应 Patch Release,feat(pencil): add 'graphiteWidth' option 对应 Feature Release,而 perf 提交加上 BREAKING CHANGE 脚注则对应 Breaking Release。注意 BREAKING CHANGE 必须放在提交信息的 footer,位置错了就不会触发 major。这个设计把版本决策从人脑转移到了 git 历史里。代价是提交信息必须规范,否则版本号会错。
CI 是它唯一的执行环境
semantic-release 设计成在 CI 上运行,而不是本地。每次 push 到 release 分支,CI 构建成功后就执行 semantic-release 命令。这样没人能跳过检查直接发版。README 强调,它必须在 release 分支上每次成功构建后运行。这意味着本地跑 semantic-release 是反模式,因为本地环境缺少 CI 的认证凭据和干净的 git 状态。release 分支可以是 master、main,也可以是 next 或 beta,这给预发布和分发渠道留了空间。整个流程是:push 触发 CI,CI 跑测试,测试过了再跑 semantic-release,它决定版本号、生成 release notes、发布。
安装与配置:从 package.json 开始
安装 semantic-release 作为开发依赖,然后在 package.json 里加一个 release 配置块。README 没有给出完整的安装命令,但项目是 npm 包,所以 npm install --save-dev semantic-release 是标准做法。配置可以放在 package.json 的 release 键里,也可以独立成 .releaserc 文件。核心配置项包括 branches 指定 release 分支,plugins 指定要用的插件。默认配置会用到 @semantic-release/commit-analyzer 来分析提交,@semantic-release/release-notes-generator 生成 changelog,以及 @semantic-release/npm 发布到 npm。CI 里需要设置 NPM_TOKEN 或类似的认证变量,因为发布步骤需要权限。README 提到支持 npm provenance,用 GitHub Actions 的签名 attestation 增强供应链安全,这需要额外配置。
发布步骤:不是一步到位
执行 semantic-release 时,它按顺序跑多个步骤。README 列出的第一步是 Verify Conditions,检查所有发布前提是否满足。后面还有生成 release notes、发布包等步骤。每个步骤由对应插件完成,插件可以替换。这套流水线设计意味着你可以插入自定义插件,比如在发布前跑额外检查,或者把包发布到 npm 之外的 registry。但步骤越多,失败点越多。如果 Verify Conditions 失败,整个发布就中止,不会产生部分发布。这是好事,但也意味着你必须把所有条件都配置对。
限制:提交规范是硬门槛
semantic-release 最大的限制是它依赖提交信息。如果团队不遵守 Angular 规范,或者历史提交混乱,它就会产生错误的版本号。README 建议用 commitizen 或 commitlint 来强制规范,但这又增加了一层工具链。另一个限制是它不适合所有语言和包管理器。虽然 README 说通过插件支持任何包管理器和语言,但实际配置 npm 之外的发布需要额外插件,比如 @semantic-release/github 或 @semantic-release/exec。如果你的项目不是 JavaScript 生态,安装和配置成本会上升。还有一个场景它不适合:发布需要人工审批的流程。semantic-release 设计成全自动,没有内置的审批环节。
替代方案:自己写脚本 vs 用 semantic-release
不采用 semantic-release 的团队通常自己写发布脚本,或者用 GitHub Actions 的 release 工作流。手动脚本的差异在于:你仍然需要自己决定版本号,只是把发布动作自动化了。semantic-release 把版本决策也自动化了,这是本质区别。另一个替代是 conventional-changelog-cli 加 standard-version,后者根据 conventional commits 生成 changelog 和 tag,但不会自动发布包。standard-version 在本地运行,而 semantic-release 在 CI 运行,这决定了谁对发布有控制权。如果你的团队不想把版本号交给提交信息,standard-version 或手动脚本更合适。
维护成本与许可证
semantic-release 采用 MIT 许可证,可以自由使用和修改。它本身是 JavaScript 项目,活跃维护,最近发布了 v25.0.9 和 v26.0.0-beta.1。升级成本主要来自配置兼容性,因为插件和核心包的版本需要匹配。如果你用了自定义插件,升级时可能需要调整。另外,semantic-release 的配置本身也要维护,比如 branches 列表和插件顺序。文档在 semantic-release.org,有 recipes 涵盖 CI 配置、发布工作流等。长期来看,最大的维护成本不是代码,而是让团队持续遵守提交规范。一旦规范松懈,版本号就会失真。
编辑结论
如果你的团队已经用 conventional commits,或者愿意强制推行,并且 CI 环境可控,semantic-release 能省掉每次发版的判断和操作。它适合 npm 包、库作者,也适合多分支发布流程复杂的项目。不适合还在手工写提交信息、或者发布流程需要人工审批的团队。采用前先验证三件事:CI 是否能稳定运行 semantic-release 命令,npm 或其他 registry 的认证凭据是否只存在于 CI 环境,以及提交规范是否能被 commitlint 这类工具强制。如果这三条都满足,再考虑引入。它把版本号的决策权交给了提交信息,这既是解放,也是约束。
社区笔记