第十八章:使用 Google Release Please 实现 github 云端自动化版本管理与发布
第十八章:使用 Google Release Please 实现 github 云端自动化版本管理与发布
Prorise第十八章:使用 Google Release Please 实现 github 云端自动化版本管理与发布
本章目标:掌握语义化版本规范,利用 Release Please 实现版本号与 CHANGELOG 的自动化生成
开始之前:你需要知道的版本号基础
前置知识快速补课
在学习自动化版本管理之前,你需要理解几个基础概念:
版本号格式:MAJOR.MINOR.PATCH(例如:2.3.5)
| 位置 | 名称 | 何时+1 | 示例场景 |
|---|---|---|---|
| MAJOR | 主版本号 | 做了 不兼容 的 API 修改 | Vue 2 → Vue 3(Options API → Composition API) |
| MINOR | 次版本号 | 添加了 向后兼容 的新功能 | React 16.8 添加 Hooks |
| PATCH | 修订号 | 修复了 向后兼容 的 Bug | 修复内存泄漏、修正文档错误 |
记忆口诀:
- 破坏兼容 → MAJOR 跳
- 新增功能 → MINOR 涨
- 修 Bug → PATCH 补
特殊规则:
- 0.x.x = 初始开发版本,随时可能破坏兼容性
- 1.0.0 = 第一个稳定版本,API 开始遵守语义化版本规则
- 预发布版本:
1.0.0-alpha.1、2.0.0-beta.2、3.0.0-rc.1
18.1. 手动版本管理的三大噩梦
18.1.1. 噩梦一:版本号冲突的死锁
场景复现:
星期一上午,开发者小李和小王都在开发新功能。
小李的时间线:
1 | # 9:00 - 拉取最新代码 |
小王的时间线(同时进行):
1 | # 9:00 - 拉取最新代码 |
合并时的灾难:
1 | <<<<<<< HEAD |
Git 无法自动解决(因为两边内容相同),但逻辑上错了——应该是 1.4.0 才对。
18.1.2. 噩梦二:CHANGELOG 维护的黑洞
传统手工流程:
每次发版前,团队需要:
- 召开会议,让每个开发者口述自己做了什么
- Tech Lead 手动整理成 Markdown
- 按类型分组(Features / Bug Fixes / Breaking Changes)
- 查找对应的 Issue 编号和 PR 链接
- 人工校对是否有遗漏
一个真实的 CHANGELOG 编写时间统计:
| 版本包含的提交数 | 编写时间 | 主要耗时 |
|---|---|---|
| 10 个提交 | 30 分钟 | 回忆每个提交的背景 |
| 50 个提交 | 2 小时 | 分类和查找 Issue 编号 |
| 100+个提交 | 半天 | 去重、校对、格式化 |
手工 CHANGELOG 的常见问题:
1 | ## v1.5.0 (2024-03-15) |
问题分析:
- ❌ “添加了新功能” — 太模糊,用户看不懂
- ❌ “修复了一些问题” — 哪些问题?
- ❌ 没有 PR 链接 — 无法追溯详细信息
- ❌ “修复了登录 bug” — 在 Features 还是 Bug Fixes?分类混乱
18.1.3. 噩梦三:发布流程的不透明
传统发布流程:
1 | 1. 开发完成 |
真实案例:
某天下午 5 点,运维发现生产环境出现了新 Bug。紧急回溯后发现:
- 小张在中午 12 点手动发布了
v2.1.0 - 但他忘记通知任何人
- Git 上没有对应的 Tag(他只改了 package.json)
- NPM 上有这个版本,但 GitHub Release 里没有
- 根本无法确定这个版本包含了哪些代码
18.2. 解决方案:Conventional Commits + Release Please
18.2.1. Conventional Commits 规范详解
核心思想:通过标准化的提交信息格式,让机器能够 “理解” 每次提交的意图。
完整语法结构
1 | <type>(<scope>): <subject> |
各部分说明:
| 部分 | 是否必需 | 说明 | 示例 |
|---|---|---|---|
| type | ✅ 必需 | 提交类型(见下表) | feat、fix、docs |
| scope | ❌ 可选 | 影响范围 | (auth)、(ui)、(api) |
| subject | ✅ 必需 | 简短描述(50 字符内) | add dark mode toggle |
| body | ❌ 可选 | 详细描述 | 多行文本,解释动机和实现 |
| footer | ❌ 可选 | 关联 Issue 或破坏性变更 | Closes #123BREAKING CHANGE: ... |
Type 类型完整列表
| Type | 作用 | 影响版本号 | 出现在 CHANGELOG | 示例 |
|---|---|---|---|---|
| feat | 新功能 | +MINOR | ✅ 是 | feat(auth): add OAuth login |
| fix | 修复 Bug | +PATCH | ✅ 是 | fix(api): handle null response |
| docs | 文档变更 | 不变 | ⚠️ 可选 | docs: update README |
| style | 代码格式(不影响逻辑) | 不变 | ❌ 否 | style: format with prettier |
| refactor | 重构(不改功能) | 不变 | ⚠️ 可选 | refactor: extract helper function |
| perf | 性能优化 | +PATCH | ✅ 是 | perf: lazy load images |
| test | 测试相关 | 不变 | ❌ 否 | test: add unit tests for utils |
| build | 构建系统/依赖 | 不变 | ⚠️ 可选 | build: upgrade webpack to v5 |
| ci | CI 配置 | 不变 | ❌ 否 | ci: add caching to GitHub Actions |
| chore | 其他杂项 | 不变 | ❌ 否 | chore: update .gitignore |
| revert | 回滚提交 | +PATCH | ✅ 是 | revert: feat(auth): add OAuth |
破坏性变更的两种写法:
方法 1:在 type 后加 !
1 | git commit -m "feat!: migrate to new API endpoint" |
方法 2:在 footer 中声明
1 | git commit -m "feat: migrate to new API endpoint |
效果:两种方法都会触发 MAJOR 版本号 +1
例如如下的参考
| 场景 | 正确答案 |
|---|---|
| 修复了用户无法登出的 bug | fix(auth): prevent logout button from being disabled |
| 添加了深色模式 | feat(ui): add dark mode toggle |
| 更新了 README 的安装说明 | docs(readme): clarify installation steps |
| 将 Vue 2 升级到 Vue 3 | feat!: upgrade to Vue 3或 feat: upgrade to Vue 3BREAKING CHANGE: ... |
| 优化了图片加载速度 | perf(images): implement lazy loading |
| 修复了测试用例的 typo | test: fix typo in user.test.js |
18.2.2. Release Please 的工作原理
一句话概括:Release Please 是一个 “提交信息解析器 + 版本号计算器 + CHANGELOG 生成器 + PR 自动化机器人”。
1. 监听(Listen)
- 每次代码推送到
main分支时触发 - 读取上次发布的版本号(从
.release-please-manifest.json或 Git Tags) - 扫描并解析所有新提交的 Type 和 BREAKING CHANGE
2. 提案(Propose)
- 检测到有效提交(
feat/fix)后,创建或更新一个特殊的 PR - PR 标题:
chore(main): release <version> - PR 分支:
release-please--branches--main - 包含的文件变更:
package.json:版本号已更新CHANGELOG.md:新增本次发布的变更记录.release-please-manifest.json:更新为新版本号
3. 堆叠(Stack)
- 如果 Release PR 未合并,新提交会自动追加到现有 PR 中
- 版本号和 CHANGELOG 会重新计算,始终保持一个 PR 反映最新待发布状态
4. 交付(Deliver)
- 合并 Release PR 后,自动创建 Git Tag 和 GitHub Release
- CHANGELOG 内容填充到 Release Notes
- 设置 Action Outputs 供后续 Job 使用
为什么使用 PR 模式而不是直接打 Tag
- 可预览:合并前可查看 CHANGELOG 内容
- 可干预:可手动调整版本号或补充文档
- 可讨论:团队可在 PR 中讨论是否应该发布
18.2.3. 配置文件完全解析:从 5 行到 60 行
Release Please 使用 “配置与状态分离” 的设计,这种模式非常适合长期维护的项目:
release-please-config.json:定义发布规则(由开发者维护).release-please-manifest.json:记录当前版本号(由工具自动维护)
完整配置文件示例(release-please-config.json)
我们需要在项目根目录中创建如下 JSON 文件。注意:为了让 IDE 能够读取 Schema 进行自动补全,这里的注释仅用于讲解,实际复制到 JSON 文件中请务必删除注释!
1 | { |
状态文件示例(.release-please-manifest.json)
1 | { |
extra-files 的实际应用场景
在我们的前端项目中,通常希望在页面底部显示当前应用版本。我们创建一个专门存放版本号的文件:
src/version.ts
1 | // 这个文件的版本号会被 Release Please 自动更新,请勿手动修改 |
然后在 src/App.vue (或 React 的 App.tsx) 中引入使用:
1 | import { VERSION } from "./version" |
当 Release Please 创建 Release PR 时,它会同时修改 package.json 和这个 src/version.ts,确保页面显示的版本永远是最新的。
18.2.4. GitHub Actions 工作流配置
创建 .github/workflows/release-please.yml。这个文件负责“看门”,它只在代码推送到 main 分支时工作,在此之前我们需要授权 workflow 创建 pr 的权限,否则会报错退出
1 | name: Release Please |
18.2.5. 完整实战演练:从开发到发布
让我们在现有的项目中实际演练一遍。
初始化配置
1 | # 1. 创建配置文件 (内容如上节所示,记得去除注释) |
场景一:开发新功能(Feature)
假设我们要开发一个新组件,并希望版本号从 0.0.0 升级到 0.1.0。
1 | # 1. 修改代码 |
检查 Release PR 内容
此时去 GitHub 查看 Pull Requests,你会发现机器人创建的 PR 包含以下变更:
package.json:"version": "0.1.0"src/version.ts:export const VERSION = '0.1.0';(自动同步了!)CHANGELOG.md: 生成了新条目。.release-please-manifest.json: 更新为0.1.0。
场景二:发现 Bug 并修复(Fix)
在 PR 合并之前,测试同学发现页面的样式有点问题。我们继续提交:
1 | # 1. 修复样式问题 |
场景三:合并发布
- Code Review:团队成员 Review 代码确认无误。
- Merge:点击 “Squash and merge” 或 “Rebase and merge”。
- 触发发布:
release-pleaseAction 再次运行。- 检测到 Release PR 已合并。
- 创建 Git Tag
v0.1.0。 - 创建 GitHub Release,内容自动填充 CHANGELOG。
场景四:破坏性变更(Breaking Change)
如果我们重构了核心逻辑,导致旧版本不兼容:
1 | git commit -m "feat!: migrate to new auth system |
18.3. 本章小结与实战检查清单
核心知识回顾
1 | 自动化版本管理体系 |
下一章预告:
在第 19 章《制品自动化交付实战》中,我们将把 Release Please 与实际的发布流程结合:
- NPM 包的自动发布(处理 2FA 认证)
- Docker 镜像的多架构构建
- 如何在发布失败时回滚
- 完整的 CD Pipeline 集成
继续前进! 🚀














