- 开发工具
- CI/CD
- DevOps
【免费下载链接】release-please
generate release PRs based on the conventionalcommits.org spec
导读:本文以本仓库 README.md 为核心骨架,系统讲解 release-please 的核心工作机制——解析 git 历史中的 Conventional Commits 提交、持续维护"发布 PR(Release PR)",并在合并后自动更新 CHANGELOG、打标签、创建 GitHub Release。你将掌握提交规范写法、
Release-As强制指定版本、BEGIN_COMMIT_OVERRIDE修正发布说明、排障三步法,以及全部受支持的 release type(语言/框架策略)与 CLI 配置方式,并深入源码层理解其版本推导逻辑。
什么是 Release PR?
与"每有代码合并到默认分支就立即发布"的做法不同,release-please 采用持续维护发布 PR的模式:它会在目标分支上创建一个(或多个)专门用于发布的 Pull Request,并在后续有新工作被合并时自动保持该 PR 与最新代码同步更新。
当你准备好发布某个版本时,只需要合并这个发布 PR即可。发布 PR 对 squash-merge 和普通 merge commit 两种合并方式都兼容。
合并发布 PR 之后,release-please 会自动执行以下三步:
- 更新 changelog 文件(例如
CHANGELOG.md),以及其他与语言相关的版本文件(例如 Node.js 项目的package.json); - 为合并提交打上版本号标签(git tag);
- 基于该标签创建 GitHub Release。
从源码看,这三步对应的职责被拆分为:buildReleasePullRequest负责生成候选发布 PR 的内容(src/strategies/base.ts),buildRelease/buildReleases负责在 PR 合并后根据 PR 标题、分支名与 PR body 还原出候选 Release(src/strategies/base.ts),最终由github-release命令把 Release 落到 GitHub 上。
发布 PR 的状态标签
你可以通过发布 PR 上的状态标签(label)判断它处于生命周期的哪个阶段:
| 标签 | 含义 |
|---|---|
autorelease: pending | 发布 PR 的初始状态,即合并之前 |
autorelease: tagged | 发布 PR 已被合并,且版本已在 GitHub 上打好标签 |
autorelease: snapshot | 快照版本号提升时的特殊状态 |
autorelease: published | 已基于该发布 PR 发布了 GitHub Release(release-please 不会自动添加此标签,但官方建议发布工具链以此作为约定) |
提交信息该怎么写?
release-please 假定你正在使用Conventional Commits 规范。需要重点记住的前缀有三类,它们与 SemVer 的对应关系如下:
| 提交前缀 | 含义 | 对应的版本号变动 |
|---|---|---|
fix: | 缺陷修复 | patch(如1.0.0 → 1.0.1) |
feat: | 新功能 | minor(如1.0.1 → 1.1.0) |
feat!:、fix!:、refactor!:等(带!) | 破坏性变更(breaking change) | major(如1.1.0 → 2.0.0) |
这套映射关系在源码中可直接验证:DefaultVersioningStrategy.determineReleaseType会遍历提交,统计breaking(破坏性)与feat/feature(新功能)提交的数量,再决定采用MajorVersionUpdate、MinorVersionUpdate还是PatchVersionUpdate(src/versioning-strategies/default.ts,三种更新器定义在 src/versioning-strategy.ts)。其中"breaking"标记由解析器根据BREAKING CHANGEnote 或!标记识别(src/commit.ts)。
建议使用 squash-merge 保持线性历史
官方强烈推荐在合并 PR 时使用 squash-merge,线性 git 历史会带来以下好处:
- 易于追踪历史:提交按合并时间排序,不会在不同 PR 之间交错混杂;
- 便于定位与回滚 bug:
git bisect能更有效地找出引入 bug 的那次变更; - 更好地控制 changelog:合并 PR 时,PR 内部那些"在 PR 语境下有意义、但在主分支上毫无意义"的提交信息(例如先
feat: introduce feature A后fix: some bugfix)会被收敛,避免把与主分支发布无关的修复写进发布说明; - 保持主分支干净:如果采用 red/green 开发(提交 A 写一个失败测试、提交 B 修复),直接 merge 或 rebase-merge 会在主分支上留下测试不通过的中间状态。
一个提交里包含多个 fix/feat 怎么办?
release-please 允许在单个提交中表达多次变更,方法是使用 footer(脚注)块:
feat: adds v4 UUID to crypto This adds support for v4 UUIDs to the library. fix(utils): unicode no longer throws exception PiperOrigin-RevId: 345559154 BREAKING-CHANGE: encode method no longer throws. Source-Link: googleapis/googleapis@5e0dcb2 feat(utils): update encode to support unicode PiperOrigin-RevId: 345559182 Source-Link: googleapis/googleapis@e5eef86上面这条提交信息最终会被解析出以下内容:
- 一条"adds v4 UUID to crypto"的 feature 条目;
- 一条"unicode no longer throws exception"的 fix 条目,并附带它是破坏性变更的说明;
- 一条"update encode to support unicode"的 feature 条目。
重要:额外的提交消息必须附加在提交信息的底部。
这一机制在 src/commit.ts 中有完整实现:解析器先把提交信息解析成 AST,再通过toConventionalChangelogFormat将 AST 转换成 conventional-changelog 格式,其中会把形如fix(utils): ...的 footer 递归地再解析为独立提交(src/commit.ts);splitMessages则负责把单个 commit message 拆分为多个消息(src/commit.ts)。
如何强制指定版本号?
当主分支上的某个提交在其commit body中包含Release-As: x.x.x(不区分大小写)时,release-please 会为该指定版本打开一个新的发布 PR。
空提交示例:
git commit --allow-empty -m "chore: release 2.0.0" -m "Release-As: 2.0.0"生成的提交信息如下:
chore: release 2.0.0 Release-As: 2.0.0在源码层面,Release-As被解析为一条标题为RELEASE AS的 note(src/commit.ts);buildNewVersion会优先查找带RELEASE ASnote 的提交并直接用其文本构造版本号(src/strategies/base.ts);DefaultVersioningStrategy同样会在遍历提交时优先命中RELEASE AS并返回CustomVersionUpdate(src/versioning-strategies/default.ts)。此外,CLI 的release-pr命令也提供了--release-as参数用于在命令行直接覆盖语义化推导出的版本号(见 docs/cli.md)。
如何修正已合并 PR 的发布说明?
如果你已经合并了一个 PR,并想修改用于生成该提交发布说明的 commit message,可以编辑已合并 PR 的 body,加入如下格式的覆盖段:
BEGIN_COMMIT_OVERRIDE feat: add ability to override merged commit message fix: another message chore: a third message END_COMMIT_OVERRIDE下次运行 release-please 时,它会优先使用覆盖段中的内容作为该提交的 commit message,而不是合并时实际使用的 commit message。
重要:此功能不适用于普通 merge(plain merge),因为 release-please 无法确定该 override 应应用到哪个(哪些)提交。建议改用 squash-merge(见上文"建议使用 squash-merge 保持线性历史"一节)。
该功能在 src/commit.ts 的preprocessCommitMessage中实现:如果提交关联了 PR,则会截取 PR body 中BEGIN_COMMIT_OVERRIDE与END_COMMIT_OVERRIDE之间的文本作为待解析的提交信息;没有覆盖段时才回退到原始的 commit message。仓库测试夹具 test/fixtures/commit-messages/meta.txt 中也有多提交、带分隔符等场景的样例可对照参考。
Release Please 没有创建发布 PR,为什么?
如果 release-please 迟迟没有创建发布 PR,请按下述三个步骤排查。
步骤 1:确认存在"可发布单元(releasable units)"
release-please 只有在注意到默认分支自上次发布以来包含"可发布单元"时,才会创建发布 PR。可发布单元是指带有以下前缀之一的提交:feat、fix、deps。(chore或build提交不是可发布单元。)
部分语言有自己特定的可发布单元配置,例如在 Java 和 Python 中,docs也是可发布单元前缀。changelog 默认分组与隐藏规则可在 src/util/filter-commits.ts 中看到:feat/fix/perf/revert默认显示,而chore/docs/style/refactor/test/build/ci默认隐藏(hidden: true),除非它们携带 BREAKING CHANGE note(src/util/filter-commits.ts)。
步骤 2:确认旧的 PR 上没有残留autorelease: pending或autorelease: triggered标签
检查现有 PR 是否带有autorelease: pending或autorelease: triggered标签。由于 GitHub API 失败,上一次发布时标签可能没有被正确移除,release-please 会误以为上一次发布仍然 pending。如果你确信没有未完成的发布,请手动移除autorelease: pending或autorelease: triggered标签。
对于 GitHub Application 用户,如果已存在标记为autorelease: pending的 PR,release-please 将不会创建新的 PR。请搜索带此标签的 PR 确认(很可能就是最新的那个发布 PR)。如果该发布 PR 不会再发布(或已经发布),请移除autorelease: pending标签并重新运行 release-please。
步骤 3:重新运行 release-please
如果你认为带可发布单元的 PR 合并后 release-please 漏掉了发布 PR,请重新运行release-please:
- 使用GitHub Application时:给已合并的 PR 添加
release-please:force-run标签; - 使用GitHub Action时:找到失败的那次调用并重试对应 workflow 运行。
release-please 会立即处理该 PR 以查找可发布单元。
支持的策略(语言)类型
release-please 为以下类型的仓库自动化发布流程:
| release type | 说明 |
|---|---|
bazel | 带MODULE.bazel和CHANGELOG.md的 Bazel 模块 |
dart | 带pubspec.yaml和CHANGELOG.md的仓库 |
elixir | 带mix.exs和CHANGELOG.md的仓库 |
go | 带CHANGELOG.md的仓库 |
helm | 带Chart.yaml和CHANGELOG.md的仓库 |
java | 每次发布后生成 SNAPSHOT 版本的策略(见 docs/java.md) |
krm-blueprint | 带 1 个或多个 KRM 文件及CHANGELOG.md的 kpt 包 |
maven | 面向 Maven 项目的策略,每次发布后生成 SNAPSHOT 版本并自动更新pom.xml(见 docs/java.md) |
node | 带package.json和CHANGELOG.md的 Node.js 仓库 |
expo | 带package.json、app.json和CHANGELOG.md的基于 Expo 的 React Native 仓库 |
ocaml | 含 1 个或多个 opam 或 esy 文件及CHANGELOG.md的 OCaml 仓库 |
php | 带composer.json和CHANGELOG.md的仓库 |
python | 带pyproject.toml、<project>/__init__.py、CHANGELOG.md,或可选的setup.py、setup.cfg的 Python 仓库 |
R | 带DESCRIPTION和NEWS.md的仓库 |
ruby | 带version.rb和CHANGELOG.md的仓库 |
rust | 带Cargo.toml(crate 或 workspace;workspace 需配合 manifest 驱动发布 与cargo-workspace插件)和CHANGELOG.md的 Rust 仓库 |
sfdx | 带sfdx-project.json和CHANGELOG.md的仓库 |
simple | 带version.txt和CHANGELOG.md的仓库 |
terraform-module | README.md 中含版本信息、带CHANGELOG.md的 terraform 模块 |
在源码中,这些策略统一注册在src/factory.ts的releasers注册表中(src/factory.ts),由buildStrategy依据releaseType字符串查表实例化对应的 Strategy 类(src/factory.ts);表中还能看到dotnet-yoshi、java-yoshi、java-backport、java-bom、java-lts、go-yoshi、php-yoshi、ruby-yoshi、python-librarian等更多内部策略变体。每个策略的核心职责——"决定发布 PR 中需要更新哪些文件"——定义在Strategy接口中(src/strategy.ts)。
如何部署 Release Please
部署方式有多种,官方推荐使用 GitHub Action。
GitHub Action(推荐)
最简单的方式是把 release-please 作为 GitHub Action 运行,具体安装与配置说明见googleapis/release-please-action项目(本仓库未包含其源码,可前往该独立仓库查阅)。
以 CLI 方式运行
所有配置选项详见 docs/cli.md。核心命令如下:
全局安装:
npm i release-please -g全局选项(所有命令可用):
| 选项 | 类型 | 说明 |
|---|---|---|
--token | string | 必填。具备仓库写权限的 GitHub token |
--repo-url | string | 必填。<owner>/<repo>格式的 GitHub 仓库 |
--api-url | string | REST API 请求的 Base URI,默认https://api.github.com |
--graphql-url | string | GraphQL 请求的 Base URI,默认https://api.github.com |
--target-branch | string | 发布 PR 基于的分支、打标签的分支,默认为仓库默认分支 |
--dry-run | boolean | 设置后只报告将要发生的操作,不实际执行 |
--debug | boolean | 设置后日志级别 >= DEBUG |
--trace | boolean | 设置后日志级别 >= TRACE |
Bootstrapping(初始化仓库):
release-please bootstrap \ --token=$GITHUB_TOKEN \ --repo-url=<owner>/<repo> \ --release-type=<release-type> [extra options]该命令用于生成初始的release-please-config.json和.release-please-manifest.json(或用附加配置更新它们),并会针对目标分支打开一个包含新配置的 PR。常用附加选项包括:--config-file(默认release-please-config.json)、--manifest-file(默认.release-please-manifest.json)、--path(组件路径,默认.)、--package-name、--component、--release-type、--initial-version(默认0.0.0)、--versioning-strategy(默认default)、--bump-minor-pre-major、--bump-patch-for-minor-pre-major、--prerelease-type、--draft、--prerelease、--force-tag-creation、--draft-pull-request、--label(默认autorelease: pending)、--release-label(默认autorelease: tagged)、--changelog-path(默认CHANGELOG.md)、--changelog-type(默认default)、--changelog-sections、--changelog-host(默认https://github.com)、--include-commit-authors、--pull-request-title-pattern(默认chore${scope}: release${component} ${version})、--pull-request-header(默认:robot: I have created a release *beep* *boop*)、--pull-request-footer、--component-no-space、--extra-files、--version-file(Ruby 专用),完整表格见 docs/cli.md。
创建/更新发布 PR:
release-please release-pr --token=$GITHUB_TOKEN \ --repo-url=<owner>/<repo> [extra options]- 使用manifest 配置时(仓库中存在 manifest config 文件),发布配置直接从 manifest config 文件中读取,附加选项包括
--config-file、--manifest-file、--path(从 monorepo manifest 发布单个组件/包)、--release-as、--draft-pull-request、--fork、--skip-labeling; - 不使用 manifest 配置时,需要显式指定发布选项:
--path(默认.)、--package-name、--component、--release-type、--release-as、--initial-version、--versioning-strategy、--bump-minor-pre-major、--bump-patch-for-minor-pre-major、--prerelease-type、--draft-pull-request、--label、--changelog-path、--changelog-type、--changelog-sections、--changelog-host、--include-commit-authors、--monorepo-tags、--pull-request-title-pattern、--pull-request-header、--pull-request-footer、--signoff、--extra-files、--version-file、--skip-labeling、--include-v-in-tags(默认true),完整表格见 docs/cli.md。
在 GitHub 上创建 Release:
release-please github-release \ --token=$GITHUB_TOKEN --repo-url=<owner>/<repo> [extra options]manifest 与无 manifest 两种模式下的选项同上(--config-file、--manifest-file、--path、--package-name、--component、--release-type、--monorepo-tags、--pull-request-title-pattern、--pull-request-header、--pull-request-footer、--draft、--prerelease、--force-tag-creation、--label、--release-label、--include-v-in-tags),完整表格见 docs/cli.md。
注:旧的
manifest-pr/manifest-release命令已标记为deprecated,分别由release-pr/github-release以相同选项替代,仅保留向后兼容,将在下一个 major 版本中移除(详见 docs/cli.md)。
初始化(Bootstrapping)你的仓库
release-please 会查看自上个发布标签以来的提交,但它不一定能发现你之前的发布记录。让仓库平滑上线的最简方式是使用 bootstrap 一个 manifest 配置(上文已给出命令示例)。bootstrap 会生成release-please-config.json与.release-please-manifest.json两个文件,本仓库根目录下即有实际样例(release-please-config.json),对应 JSON Schema 见 schemas/config.json 与 schemas/manifest.json。
自定义 Release Please
release-please 提供了多项配置选项用于定制你的发布流程,包括 changelog 类型、版本策略(如always-bump-major、always-bump-minor、always-bump-patch、prerelease、service-pack等,实现位于 src/versioning-strategies/)、插件机制(如 src/plugins/workspace.ts、src/plugins/linked-versions.ts、src/plugins/merge.ts 等)以及策略工厂与 changelog 工厂。完整说明见 docs/customizing.md。
通过 Manifest 配置支持 Monorepo
release-please 同样支持从同一个仓库发布多个构件(组件/包),即 monorepo 场景。配置方式与组件划分规则详见 docs/manifest-releaser.md;rust workspace 等场景需要配合cargo-workspace插件(实现见 src/plugins/cargo-workspace.ts)。
支持的 Node.js 版本与版本策略
- 本仓库的客户端库遵循 Node.js 发布节奏,兼容所有当前active与maintenance状态的 Node.js 版本;从 package.json 可以看到当前
engines.node要求为>=22.0.0。 - 面向部分已 EOL 的 Node.js 版本也提供了客户端库,可通过 npm dist-tag 安装,命名约定为
legacy-(version)。Legacy 版本按"尽力而为"支持:不在 CI 中测试;部分安全补丁可能无法 backport;依赖不会持续更新,功能也不会 backport。目前提供的 legacy tag 为legacy-8(兼容 Node.js 8)。
版本策略与许可证
本库自身遵循Semantic Versioning,当前版本为17.11.2(见 package.json)。贡献指南见 CONTRIBUTING.md,设计文档见 docs/design.md,常见问题排查见 docs/troubleshooting.md。代码基于Apache 2.0许可发布(见 LICENSE)。
免责声明:本仓库不是 Google 官方产品。
- 开发工具
- CI/CD
- DevOps
【免费下载链接】release-please
generate release PRs based on the conventionalcommits.org spec
相关推荐
release-please 完全指南:从 Conventional Commits 到 GitHub Releases
release please 完全指南:从 Conventional Commits 到 GitHub Releases 想要自动化管理 GitHub 项目版本
开发工具CI/CDDevOpsbrowserless 发布自动化全流程指南:release-please 与 Conventional Commits 驱动的 npm 与 Docker 协同发布
browserless 发布自动化全流程指南:release please 与 Conventional Commits 驱动的 npm 与 Docker 协同
后端API网关为什么PDF补丁丁能成为你处理PDF文档的终极解决方案?
为什么PDF补丁丁能成为你处理PDF文档的终极解决方案? 在日常工作中,你是否经常遇到这样的困扰:PDF文档没有书签导航、多个文档合并后格式混乱、扫描版PDF无
桌面应用文档
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考