GreptimeDB 版本发布说明(Release Note / Changelog)生成实战:基于 git cliff 的完整工作流
【免费下载链接】greptimedbThe open-source observability database. One columnar engine for metrics, logs, and traces, on object storage.项目地址: https://gitcode.com/GitHub_Trending/gr/greptimedb
导读:本文讲解如何为 GreptimeDB 生成专业、完整、可对外发布的版本变更日志(changelog)。你将掌握从 GitHub token 注入、上一版本判定、
git cliff区间选择(minor 与 patch 的拓扑差异)、减去已发布 PR、重建贡献者名单,到人工精选 Highlights、输出文件规范、以及向 docs 仓库提交草稿 PR 的完整链路。文章以仓库内.agents/skills/greptimedb-release-note/SKILL.md为主干,并结合 cliff.toml、.agents/skills/greptimedb-release/SKILL.md 等仓库文件交叉佐证。
1. 概览:一次完整的 GreptimeDB 发版说明生成流程
GreptimeDB 官方仓库(GreptimeTeam/greptimedb)将「生成 changelog」沉淀为独立的 Agent Skill(.agents/skills/greptimedb-release-note/SKILL.md),并配套独立的发版 runbook(.agents/skills/greptimedb-release/SKILL.md,负责打 tag、创建 GitHub Release、触发 CI)。两者分工明确:
greptimedb-release-note:生成 changelog + 精选 Highlights + 准备 docs 博客 PR;greptimedb-release:发布新版本(tag + GitHub Release + docs release-note PR)。
整个生成流程的核心工具链为git cliff(配置见仓库根目录的 cliff.toml)与gh(GitHub CLI),外加用于「减去已发布 PR / 重建贡献者名单」的Python 脚本。所有命令都要求在 greptimedb 仓库的 checkout 目录内执行。
整体流程如下:
- 注入 GitHub token(供
git cliff调 GitHub API 丰富 PR 标题与作者); - 确定上一正式版本(跳过 nightly / rc / beta);
- 选定
git cliff的版本区间(区分 minor 与 patch 两种拓扑); - 生成原始 changelog,减去已在中间 patch 版本发布过的 PR;
- 重新计算
New Contributors与All Contributors; - 与
git log交叉验证; - 手工精选 Highlights(含可运行示例)与 Dashboard 小节;
- 输出到
CHANGELOG-vX.Y.Z.md(不提交); - 生成 docs 仓库博客变体并以 draft PR 提交。
2. 前置条件与远端解析
在开始之前,需要确认以下工具可用:
git cliff:changelog 生成器,其配置为仓库根目录的 cliff.toml;gh(GitHub CLI):用于查询 release 列表、读取 release body、调用 API 获取 PR 信息;先执行gh auth status确认已登录;- Python:第 3、4 节的「减去已发布 PR」与「重建贡献者名单」步骤需要脚本化处理。
2.1 解析指向官方仓库的 remote
仓库可能同时配置了多个远端,文档统一用<remote>代指指向GreptimeTeam/greptimedb的那个(通常是upstream,直接 clone 时可能是origin)。解析命令:
git remote -v | grep -i 'GreptimeTeam/greptimedb' | awk '{print $1}' | head -1后续所有涉及gh的操作都显式带上--repo GreptimeTeam/greptimedb,避免误操作 fork 或个人远端。
2.2 了解工具链的组织方式
在仓库中,Agent 技能统一存放在.agents/skills/<skill-name>/SKILL.md(见 .agents/README.md),Codex 会自动从.agents/skills发现技能,Claude Code 则通过指向该目录的符号链接读取。发版说明技能还有配套的 Agent 接口声明(.agents/skills/greptimedb-release-note/agents/openai.yaml),将技能描述为「Generate GreptimeDB release notes」——这说明该技能的核心能力就是三件事:生成 changelog、精选 highlights、准备 docs release-note PR。
3. GitHub token:注入但永不打印
git cliff需要借助 GitHub API 将 commit 丰富为 PR 标题与作者;当涉及数百个 commit 时,没有 token 会触发 API 限流,导致信息不完整(有 token 时仍会运行,只是可能被限流/缺失数据)。
关键原则:token 以内联方式传入,绝不读取或回显 token:
GITHUB_TOKEN=$(gh auth token) git cliff ...另一种方式是让用户通过 env 文件导出GITHUB_TOKEN(同样不要读取其内容)。无论哪种方式,都不得在日志、输出或对话中打印 token 值。
4. 确定上一版本:跳过 nightly、rc 与 beta
从 release 列表中过滤出正式版本号:
gh release list --repo GreptimeTeam/greptimedb需要忽略的标签形态包括:
*-nightly-*:nightly 版本;-rc.*、-beta.*:候选发布与测试版;- 带构建后缀的标签(如
v1.0.0-rc.2-13cdfa9b5-20260325-1774407105)。
重点关注形如vX.Y.Z的正式标签,然后按版本形态确定「上一版本」:
| 当前要发布的版本 | 上一版本判定规则 | 示例 |
|---|---|---|
PatchvX.Y.Z(Z>0) | 上一版本 =vX.Y.(Z-1) | 发v1.0.2→ 上一版本为v1.0.1 |
新 minorvX.Y.0 | 上一版本 = 最新的vX.(Y-1).* | 发v1.1.0→ 上一版本为最新v1.0.x;发v1.0.0→ 最大的0.x |
务必与用户二次确认这个「上一版本」的判定结果,因为它直接决定后续要减去哪些已发布的 patch PR。
5. 区间选择与拓扑:minor 与 patch 的两种生成路径
这是整个技能中最关键、也最容易出错的环节。核心拓扑事实:
- minor 标签(如
v1.0.0)是main的祖先; - patch 标签(
v1.0.1、v1.0.2)位于release/v1.0分支上,不是main的祖先(它们是 cherry-pick,SHA 不同)。
可用如下命令验证某个标签是否为main的祖先:
git merge-base --is-ancestor <tag> <remote>/main5.1 新 minor(X.Y.0,从 main 切出)
这里有一个容易混淆的要点:git cliff的 base 是上一 minor 的.0标签(如v1.0.0,它是main的祖先),而不是第 4 节确定的「上一版本」(最新的 patch,如v1.0.2)。后者只用于决定要减去哪些 patch PR。
GITHUB_TOKEN=$(gh auth token) git cliff <prev-minor-tag>..<release-commit> --tag vX.Y.0 \ -o /path/CHANGELOG-vX.Y.0.md其中:
base= 上一 minor 标签(如v1.0.0);tip= release commit(release/vX.Y的 tip,通常就是<remote>/main)。
关于 nightly 标签的处理:cliff.toml中配置了ignore_tags正则:
ignore_tags = ".*-nightly-.*|^v[0-9]+\\.[0-9]+\\.[0-9]+(-(alpha|beta|rc)\\.[0-9]+)?-[0-9a-f]{7,}-[0-9]{8}-[0-9]+$"该正则的作用是:忽略 nightly 标签以及带构建后缀的 release 标签(如v1.0.0-rc.2-13cdfa9b5-20260325-1774407105),使这些区间内的 commit 被折叠进下一个可见 release 区块,而不是生成多余的独立标题。
随后减去中间 patch 版本中已发布的 PR:这些 patch(vX.(Y-1).1、.2……)的 main 分支 commit 也落在该区间内,如果不减去会重复列出;而读者关心的是相对最新 patch 的增量。收集 patch release body 中的 PR 集合:
gh release view vX.(Y-1).Z --repo GreptimeTeam/greptimedb | grep -oE 'pull/[0-9]+'然后删除 changelog 中每个#NNNN落在该集合内的条目。技能明确建议:用一个小型 Python 脚本是可靠方式——匹配以*开头的行中的pull/<n>)。
5.2 Patch(X.Y.Z,Z>0,release 分支上的 cherry-pick)
上一 patch 标签是 release 分支的祖先,因此当 cherry-pick 以独立 commit 形式落地时,直接使用普通区间即可:
GITHUB_TOKEN=$(gh auth token) git cliff <prev-patch-tag>..<release-branch-tip> --tag vX.Y.Z -o ...无需额外减去 PR(分支上只包含新的 cherry-pick)。
5.3 常见场景:squashed pick commit
patch 分支常常是一个单独的 squash commit,形如chore: pick fixes and bump version to vX.Y.Z (#NNNN),此时上述普通区间只会生成一条记录。处理步骤:
第一步:找出被 pick 的 PR,读取 squash commit 信息:
git log -1 --format=%B <release-branch-tip>其中每一行* fix: ... (#NN)就是一个被 pick 的 PR。
第二步:两种构建方式二选一(patch 通常只有少量 PR,先询问用户偏好):
方式 (a):在main上生成再过滤——让git cliff产出格式正确的条目(标题、作者、分类):
在
main上按时间顺序定位并排列被 pick PR 的 commit:git log --oneline <remote>/main --grep='#NN1' --grep='#NN2' --reverse第一行是最早的 pick,最后一行是最新的 pick。
对覆盖全部被 pick commit 的
main区间运行 cliff(base = 最早被 pick commit 的父提交,tip = 最新的 pick),然后只保留被 pick 的#NN条目:GITHUB_TOKEN=$(gh auth token) git cliff <oldest-pick>~1..<newest-pick> --tag vX.Y.Z -o /tmp/raw.md原始输出中会包含区间内未被 pick的无关联 PR——需要丢弃它们,然后按第 6 节重建贡献者名单。
方式 (b):手工撰写条目——对于小 patch(以及 API/网络不稳定时)是很好的兜底方案。对每个被 pick 的 PR 获取标题与作者:
gh api repos/GreptimeTeam/greptimedb/pulls/<n>然后手工写出* <title> by [@user] in #NN行和贡献者列表。
兜底原则:无论分支历史多么混乱,统一遵守「识别被 pick 的 PR,只保留这些 PR」的规则。
网络不稳时的补充说明:git cliff会从 GitHub API 拉取仓库完整 commit 历史来做作者信息丰富(即使区间很小,也会分页回溯数千个 commit)。连接不稳时可能中途超时;由于它会对分页结果做缓存,直接重跑直到完成即可——每次重试都会从缓存继续。若持续失败,则回退到方式 (b)。
6. 减去 PR 后重建贡献者名单
cliff是在完整区间上计算New Contributors/All Contributors的,因此删除条目后必须根据剩余的 commit 条目重新计算:
- All Contributors= 从剩余
* ... by [@user] ... in [#NN]行中提取的@user有序集合(剔除dependabot[bot]之类的机器人)。 - New Contributors= 在 All Contributors 基础上,剔除「首次贡献 PR 已被删除」的条目(例如该贡献者唯一落在区间内的 PR 其实已随 patch 发布过)。
这个计算应当放在同一个减去 PR 的脚本中完成,一步到位。
关于贡献者名单的呈现方式,cliff.toml的模板给出了仓库的实际规范:All Contributors按用户名排序并以逗号分隔,且显式跳过dependabot[bot];New Contributors则逐一列出首次贡献者及其 PR 链接。模板中的is_first_time与pr_number字段正是上述计算的输出依据。
7. 验证:与 git log 交叉核对
生成完毕后,用git log <base>..<tip>交叉核对结果:
- 没有已减去 PR 的残留;
- 没有遗漏真正新增的 PR;
- 机械性的
chore: bump version to vX.Y.Z行可选择性删除(询问用户,有人偏好保留)。
8. 人工精选 Highlights 与 Dashboard 小节
这是从「机械 changelog」升级为「可读 release note」的关键步骤。内容插入在Release date:行之后,并参考历史 release body 的写法(gh release view v1.0.0 --repo GreptimeTeam/greptimedb)。
8.1 Highlights 的写作规范
简短引言:精炼、工程师语气,不用营销形容词;
### 👍 Highlights小节:选择少数、深入的亮点,每条都配一个可运行的示例(SQL 或 TOML 配置);示例必须经源码/文档验证:阅读 highlight 对应的 PR 以及 docs 仓库(
GreptimeTeam/docs,通常本地已 checkout)中的相关文档页,并在以下位置校验语法:docs/reference/sql/*.mdconfig/*.example.tomlconfig/config.md
在当前仓库中,这些文件的对应物正是 config/config.md 与 config/standalone.example.toml 等配置文件,以及 docs/rfcs 下的 RFC 文档,可作为示例校验的参照。
不提及实现细节、微小功能、未完成或实验性(尚未 ready)的功能;
必须让用户审阅并编辑 highlights,迭代修改。
8.2 Dashboard 小节
不要只升级版本号就完事。应阅读随版本捆绑的 dashboard 的 PR(gh release view <ver> --repo GreptimeTeam/dashboard后再看关联 PR),描述对用户可见的变更。当前仓库也内嵌了 dashboard 资源(grafana/dashboards 下含 cluster 与 standalone 的 dashboard JSON 及生成脚本 grafana/scripts/gen-dashboards.sh),可帮助理解 dashboard 变更的形态。
9. 输出规范
将结果写入CHANGELOG-vX.Y.Z.md(标题为# vX.Y.Z,由--tag参数产生),不要提交该文件——发版 runbook 会在 release 与 docs PR 完成后删除它(见 .agents/skills/greptimedb-release/SKILL.md 第 4 节:docs PR 打开后即删除本地CHANGELOG-vX.Y.Z.md)。
9.1 changelog 的模板结构
仓库 cliff.toml 中的 Tera 模板定义了最终 changelog 的完整骨架:
- 标题
# {{ version }}与Release date: ...行; - Breaking changes区块(按
breaking属性过滤,独立成节); - 其余 commit 按
group_by(attribute="group")分组,组名来自commit_parsers中定义的分组标签:🚀 Features、🐛 Bug Fixes、🚜 Refactor、📚 Documentation、⚡ Performance、🎨 Styling、🧪 Testing、⚙️ Miscellaneous Tasks、🛡️ Security、◀️ Revert; - 每条目格式为
* {{ pr_title }} by @user in #NN; - 末尾为New Contributors与All Contributors两个区块。
模板中几个值得注意的配置点:
conventional_commits = true # 按 Conventional Commits 解析 filter_unconventional = true # 过滤非 conventional commit commit_parsers = [ ... ] # 正则 → 分组映射 protect_breaking_commits = false filter_commits = false # 不过滤未匹配的 commit sort_commits = "oldest" # 组内按新旧排序其中^chore\(release\): prepare for、^chore\(deps.*\)、^chore\(pr\)、^chore\(pull\)等模式被配置为skip = true,会在生成时直接跳过这些机械 commit。
10. docs 仓库博客变体与 draft PR
发布说明还会以博客形式发布到GreptimeTeam/docs仓库。
10.1 准备工作
- 询问用户其本地
GreptimeTeam/docscheckout 路径;若没有,可提供 clone 方案(git clone git@github.com:GreptimeTeam/docs.git <path>); - 文件名为
blog/release-X-Y-Z.md(版本号用短横线连接,参考blog/release-1-0-0.md)。
10.2 内容格式
内容 = docs frontmatter + GitHub release body,且# vX.Y.Z这个 H1 必须紧跟在 frontmatter 之下。博客 frontmatter 没有title:字段,Docusaurus 会用这个 H1 作为页面标题和侧边栏标签——省略它会导致页面以文件名渲染(如release-1-1-0而非v1.1.0)。
参考模板:
--- keywords: [release, GreptimeDB, changelog, vX.Y.Z] description: GreptimeDB vX.Y.Z Changelog date: YYYY-MM-DD --- # vX.Y.Z Release date: ...10.3 不打扰 docs 工作区:使用 git worktree
docs 的工作区可能有无关的 WIP——不要动它,用origin/main创建独立的 worktree:
git -C <docs> fetch origin main git -C <docs> worktree add -b chore/X.Y.Z-release-note /tmp/docs-release-note origin/main10.4 遵循 PR 模板并创建草稿 PR
- 阅读并遵循当前 docs 仓库的 PR 模板(
.github/pull_request_template.md),填写所有必需章节,审阅者负责的 checklist 保持未勾选;不要依赖旧模板中硬编码的章节名; - 带 sign-off 提交、推送、创建draftPR,然后移除 worktree:
git -C /tmp/docs-release-note add blog/release-X-Y.Z.md git -C /tmp/docs-release-note commit -s -m "docs: add X.Y.Z release note" git -C /tmp/docs-release-note push -u origin chore/X.Y.Z-release-note gh pr create --draft --repo GreptimeTeam/docs --base main --head chore/X.Y.Z-release-note \ --title "docs: add X.Y.Z release note" --body-file <template-filled body> git -C <docs> worktree remove /tmp/docs-release-note已知坑:如果 token 缺少read:org权限,gh pr edit/create可能报 org-scope 错误。此时改用 REST 直接编辑 body:
gh api repos/GreptimeTeam/docs/pulls/<n> -X PATCH -F body=@body.md11. 与发版 Runbook 的衔接
生成 changelog 只是完整发布链路的一环。配合 .agents/skills/greptimedb-release/SKILL.md 中的 runbook,完整流程为:
- 由版本号推断分支(
v1.0.x→release/v1.0;新 minorX.Y.0从main切出); - 校验 Cargo workspace 版本与待发布版本一致;
- 用本技能生成并精选 changelog;
gh release create创建 GitHub Release(不要预先创建 tag,创建 release 即创建 tag 并触发 tag-push CI 构建二进制,耗时约数小时;默认以--prerelease标记「构建中」,CI 成功后清除);- 立即打开 docs 草稿 PR(无需等待 CI),然后删除本地 changelog 文件;
- CI 构建完成后核对
isPrerelease与assets,并按「是否最新版本」决定对latest标记的处理。
12. 小结
GreptimeDB 的 release note 生成是一套高度工程化的流程,核心经验可归纳为:
- 拓扑优先:先搞清 minor 标签是
main祖先、patch 标签在 release 分支上,再决定区间与减除策略; - 减除防重复:minor 发布时务必减去中间 patch 已发布的 PR,读者只关心相对最新 patch 的增量;
- 脚本保可靠:PR 减除与贡献者重建用 Python 脚本实现,避免手工遗漏;
- 人工精选升华:机械 changelog 之外,用带可运行示例的深度 Highlights 让发布说明真正可读;
- 工具链纪律:token 只注入不回显、changelog 不提交、docs 工作区用 worktree 隔离、PR 走 draft。
这套流程的所有实现细节均沉淀在仓库的 .agents/skills/greptimedb-release-note/SKILL.md 与根目录 cliff.toml 中,是理解 GreptimeDB 社区发版节奏与工具链的最佳起点。
【免费下载链接】greptimedbThe open-source observability database. One columnar engine for metrics, logs, and traces, on object storage.项目地址: https://gitcode.com/GitHub_Trending/gr/greptimedb
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考