ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

github-changelog-generator 如何解析历史 Changelog:以 AngularJS 官方 CHANGELOG 为样本的格式兼容性剖析

github-changelog-generator 如何解析历史 Changelog:以 AngularJS 官方 CHANGELOG 为样本的格式兼容性剖析
  • 开发工具

【免费下载链接】github-changelog-generator

Automatically generate change log from your tags, issues, labels and pull requests on GitHub.

项目地址:https://gitcode.com/gh_mirrors/gi/github-changelog-generator
点击查看免费下载

本文以仓库测试夹具 spec/files/angular.js.md 为核心样本,剖析 github-changelog-generator 对"非自身格式"历史 changelog 的解析原理与兼容边界:从文档结构特征、Reader 解析源码,到通过--base将旧 changelog 并入新生成结果的迁移实践。读完本文,你将掌握生成器默认输出格式与 AngularJS 式旧格式的差异、解析规则的源码级依据,以及老仓库接入自动化 changelog 生成的具体方案。

一、这份 AngularJS Changelog 在仓库中的角色

spec/files/angular.js.md是 AngularJS 官方仓库CHANGELOG.md的一份真实拷贝样本,共9395 行,收录了 2014-11 至 2015-03 之间134 个版本的变更记录(最新为1.4.0-beta.6 cookie-liberation,最旧为1.2.27 prime-factorization)。它并不属于生成器"生产"出来的输出,而是以**测试夹具(fixture)**的身份存放在spec/files/目录,与bundler.md、github-changelog-generator.md并列。

它承担的核心角色在 spec/unit/reader_spec.rb 中体现得最清楚:Reader类负责"读入一个已存在的 changelog 文件并转成结构化对象",而这份文件就是验证Reader对异构格式输入解析行为的样本。值得注意的是,针对它的断言目前全部以pending('Implement heading_level for parser.')标注,测试注释中写明期望解析出version => '1.4.0-beta.6 cookie-liberation'、url => nil、date => '2015-03-17'——这说明该文件是驱动 Reader 未来支持可配置标题级别的"靶子样本"。

与它同目录的另两份夹具形成了三种格式的对照:

  • spec/files/github-changelog-generator.md:生成器自身输出格式(H2 标题 +**Fixed bugs:**式加粗小节),reader_spec 断言其可解析出 28 个条目;
  • spec/files/bundler.md:Bundler 项目的手工 changelog(## 1.9.1 (2015-03-21)式 H2 标题),断言可解析出 151 个条目;
  • spec/files/angular.js.md:H1 版本标题 + HTML 锚点的极端异构格式,测试暂挂。

二、AngularJS Changelog 的文档结构与格式特征

从 spec/files/angular.js.md 开头即可看到其独特的四层结构:

<a name="1.4.0-beta.6"></a> # 1.4.0-beta.6 cookie-liberation (2015-03-17) ## Bug Fixes - **$animate:** call `applyStyles` from options on `leave` (4374f892, #10068)

逐层拆解其特征:

1. HTML 锚点行。每个版本条目之上都有一行<a name="1.4.0-beta.6"></a>(全文 134 个,与版本数一一对应),用于在 GitHub 页面上提供稳定的跳转锚点。

2. 一级标题#承载版本号。版本标题使用 Markdown H1(全文共 134 个#标题),格式为# 版本号 codename (日期),例如# 1.3.15 locality-filtration (2015-03-17)。版本号之后还带上了 AngularJS 特有的"代号"(cookie-liberation、karmic-stabilization 等),这是它的标志性命名风格。

3. 二级标题##承载变更分类。全文 313 个##分类小节,且分类体系比常见的 Bug/Feature 更细致,主要出现:

  • ## Bug Fixes
  • ## Features
  • ## Performance Improvements
  • ## Breaking Changes

4. 条目与引用格式。每条记录形如- **$animate:** callapplyStylesfrom options onleave``,随后换行缩进附上提交 SHA 与关联 issue 编号的 Markdown 链接;Breaking Changes小节内还会嵌入 HTML/JS 代码示例与"Before / After"对比(见 spec/files/angular.js.md 的ngMessagesInclude迁移示例)。

5. 文件尾部的 reference links。文档末尾是一大批[limitTo]: http://...形式的 Markdown 引用式链接定义(spec/files/angular.js.md),属于手工维护 changelog 时代的常见写法。

三、与生成器默认输出格式的差异对比

对照 lib/github_changelog_generator/generator/entry.rb 中generate_header与 lib/github_changelog_generator/generator/section.rb 中generate_content的产出,可以整理出下表:

维度AngularJS 旧格式(本样本)生成器默认输出
版本标题级别# 1.4.0-beta.6 cookie-liberation (2015-03-17)(H1,含代号)## 1.2.5 (2015-01-15)(H2,版本号可点击)
版本链接无(url => nil)版本号
版本间对比链接无Full Changelog(由--compare-link控制,见 argv_parser.rb)
分类小节## Bug Fixes/## Features(H2 文本标题)**Fixed bugs:**/**Implemented enhancements:**(加粗前缀,对应--bugs-label、--enhancement-label等选项,见 argv_parser.rb)
条目样式- **$animate:** …+ 缩进 commit/issue 引用- 标题 \#22 (@作者)
锚点<a name="…"></a>手动维护无

从源码看,生成器默认头部会为每个版本生成## tag (日期)与可选的[Full Changelog]对比链接,而 AngularJS 样本这两种链接都不存在——这正是"旧格式"与"生成格式"最直观的分水岭。

四、Reader 的解析原理:为什么这份文件会让测试暂挂

Reader的解析入口在 lib/github_changelog_generator/reader.rb:

  • parse_heading(reader.rb)按一组"标题结构"正则逐一尝试匹配,命中即提取version、url、date三个字段;
  • parse(reader.rb)以^## .+?$切分全文为若干 section,并把每个标题之后的文本挂为content;
  • 默认的标题结构(reader.rb)仅覆盖六种 H2 形态:
/^## \(?<version>.+?)\\))?( \((?<date>.+?)\))?$/ /^## (?<version>.+?)( \((?<date>.+?)\))?$/

由此可以推断出 AngularJS 样本无法被当前版本完整解析的三个根因:

  1. 标题级别不匹配:样本版本标题是#(H1),而默认heading_level固定为"##",heading_structures正则也都锚定^##。从源码结构看,Reader尚未实现可配置的标题级别(@options[:heading_level]虽已预留,但parse中的分割与扫描正则仍写死为^##)。
  2. 版本号含代号:即使把标题级别放宽到 H1,1.4.0-beta.6 cookie-liberation中的空格也意味着version字段会整体捕获"版本号 + 代号",测试注释中version => '1.4.0-beta.6 cookie-liberation'的期望正是对这一行为的预判。
  3. 无链接无日期兜底问题:# 1.2.27 prime-factorization (2014-11-20)这类带日期的标题可被第二组正则的部分逻辑兼容,但<a name>锚点行会混入 section 的content中,需要额外清洗。

reader_spec 中另两份样本恰好证明:只要标题是 H2 形态,无论是否带链接都能被解析——bundler.md的## 1.9.1 (2015-03-21)(无 url)可解析出 151 条,github-changelog-generator.md的## 1.3.10 (date)可解析出 28 条,而 angular.js.md 的断言全部暂挂,成为"待实现 heading_level 特性"的活体验收标准。

五、把历史 changelog 并入新生成结果:--base 迁移实践

对于像 AngularJS 这样已经维护了多年手工 changelog 的老仓库,最现实的接入方式是"新条目自动生成、旧内容原样保留",这正是--base选项的用途。

命令层面:-b, --base NAME(argv_parser.rb),说明为"Optional base file to append generated changes to. Default is HISTORY.md"。若项目根目录存在HISTORY.md,会被自动识别为静态历史 changelog。

实现层面:在 lib/github_changelog_generator/generator/generator.rb 的compound_changelog主流程中,生成完所有版本条目后执行:

log += File.read(@options[:base]) if File.file?(@options[:base])

即:生成器产生的全部条目之后,直接追加旧 changelog 全文。因此一份 AngularJS 式的旧文件(哪怕它的标题级别、锚点、分类命名都与新格式不同)也能原样"挂载"在新 changelog 尾部,互不干扰。

参数文件方式:也可以像 spec/files/config_example 那样,把这类参数写进项目根目录的.github_changelog_generator文件统一管理(README "Params File" 一节示例了unreleased=false、future-release=5.0.0、since-tag=1.0.0等写法),--base同样适用。若希望只生成某次发布区间的条目,可组合--since-tag与--output,将结果交给gh release create --notes-file用作 Release Notes(详见 README.md)。

六、接入老仓库时的格式兼容要点

综合以上源码证据,针对"历史 changelog 由其他工具或手工维护"的项目,可以给出如下可验证的实践结论:

  1. 新旧格式共存是设计内行为:--base的追加机制决定了旧文件不需要被改写或转换,格式差异不会阻塞生成流程;
  2. H2 是当前可解析的最低兼容线:若旧文件本身就是 H2 结构(如 bundler.md 的## 1.9.1 (2015-03-21)),reader_spec 的断言(151 条全部解析成功)证明其可被Reader完整结构化;而 H1 结构(如 angular.js.md)目前只能整体保留,尚需等待heading_level特性落地;
  3. 新生成的条目会严格遵循生成器格式:H2 版本标题 + 版本链接 +[Full Changelog]+ 加粗小节前缀,各部分前缀与标签均可通过 argv_parser.rb 中的--bugs-label、--enhancement-label、--issues-label、--pr-label、--unreleased-label等选项定制,--date-format(默认%Y-%m-%d)控制日期输出,--simple-list可去掉小节前缀形成纯列表;
  4. 验证入口清晰:上述所有解析行为都能在 spec/unit/reader_spec.rb 找到对应的正反用例,作为排查格式问题的第一手依据。

七、小结

spec/files/angular.js.md表面上是 134 个版本的 AngularJS 历史记录,实质上是 github-changelog-generator 测试矩阵中"最难啃的格式样本":H1 版本标题、代号命名、HTML 锚点、reference links,几乎每一项都踩在 Reader 当前解析规则(固定##级别、两组正则)的边界之外。理解这份样本,等于同时理解了生成器的输出契约(H2 + 链接 + 加粗小节)与--base的历史迁移通道——这正是把老项目接入自动化 changelog 生成时最需要掌握的一对"兼容性知识点"。

  • 开发工具

【免费下载链接】github-changelog-generator

Automatically generate change log from your tags, issues, labels and pull requests on GitHub.

项目地址:https://gitcode.com/gh_mirrors/gi/github-changelog-generator
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进