资讯动态

release-please 的 CHANGELOG 生成机制深度解析:从标准格式、模板引擎到 Updater 插入算法

发布时间:2026/9/28 3:14:05 来源:尧图企业网站定制
开发工具CI/CDDevOps【免费下载链接】release-pleasegenerate release PRs based on the conventionalcommits.org spec项目地址https://gitcode.com/gh_mirrors/re/release-please点击查看免费下载release-please 是依据 conventionalcommits.org 规范自动生成 release PR 的发布工具而CHANGELOG.md是它每次发布的核心产出物。本文以仓库测试夹具 test/fixtures/CHANGELOG-new.md 为标本逐行解剖 release-please 生成的 CHANGELOG 标准格式并结合 changelog 模板、Changelog Updater 源码 与 DefaultChangelogNotes 实现完整还原commit 解析 → 版本变更笔记生成 → CHANGELOG 文件写入的调用链最后给出通过配置文件与 CLI 参数定制 CHANGELOG 的实战方案。读完本文你将掌握 release-please 生成 CHANGELOG 的格式规范、底层工作原理与定制方法。一、认识 CHANGELOG-new.mdrelease-please 的标准产出样本在 release-please 仓库中test/fixtures/CHANGELOG-new.md是一个典型的新版本 CHANGELOG测试夹具其内容正是 release-please 为1.2.0版本生成的标准变更记录。它以极小的篇幅浓缩了 CHANGELOG 的全部格式要素是理解该工具输出规范的最佳入门标本# Changelog [npm history][1] [1]: https://www.npmjs.com/package/release-please?activeTabversions ## [1.2.0](https://www.github.com/googleapis/release-please/compare/v1.1.0...v1.2.0) (2019-05-10) ### Bug Fixes * candidate issue should only be updated every 15 minutes. (#70) (edcd1f7) ### Features * add GitHub action for generating candidate issue (#69) (6373aed) * checkbox based releases (#77) (1e4193c)这个样本包含四个层次的结构接下来逐一拆解其生成原理。1.1 文件头# Changelog与历史导航首行# Changelog是固定的 H1 标题由 Changelog Updater 中的header()方法硬编码输出private header() { return \ # Changelog ; }其后跟随的[npm history][1]与底部引用定义[1]: ...是 Markdown 的引用式链接语法用于在仓库页面顶部快速跳转到 npm 版本历史。需要说明的是这个引用链接的内容由仓库自身的生成历史决定release-please 的核心 Updater 并不主动写入 npm 链接它来自仓库原有的 CHANGELOG 头部adjustHeaders与插入算法会保留其前方的既有内容见下文第三节。1.2 版本标题## 1.2.0 (2019-05-10)每个新版本以 H2 标题开头格式为## 版本号 (发布日期)该格式由模板 templates/header.hbs 定义### {{#if root.linkCompare~}} {{version}} {{~else}} {{~version}} {{~/if}} {{~#if title}} {{title}} {{~/if}} {{~#if date}} / {{date}} {{/if}}关键细节当存在previousTag上一个版本标签时linkCompare为真版本号会被包成指向版本对比页的链接例如v1.1.0...v1.2.0若没有上一个标签则只输出裸版本号。对应地在 DefaultChangelogNotes.buildNotes 中上下文对象会显式设置linkCompare: !!options.previousTag这就是首次发布不带 compare 链接、后续发布带链接的实现依据。1.3 变更分组### Bug Fixes与### Features按 conventionalcommits 规范commit 类型被归类为若干组每个组以 H3 标题呈现。默认分组Bug Fixes、Features 等由conventional-changelog-conventionalcommitspreset 提供分组结构通过 templates/template.hbs 渲染{{#each commitGroups}} {{#if title}} #### {{title}} {{/if}} {{#each commits}} {{ commit rootroot}}{{/each}}{{/each}}模板同时支持破坏性变更组{{#if noteGroups}}渲染#### ⚠ {{title}}与自定义 changelog sections配置项changelog-sections详见第五节。1.4 commit 条目subject PR 引用 commit hash每个条目由模板 templates/commit.hbs 渲染* {{#if subject}} {{~subject}} {{~else}} {{~header}} {{~/if}}{{#if body}} {{body}}{{~/if}}即* 提交信息摘要 (PR 链接) (commit hash 链接)的形态。其中 commit 对象由 DefaultChangelogNotes.buildNotes 从解析后的ConventionalCommit构造subject取自commit.bareMessage并经htmlEscape转义防止、破坏 Markdownreferences保留 PR/issue 引用hash取commit.sha。值得注意的两点实现细节replaceIssueLinkdefault.ts#L123-L134会把BREAKING CHANGE注释中的(#\d)替换为指向 issue 页的 Markdown 链接closes → refs替换default.ts#L70-L74preset.writerOpts.commitPartial this.commitPartial || preset.writerOpts.commitPartial?.replace(/,\s*closes/g, , refs);这是为了防止 release PR 被合并时GitHub 因 commit 消息中的 closes 关键字自动关闭相关 issue。二、完整生成链路从提交解析到 CHANGELOG 写入CHANGELOG-new.md 不是手工维护的而是 release-please 流水线四步协作的产物解析 commits读取自上一个版本标签以来的提交按 conventionalcommits 规范解析出 type、scope、subject、references 与 BREAKING CHANGE 注释参见 src/commit.ts 与 src/util/commit-utils.ts计算版本根据提交类型由版本策略决定新版本号feature 升 minor、breaking change 升 major、bugfix 升 patch见 src/versioning-strategy.ts生成变更笔记DefaultChangelogNotes.buildNotes将 commits 转换为conventional-changelog-writer可消费的对象调用parseArray结合 templates 渲染出新版本条目字符串写入文件ChangelogUpdater 把新条目插入既有CHANGELOG.md的合适位置。其中第 3、4 步直接决定了 CHANGELOG-new.md 的最终形态下面分别深入。三、Changelog Updater插入算法的精确定位src/updaters/changelog.ts 中的Changelog类继承自DefaultUpdater其updateContent是理解新条目如何进入既有文件的关键。核心逻辑如下const DEFAULT_VERSION_HEADER_REGEX \n###? v?[0-9[; updateContent(content: string | undefined): string { content content || ; // 兼容 H2Features/BREAKING CHANGES与 H3fixes两种版本头 const lastEntryIndex content.search(this.versionHeaderRegex); if (lastEntryIndex -1) { if (content) { return ${this.header()}\n${this.changelogEntry}\n\n${adjustHeaders(content).trim()}\n; } else { return ${this.header()}\n${this.changelogEntry}\n; } } else { const before content.slice(0, lastEntryIndex); const after content.slice(lastEntryIndex); return ${before}\n${this.changelogEntry}\n${after}.trim() \n; } }算法要点定位锚点用正则\n###? v?[0-9[在既有内容中查找第一个版本头兼容## v0.8.2、## [1.2.0]、### 0.5.0等多种风格这也是 test/updaters/changelog.ts 测试覆盖 ruby、dotnet、patch 等多种格式的原因找到锚点将新条目插入在文件头与最旧版本条目之间保证最新版本永远在最上面找不到锚点把既有内容整体塞到新条目之后并通过adjustHeaders把其中的 H1 降级为 H2content.replace(/^#(\s)/gm, ##$1)维持全文只有一个# Changelog标题的结构支持自定义正则构造时可通过versionHeaderRegex覆盖默认锚点正则例如 dotnet 风格用\n## Version [0-9[]见 test/updaters/changelog.ts#L74-L86。测试夹具 test/updaters/fixtures/CHANGELOG.md、CHANGELOG-fix.md、CHANGELOG-ruby.md 分别演示了常规格式、最近一次是 patch、ruby 风格三种输入下updateContent的插入结果并与快照断言比对。四、DefaultChangelogNotes变更笔记的渲染引擎CHANGELOG-new.md 中新版本条目的原始文本由 src/changelog-notes/default.ts 的DefaultChangelogNotes生成。它封装了conventional-changelog-writer与conventional-changelog-conventionalcommitspresetconst preset await presetFactory(config); preset.writerOpts.commitPartial this.commitPartial || ...; preset.writerOpts.headerPartial this.headerPartial || ...; preset.writerOpts.mainTemplate this.mainTemplate || ...; ... return conventionalChangelogWriter.parseArray(changelogCommits, context, preset.writerOpts).trim();关键设计上下文注入host默认https://github.com、owner、repository、version、previousTag、currentTag共同决定 compare 链接与 issue 链接的形态模板可替换构造时允许传入自定义commitPartial、headerPartial、mainTemplate对应 templates/commit.hbs、templates/header.hbs、[templates/template.hbs]实现不改代码也能换排版作者信息可选开启includeCommitAuthors后subject 会追加(username)或作者名default.ts#L91-L97RELEASE AS脚注commit 的RELEASE-AS注释会被提取为Release-As: xxx脚注行供解析器识别手动指定版本default.ts#L109-L112。该生成结果不仅写入 CHANGELOG.md还会被复用于 release PR 正文与 GitHub release notes参见 src/release-pull-request.ts。五、定制 CHANGELOG配置项与 CLI 参数release-please 为 CHANGELOG 提供多层定制能力相关配置集中在 docs/customizing.md 与 src/bin/release-please.ts 中5.1 changelog-sections自定义分组通过配置changelog-sections可覆盖默认的 commit 类型分组例如将feat展示为 New Features、fix展示为 Bug Fixes。该数组在 manifest.ts#L167 中被定义为ChangelogSection[]并随 manifest 配置 传入changelogSections选项在DefaultChangelogNotes中它被写入config.types交给 preset 消费default.ts#L65-L68。5.2 changelog-type切换生成引擎default本文剖析的DefaultChangelogNotes按 commit 类型分组并链接 PR 与 commitgithub调用 GitHub Releases API 生成笔记见 src/changelog-notes/github.ts。默认值为defaultsrc/factory.ts#L140可通过 manifest 配置changelog-type或 CLI 参数切换。5.3 changelog-path指定 CHANGELOG 文件位置默认文件为仓库根目录的CHANGELOG.md可通过 manifest 的changelog-path或 CLI 的--changelog-path指定其他路径见 src/bin/release-please.ts#L110 与 src/manifest.ts#L132。CLI 也提供--changelog-sections选项src/bin/release-please.ts#L344。5.4 相关 CLI 选项速查CLI 选项对应 manifest 配置作用--changelog-path pathchangelog-pathCHANGELOG 文件路径--changelog-type typechangelog-typedefault或github--changelog-sections jsonchangelog-sections自定义 commit 分组--pull-request-headerpull-request-header定制 PR 头部文案--pull-request-footerpull-request-footer定制 PR 尾部文案六、扩展机器可读的 changelog.json除 Markdown 格式外release-please 还提供结构化版本 src/updaters/changelog-json.ts 的ChangelogJsonUpdater将每个 commit 规整为{type, scope, sha, issues, message, breakingChangeNote}并写入changelog.json的entries数组最新版本unshift到数组头部整体以 2 空格缩进输出。它与 Markdown CHANGELOG 共用同一份解析后的 commits 数据适合需要程序化消费变更信息的 CI 场景。七、总结从 test/fixtures/CHANGELOG-new.md 这一份小小的样本出发可以看到 release-please 的 CHANGELOG 生成是一个完整的分层体系conventionalcommits解析负责看懂提交DefaultChangelogNotes负责组织内容handlebars 模板负责排版渲染ChangelogUpdater 负责精确定位插入。理解这套机制后你可以通过changelog-sections、changelog-type、changelog-path等配置轻松定制出符合团队规范的发布记录也可以通过阅读 test/updaters/changelog.ts 的测试用例快速验证自己的理解。赞分享开发工具CI/CDDevOps【免费下载链接】release-pleasegenerate release PRs based on the conventionalcommits.org spec项目地址https://gitcode.com/gh_mirrors/re/release-please点击查看免费下载相关推荐天若OCR开源版Windows用户必备的3分钟离线文字识别解决方案天若OCR开源版Windows用户必备的3分钟离线文字识别解决方案 还在为截图中的文字无法复制而烦恼吗天若OCR开源版就是为你量身打造的离线文字识别利器这开发工具CI/CDDevOps5分钟掌握可视化工具集前端开发者的效率革命5分钟掌握可视化工具集前端开发者的效率革命 你是否曾为处理图片、PDF和视频而频繁切换不同工具感到烦恼visualization collection项目为前端图形学AI 应用Askama模板引擎模板扩展机制深度解析Askama模板引擎模板扩展机制深度解析 你是否曾经在构建Web应用时为每个页面重复编写相同的HTML头部、导航栏和页脚而感到烦恼或者当需要修改网站布局时上一篇Android电池小部件终极指南从优雅监控到深度分析下一篇PyMacroRecord 1.4.0自动化办公的终极解放者三步告别重复劳动创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑