【昇腾CANN】changelog自动化:用脚本省掉80%的版本记录工作
每次发版前最烦人的事情是什么?写 changelog。翻一个月的 commit history,对着一堆 fix typo、update readme、wip、asdf 这样的 commit message,欲言又止。
release-management 仓库里的 changelog 自动化模块,解决的就是这个问题。
为什么手动写 changelog 是浪费时间
想象一个典型场景:ops-transformer 要从 1.2.0 发到 2.0.0,这两个月里仓库有 300 多次 commit。如果手动整理:
- 打开 git log,从第一个 commit 翻到最后一个
- 每次 commit 都要点进去看 diff,判断是 feature 还是 fix
- 把内容归类到不同 section
- 检查有没有 breaking change 要特别标注
- 反复确认有没有遗漏的重要改动
这活儿熟练工也要干两个小时。而且人整理的东西容易有主观偏差,比如觉得自己写的 update 比 fix 更重要,就把它归到 New Features 里——其实只是改了变量名。
自动化生成的基本原理
changelog 生成的本质是:从结构化的 commit message 里提取信息,按版本聚合,按类别分组。
核心逻辑其实不复杂:
from release_management import ChangeLog
# 从指定 tag 范围生成 changelog
changelog = ChangeLog.generate(
repo="ops-transformer",
from_tag="v1.2.0",
to_tag="v2.0.0",
# conventional commit 格式解析
categories={
"feat": "New Features", # feat: 开头的 commit
"fix": "Bug Fixes", # fix: 开头的 commit
"perf": "Performance", # perf: 开头的 commit
"docs": "Documentation", # docs: 开头的 commit
"refactor": "Refactoring", # refactor: 开头的 commit
},
# 过滤掉哪些类型的 commit 不出现在 changelog 里
exclude=["style", "test", "chore"]
)
print(changelog)
输出的前提是 commit message 符合 Conventional Commits 规范,比如:
feat(flash-attention): add v2 implementation supporting 32k context
fix(moe-router): correct topk overflow when experts is odd
perf(mc2-allgather): reduce communication overhead by 15%
docs: update README for v2 migration guide
feat: 后面括号里的 scope 会被保留下来,用于标注是哪个子模块的改动。changelog 里会显示 flash-attention: add v2 implementation...,阅读体验好很多。
自定义过滤规则:怎么过滤噪音 commit
自动生成有一个问题:仓库里有很多没有意义的 commit,比如依赖升级、CI 配置更新、merge branch 这些。直接放进 changelog 会显得很业余。
# 定义过滤规则,正则匹配排除噪音 commit
changelog = ChangeLog.generate(
repo="ops-transformer",
from_tag="v1.2.0",
to_tag="v2.0.0",
filters={
# 排除所有依赖相关的 commit
"exclude_patterns": [
r"^chore(deps):",
r"^chore\(ci\):",
r"^style:",
r"^test:",
r"Merge branch",
r"^Update .*lock",
],
# 只保留超过 N 个字符的 commit message
# 太短的 commit 往往是 typo fix 或者无关紧要的改动
"min_message_length": 20,
# merge commit 通常不包含实质内容
"exclude_merges": True,
}
)
有一个容易忽略的细节:breaking change 不会自动标注。Conventional Commits 规范里 breaking change 要在 footer 里写 BREAKING CHANGE:,或者在 message 末尾加 !:。但很多开发者不知道这个约定,代码写完了才发现有个 API 不兼容。
# 自动扫描 breaking change
changelog = ChangeLog.generate(
repo="ops-transformer",
from_tag="v1.2.0",
to_tag="v2.0.0",
# 扫描常见的不兼容模式
breaking_patterns=[
r"^BREAKING CHANGE:",
r"remove.*parameter",
r"rename.*argument",
r"change.*return.*type",
],
# 识别到 breaking change 自动提升到 Breaking Changes section
auto_breaking=True
)
生成后人工 review 的几个检查点
自动化生成之后,人工 review 仍然必要,但重点变了——不是从头整理,而是检查生成结果有没有明显错误。
我一般会过这几个点:
第一,大功能有没有被漏掉。如果某个 commit 加了新的融合模式,但在 changelog 里找不到,那八成是被 filter 规则误杀了。去 commit history 里搜一下关键词,确认是漏掉了还是确实被过滤了。
第二,分组是否合理。有时候同一个 commit 改了多个文件,conventional commit 的 scope 只能标一个,其他子模块的改动容易被忽略。这种情况要手动拆分成多条。
第三,语气是否一致。自动化生成的是 add xxx 和 fix xxx,但 changelog 作为一个对外文档,应该统一人称和时态。我一般会用脚本做一次批量替换:
# 统一 changelog 语气:第三人称、一般过去时
changelog = ChangeLog.generate(...)
normalized = changelog.replace(
"add", "Added"
).replace(
"fix", "Fixed"
).replace(
"update", "Updated"
)
和 CI 集成:每次 PR 合入自动更新
最理想的使用方式是让 changelog 生成成为 CI 流程的一部分,而不是发版前临时抱佛脚。
# .github/workflows/changelog.yml
name: Changelog Update
on:
pull_request:
types: [closed]
branches: [main]
jobs:
update-changelog:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Generate changelog entry
run: |
python -m release_management.changelog \
--repo ${{ github.event.pull_request.head.repo.name }} \
--sha ${{ github.event.pull_request.head.sha }} \
--output changelog_entry.txt
- name: Create PR for changelog update
uses: peter-evans/create-pull-request@v4
with:
title: "docs: update changelog"
body-file: changelog_entry.txt
branch: changelog/${{ github.event.pull_request.number }}
这样每次 PR 合并都会自动生成一条 changelog entry,后续发版的时候直接合并这些 entry 就行了,changelog 内容早就准备好了。
工具不是万能的
最后说一个反直觉的点:changelog 工具再好,也解决不了根本问题——commit message 质量。
如果团队里 commit message 写得很随意,update、fix、wip 满天飞,那 changelog 生成出来也是一堆噪音。工具只是放大镜,能放大好的规范,也能放大乱规范。
所以在用 release-management 的 changelog 模块之前,先把 commit message 规范建起来。Conventional Commits 不难学,团队里约定一个 scope 列表(比如 flash-attention、moe-router、mc2-allgather),每次 commit 前花 30 秒想清楚这条 commit 改了什么——之后写 changelog 能省两小时。
仓库在 https://atomgit.com/cann/release-management,changelog 相关的 API 文档可以直接看源码里的 changelog.py,逻辑很清晰。
鲲鹏昇腾开发者社区是面向全社会开放的“联接全球计算开发者,聚合华为+生态”的社区,内容涵盖鲲鹏、昇腾资源,帮助开发者快速获取所需的知识、经验、软件、工具、算力,支撑开发者易学、好用、成功,成为核心开发者。
更多推荐

所有评论(0)