semantic-release 是一个自动化版本控制和发布管理的工具,主要用于 JavaScript 项目。它通过分析提交信息来确定版本号的更新,并自动生成发布日志、创建 Git 标签和发布到 npm 等平台。
- 重新整理几种情况工作流及其典型配置,并在 GitHub 上验证,整理成一个 semantic-release 的教学 repo 发布(semantic-release-workflows),附带示例 ➕ 2025-07-10
- 源码或相关构建文件中是否有地方需要更新版本号为将语义版本号
- 典型的如有的 python 工具的主脚本顶端会有
__version__ = "1.0.0"这种字样 - 有的项目配置文件中有对项目版本号的定义,如 CMakeLists.txt, conanfile.py 等
- 典型的如有的 python 工具的主脚本顶端会有
- 发布的目标是 GitHub/GitLab Release,还是其他第三方包管理平台(如)
- 是否构建复杂(是单平台构建、多平台构建、跨平台构建等)
- 如果需要将构建工作放在 semantic-release/exec 执行,单平台构建的话,直接写个构建脚本即可
- 否则,流程得变为 semantic-release(dry-run)-> update and build -> sematic-release,后续两步根据语义版本号是否更新进行(条件写法参考 https://github.com/cycjimmy/semantic-release-action/blob/main/.github/workflows/release.yml )
- 如果需要将构建工作放在 semantic-release/exec 执行,单平台构建的话,直接写个构建脚本即可
- 源码或相关构建文件中是否有地方需要更新版本号为将语义版本号
验证 semantic-release dry-run + 条件构建方案
多平台构建场景下,先 dry-run 获取版本号再条件触发构建的方案尚未实际验证。 - 或者另一种方案, 设置 release 分支一个
.releaserc.yml, tag 另一个.releaserc.tag.yml, …
有些乱… 感觉可以参考参考其他发布多平台工具的仓库的做法 (实际基本非 nodejs 仓库都会自己构建发布脚本)
关于 semantic-release 在完整 ci 链中的一些思考:
感觉 semantic-release 官方还是有点太固执了,连一个指定配置文件的 —config 参数的功能都不愿意加…
- 似乎 —extends 有类似的功能 (https://github.com/semantic-release/semantic-release/issues/1592#issuecomment-705321266 , )
emm… 散了吧, semantic-release 只是对 npm 包项目适配得比较好
工作流
基于 semantic-release 的代码开发 CI 工作流:
- dev 分支开发
- 代码 push/merge 到 release 分支(如 main,master,release/xxx)
- semantic-release 检索 commit,判断是否需要更新版本,如是,更新 CHANGLOG.md 以及其他可能需要改动的地方(如源码或配置文件中定义的版本号),并将改动 push 到 release 分支,触发下一步,否则,结束
- semantic-release-bot 推送代码的同时会打一个 tag,在 tag 的 ci 中触发 Release 版本的构建,并由 semantic-release 发布(通过
@semantic-release/github或@semantic-release/gitlab)
项目一般要配置两个文件: Semantic-Release 配置文件(一般是 .releaserc.yml) 和 CI 配置文件。
示例(非 nodejs 项目)
示例:winguake (笔者的一个小项目),其两个配置文件分别为:
branches:
- main
- master
plugins:
- "@semantic-release/commit-analyzer"
- "@semantic-release/release-notes-generator"
- - "@semantic-release/changelog"
- changelogFile: CHANGELOG.md
- - "@semantic-release/exec"
- prepareCmd: |
powershell -File .\.prepare.ps1 ${nextRelease.version}
- - "@semantic-release/git"
- assets:
- CHANGELOG.md
- winguake.ahk
message: |-
chore(release): ${nextRelease.version} [skip ci]
${nextRelease.notes}
- - "@semantic-release/github"
- assets:
- bin/winguake_*.exe
- winguake.ahk
name: Build and Release winguake
on:
push:
branches:
- main
- master
workflow_dispatch:
permissions:
contents: write
jobs:
build:
runs-on: windows-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0 # semantic-release 需要完整的 git 历史
# If semantic-release decides to release, it will build package by running .prepare.ps1 in plugin @semantic-release/exec.
- name: Semantic Release
uses: cycjimmy/semantic-release-action@v4
with:
# semantic-release 需额外安装的插件
extra_plugins: |
@semantic-release/changelog
@semantic-release/git
@semantic-release/exec
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}CI 很简单,就只有执行 semantic-release 一个 action,里面做了什么可在 .releaserc.yml 中查看。
- 前两个插件
@semantic-release/commit-analyzer和@semantic-release/release-notes-generator是基本固定的,用于分析语义版本号以及改动汇总 @semantic-release/clanglog用于生成或更新 changlog,可选@semantic-release/exec执行用于自定义命令,这里执行的是自己定义的构建脚本,里面包含了包的构建过程- 之所以构建过程放在这里,是因为需要用到前面分析得到的语义版本号, 需要将该版本号更新到源码中,然后才能执行构建
- 如果不需要对源码或需包含进发行包的文件进行修改,则可将构建工作放在 semantic-release action 之前
- 因为该项目发布的目标是 GitHub Release 页面,需要在 semantic-release 的
@semantic-release/github执行前就构筑好发行包,因此只能将构建工作放在 exec 插件中- 如果发布的目标不是 GitHub Release,而是第三方包管理库(如 python 包,nodejs 包),则构建和发布完全可以放 semantic-release action 之后,此时 GitHub Release 页面仅会有源码压缩包。
- 之所以构建过程放在这里,是因为需要用到前面分析得到的语义版本号, 需要将该版本号更新到源码中,然后才能执行构建