首页
/ Kong 变更日志自动化实践:changelog 目录的工具链、生成流程与 PR 校验脚本

Kong 变更日志自动化实践:changelog 目录的工具链、生成流程与 PR 校验脚本

2026-09-05 21:42:58作者:冯爽妲Honey

本篇围绕 Kong 仓库中的 changelog/README.md 展开,讲解 Kong 官方如何把"发版变更日志"从手工维护变成一套可重复执行的工具链:如何配置 changelog CLI 工具,如何用一条 make 命令自动生成版本变更日志并创建 PR,以及如何使用 verify-prs 脚本对比任意两个修订版本、找出缺少变更日志条目的 PR。读完本文,你可以完整复现 Kong 的变更日志生成与核对流程,并理解其 Makefile 各阶段与校验脚本的底层调用逻辑。

一、changelog 目录的结构约定

理解工具链之前,先看一下 changelog/ 目录的组织方式,这是整套流程的数据基础:

变更条目的字段格式由 changelog/changelog-template.yaml 定义:

message: # "Description of your change" (required)
type: # One of "feature", "bugfix", "dependency", "deprecation", "breaking_change", "performance" (required)
scope: # One of "Core", "Plugin", "PDK", "Admin API", "Performance", "Configuration", "Clustering", "Portal", "CLI Command" (optional)

其中 message 必填,type 必填且取值限于六种(特性、缺陷修复、依赖升级、弃用、破坏性变更、性能优化),scope 可选并用于在生成的 Markdown 中做二级分组。

生成后的 Markdown 按 type 分节、再按 scope 分子节。以 3.9.0.md 为例,可以看到 ### Deprecations### Dependencies### Features 等章节,每个条目下面还附带对应的 GitHub Issue 链接(由 --github-issue-repo 参数生成)以及 Jira 链接(由 --with-jiras 参数生成)。根目录的 CHANGELOG.md 在发布时会把这些条目汇编进去,其 ## Unreleased 小节也明确指向 changelog/unreleased

二、环境准备:changelog 二进制与 GITHUB_TOKEN

根据 changelog/README.md 的 Setup 章节,需要准备两样东西:

  1. changelog 二进制工具。从 Kong 官方的 gateway-changelog 项目 0.0.2 版本 release 下载(README 同时给出了 release-helper 中的脚本来源作为替代),并将其所在目录加入 PATH

    ~ $ PATH="/path/to/changelog:$PATH"
    
    ~ $ changelog
    changelog version 0.0.2
    
  2. GITHUB_TOKEN 环境变量,供后续所有 GitHub API 调用鉴权:

    ~ $ echo $GITHUB_TOKEN
    

注意版本约束:Makefile 中定义了 REQUIRED_VERSION := 0.0.2check_version 目标会把 changelog -v 输出的版本号解析出来,若仍为旧的 0.0.1 会直接报错要求升级——这意味着 0.0.1 的旧二进制无法驱动本流程。

三、一条 make 命令生成变更日志 PR

3.1 命令与参数

在仓库的 changelog/ 子目录下执行:

~ $ pwd
/Users/zachary/workspace/kong/changelog

~ $ make BASE_BRANCH="release/3.6.x" VERSION="3.6.0"

README 对三个参数的解释:

  1. BASE_BRANCH:变更日志 PR 所基于的远端分支,同时作为 merge base。本地仓库不要求检出在该分支上——Makefile 会自己 git fetch --prune 后基于 origin/$(BASE_BRANCH) 创建分支。
  2. VERSION:要生成变更日志 PR 的目标版本号。README 说明它"可以是任意字符串,只要你清楚自己在做什么(例如测试用途)"。
  3. DEBUG:显示调试输出,默认 false,最终以 --debug=$(DEBUG) 传给 changelog generate

此外 Makefile 中还定义了默认值 BASE_BRANCH ?= release/3.6.xVERSION ?= 3.6.0,以及固定的 OWNER_REPO := Kong/kongUNRELEASED_DIR ?= unreleased

3.2 Makefile 的五个阶段

all 目标按序执行五个阶段:check_tools check_version create_branch generate push_changelog create_pr。此外还有一个 no_pr 目标,跳过最后一步 PR 创建(只推送分支),适合只想本地验证生成结果、不立即开 PR 的场景。逐阶段看源码实现:

check_tools —— 依赖自检REQUIRED_TOOLS := git changelog curl jq,用 command -v 逐个检查,任一缺失即 $(error ...) 终止;同时检查 GITHUB_TOKEN 是否设置。这对应 README 中"依赖 curljq 等工具,任一不满足则拒绝创建或更新变更日志 PR"的说法。

check_version —— 版本自检。前面提到的 0.0.1/0.0.2 判断逻辑。

create_branch —— 准备分支

@git fetch --prune
@git submodule update --init --recursive
@git checkout -B $(BRANCH_NAME) $(ORIGIN_BRANCH)

其中 BRANCH_NAME := generate-$(VERSION)-changelog,例如 generate-3.6.0-changelogcheckout -B 保证该分支存在则重置、不存在则新建,起点是 origin/$(BASE_BRANCH)——这就是"本地不要求检出 base 分支"的原因。

generate —— 汇编 Markdown。核心命令(针对 kong 部分,kong-manager 同理):

changelog --debug=$(DEBUG) generate \
    --repo-path . \
    --changelog-paths 3.6.0/kong,unreleased/kong \
    --title Kong \
    --github-issue-repo Kong/kong \
    --github-api-repo Kong/kong \
    --with-jiras \
    >> 3.6.0.md

几个参数值得注意:

  • --changelog-paths 同时指向"版本目录 + unreleased 目录",即先把 VERSION/kong 下已有条目和 unreleased/kong 下全部新条目一起纳入汇编;
  • --github-issue-repo 决定条目中的 Issue/PR 链接指向哪个仓库(kong 部分指向 Kong/kong);
  • Makefile 中有个细节:kong-manager 部分的生成使用 --title Kong-Manager--github-issue-repo Kong/kong-manager(条目归属 kong-manager 仓库),但 --github-api-repo 仍统一为 Kong/kong
  • 只有当对应目录下确实存在 .yml 文件时(nullglob 判断)才执行生成,避免产出空标题。

push_changelog —— 移动条目并推送。这一步完成了"未发布条目已发布"的落库动作:

@mkdir -p $(VERSION)
@mv -f $(VERSION).md $(VERSION)/
@for i in kong kong-manager ; do \
    mkdir -p $(UNRELEASED_DIR)/$$i ; mkdir -p $(VERSION)/$$i ; \
    git mv -k $(UNRELEASED_DIR)/$$i/*.yml $(VERSION)/$$i/ ; \
    touch $(UNRELEASED_DIR)/$$i/.gitkeep ; touch $(VERSION)/$$i/.gitkeep ; \
done
@git add .
@git commit -m "docs(release): generate $(VERSION) changelog"
@git push -fu origin HEAD

即:把 3.6.0.md 移入 3.6.0/ 目录,把所有 unreleased/{kong,kong-manager}/*.ymlgit mv 迁入 3.6.0/{kong,kong-manager}/,留下 .gitkeep 保证空目录可被 git 跟踪,最后以固定提交信息 docs(release): generate <VERSION> changelog 提交并推送。

create_pr —— 创建或复用 PR,调用 create_pr 脚本。该脚本的逻辑很清晰:先查询 repos/<owner>/pulls?state=open&base=<BASE_BRANCH>&head=<BRANCH_NAME>,若已存在同 head 分支的 open PR 则打印 "Updated existing PR"(因为刚推送过新提交,PR 自动更新);否则调用创建 PR 接口,标题为 docs(release): generate <VERSION> changelog。这正好解释了 README 中"该命令会创建新的变更日志 PR 或更新已有 PR;若之后又有带 changelog 的功能 PR 合入,请再次重复执行该命令"的说明——重复执行时 unreleased 目录里积累了新条目,generate 会重新汇编并更新同一个 PR。

四、verify-prs:开发 PR 的批量校验脚本

verify-prs 是同一 README 的第二个工具。给定两个任意修订(tag、分支或 commit hash),它会列出:全部提交、全部 PR、缺少 changelog 条目的 PR,以及疑似未同步到 EE 的 CE PR(CE2EE 检查,实验性)。

4.1 用法与参数

~ $ changelog/verify-prs -h

README 给出的示例:

changelog/verify-prs --org-repo kong/kong --base-commit 3.4.2 --head-commit 3.4.3 [--strict-filter] [--bulk 5] [--safe-mode] [-v]
# 或
ORG_REPO=kong/kong BASE_COMMIT=3.4.2 HEAD_COMMIT=3.4.3 changelog/verify-prs

从脚本源码 changelog/verify-prs 整理完整参数表(比 README 更全):

参数 说明
-h, --help 打印帮助信息并退出
-v, --verbose 打印调试信息(开启 set -x
--org-repo <repo> GitHub 仓库,如 kong/kongkong/kong-ee,也可用环境变量 ORG_REPO 指定
--base-commit <rev> 起始修订(tag、分支或 hash)
--head-commit <rev> 结束修订
--strict-filter CE2EE 检查启用更严格过滤:关联的 EE PR 标题必须包含 cherry 关键词(源码中标注 Recommended)
--safe-mode CE2EE 的交叉引用检查改为逐个串行执行,覆盖 --bulk(源码中标注 Recommended)
--bulk N parallel 的并发任务数,默认 5;源码提示应结合 CPU 核数调整,过高可能触发 GitHub API 限速

硬性环境要求(check_tools 函数):必须导出 GITHUB_TOKEN;Bash 版本不低于 5;系统装有 jq 和 GNU parallel。另外注意两点源码中的保护逻辑:--bulk 必须为正整数,且 ≥ 8 时会打印"并发过高、可能触及 GitHub API rate limit"的警告。

4.2 执行流程与输出

脚本的 main 按四步执行:get_commits → get_prs → check_changelog → check_ce2ee,对应输出五类结果(控制台与本地文件双份):

  1. Commits:通过 GitHub Compare API(repos/<repo>/compare/<base>...<head>)分页拉取全部提交,README 示例输出显示"number of commits: 280 / number of pages: 6"。
  2. PRs:将提交 SHA 作为搜索条件批量查询 Search Issues API(repo:<repo> type:pr is:merged <sha...>),每个查询最多拼 17 个 SHA,避免搜索串过长。
  3. PRs without changelog:对每个 PR 调用 pulls/<n>/files 接口取文件列表,若 PR 修改的文件中没有匹配 changelog/unreleased/kong*/*.yml 的条目,则列入"缺 changelog"名单——这正是与第三节的"每个 PR 附带 .yml"约定形成闭环的核对手段。
  4. CE PRs without cherry-pick label / cross-referenced EE PRs:仅当 --org-repo kong/kong 时执行。检查 PR 是否带 cherry-pick kong-ee 标签(issues/<n>/labels),或 timeline 中是否交叉引用了已合入的 EE 仓库 PR(issues/<n>/timeline);--strict-filter 时额外要求 EE PR 标题含 cherry。README 也明确提示:这只是实验性的快捷校验,"开发者可能并未遵循 CE2EE 规范",因此结果用于快速核对多数 PR 而非绝对判定。

所有结果写入 mktemp -d 创建的临时目录(commits.txtprs.txtprs_no_changelog.txt 等),脚本结尾会提醒"记得删除临时目录";异常退出时 cleanup trap 会自动清理,Ctrl-C 可随时中断。README 给出的运行示例(--base-commit 3.4.0 --head-commit 3.5.0)展示了完整的输出形态:统计信息 → PR 列表 → 三类待核实 PR 列表 → 五个结果文件路径。

五、实践建议与小结

  • 执行时机:变更日志 PR 应在"功能 PR 陆续合入 base 分支之后"重复执行 make,因为每次执行都会把当时 unreleased/ 下的全部条目汇编进 PR;新条目合入后再跑一次即可增量更新同一 PR。
  • 可重复性create_branch 使用 git checkout -Bcreate_pr 先查后建,整个流程幂等,可安全重试。
  • 依赖清单gitchangelog(≥0.0.2)、curljqGITHUB_TOKENverify-prs 额外要求 Bash ≥ 5 与 GNU parallel
  • 核对闭环unreleased 约定(changelog-template.yaml)→ 生成(Makefile)→ 校验(verify-prs)构成一个完整闭环:约定决定 .yml 格式,生成把 .yml 汇编为版本 Markdown 并迁移文件,校验则回溯两个修订之间的所有 PR、揪出漏写条目的 PR。

这套流程让 Kong 每个版本的变更日志(如 3.9.0.md)既保持逐条可追溯到 PR/Issue/Jira,又无需发布时手工拼写——所有条目在开发阶段就随 PR 进入仓库,发布只是"汇编 + 移动文件"两步机械操作。

登录后查看全文
热门项目推荐
相关项目推荐