首页
/ Zed 发行说明(Release Notes)工作流解析:从 PR 模板到自动化聚合脚本

Zed 发行说明(Release Notes)工作流解析:从 PR 模板到自动化聚合脚本

2026-09-06 17:31:08作者:裴锟轩Denise

本文基于 Zed 仓库中的开发文档 release-notes.md,完整梳理 Zed 项目"PR 内 Release Notes 标注 → 每周聚合 → 版本发布"的发行说明工作流,并结合 script/draft-release-notesscript/get-release-notes-since 等仓库内真实脚本源码,讲清每条书写规范的背后机制。读完后你能掌握:如何在自己的 PR 中正确填写 Release Notes,以及这套纯文本约定是如何被脚本解析、过滤、汇总进正式 Release 描述的。

起点:PR 模板中固定的 “Release Notes” 区块

Zed 的发行说明不是发布前人工撰写的,而是在每次合并请求(PR)提交时就地标注。每当打开一个 PR,PR 描述会按照 PR 模板 自动填充,其末尾固定保留如下区块:

...

Release Notes:

- N/A _or_ Added/Fixed/Improved ...

完整的 PR 模板 还包含 Objective(目标与 Fixes #X 关联 issue)、Solution(方案说明)、Testing(测试情况)、Self-Review Checklist(自查清单,涵盖 diff 质量、unsafe 注释、UI 规范、测试覆盖与性能影响)以及可选的 Showcase(视觉变化的截图/GIF/视频演示区)等章节。其中真正被发行说明流水线消费的只有最后一行 Release Notes: 及其下方内容——这是整套工作流的"数据契约"。

每周聚合:Wednesday 的 preview 通道变更收集

文档描述的核心节奏是:每周三,团队运行 get-preview-channel-changes 脚本,收集所有落入 preview 通道的 PR 的 Release Notes 行。该脚本的输出规则是:

  • 输出 Release Notes 行以下的全部内容
  • 附带元数据,例如 PR 作者(当作者不是 Zed 团队成员时署名)以及 PR 链接。

需要说明的是:在当前仓库快照中,文档链接指向的 script/get-preview-channel-changes 这一确切文件名已不存在(检索仓库仅命中文档自身引用),但同一工作流的另外两个环节脚本仍保留在仓库中,即 script/draft-release-notesscript/get-release-notes-since,它们完整呈现了"从 commit message 提取 Release Notes 行"的解析与聚合逻辑,可作为理解该工作流的直接证据。

N/A 约定与跳过逻辑

文档明确:如果填 N/A,脚本会完全跳过该 PR。这不是口头约定,而是脚本里硬编码的分支。在 draft-release-notes 中可以看到对应实现:

if (commit.releaseNotes == "") {
  missing.push("- MISSING " + commit.firstLine + " " + link);
} else if (commit.releaseNotes.startsWith("- N/A")) {
  skipped.push("- N/A " + commit.firstLine + " " + link);
} else {
  releaseNotes.push(notes);
}

三个桶的语义非常清晰:

触发条件 含义
missing commit message 中 Release Notes: 下方为空 漏写,需要人工补查
skipped - N/A 开头 无用户可感知变化,正式跳过
releaseNotes 其余情况 进入正式发行说明

此外,脚本还会把 PR 编号链接追加到说明行末尾((#pr)),对 cherry-pick 提交识别 (cherry-pick #N) 标注,对直接 commit(无 PR 编号)则回退到 commit 链接——这保证了发行说明中每一条都能回溯到具体变更。

书写规范:完整继承文档的七条准则

release-notes.md 给出了撰写 Release Notes 行的完整准则,以下逐条保留并结合脚本行为补充解释:

  1. 只有用户能"看到或感觉到"差异时才写。纯内部重构、依赖升级、CI 调整等不产生 Release Notes 行,填 N/A
  2. 用 Zed 用户能理解的语言写。不要假设读者懂编辑器内部开发术语;把变化表述为"文本编辑器用户"能感知的功能或行为,而不是实现细节。
  3. 面向团队的技術细节写在 Release Notes 行之上。PR 描述的前半部分(Objective/Solution/Testing 等区块)是给其他工程师看的;Release Notes 行以下的内容会被原样搬进公开发布的发行说明,因此不能混杂内部术语。
  4. 文档类改动一律标注 N/A。修改 docs 不影响用户"看到或感觉到"编辑器本身。
  5. 新增或修改了设置项、按键绑定(keybinding)的 PR,必须点名该设置/按键。不要把用户引导去翻文档或 PR 详情才能发现这一信息(当然文档本身也应当同步更新)。
  6. 回退(revert)类 PR 分两种情况处理
    • 被回退的变更已经随版本发布:必须写一条 Release Notes 说明回退原因,因为对用户而言这是破坏性变化(breaking change);
    • 被回退的变更尚未发布:应回到原 PR,把它的 Release Notes 行改为 N/A——否则聚合脚本只认"最终落地 commit 的说明",原 PR 的行仍会被收集进来,"release notes compiler 可能不知道该如何跳过它"。

第 6 条解释了为什么 N/A 不只是"省略",而是一种显式的跳过信号:脚本的 startsWith("- N/A") 判断(见上文)依赖它来区分"漏写"与"主动跳过"。

源码级剖析:聚合脚本如何工作

draft-release-notes:从两个 tag 之间的 commit 中抽取说明

script/draft-release-notes 是一个 Node 脚本,用法为 draft-release-notes <version> {stable|preview}(例如 draft-release-notes 0.220.3 stable)。其工作分为四步:

  1. 参数校验与 patch 限制。脚本校验版本号必须为三段式数字、通道只能是 stablepreview,并显式注释"目前只能为 patch 版本草拟说明"——若 patch 段为 0(即 minor/重大版本),直接退出,因为跨 minor 的说明需要人工整理。
  2. 浅克隆定位 tag。以 git clone --filter=tree:0 --no-checkout --depth 100 克隆目标 tag(stable 通道为 vX.Y.Z,preview 通道为 vX.Y.Z-pre),再验证上一版本 tag vX.Y.Z-1 存在。
  3. 解析 commit message。执行 git log <priorTag>..<tag> --format=DIVIDER\n%H|||%B,对每条 commit 用正则提取 Release Notes:(大小写不敏感)之后、到第一个空行之前的段落,并把段内的软换行折叠为空格——这解释了书写规范里"说明行应是单条可读句子"的原因:脚本会把多行文本压成一行。另外,若说明中还残留模板占位符 <public_issue_number_if_exists>,脚本会视为"未写",落入 missing 桶。
  4. 分桶输出。按上文表格将每条 commit 归入 releaseNotes / skipped / missing;若没有任何用户可感知的变更,输出 "No public-facing changes in this release" 并附 tag 区间 compare 链接,否则直接输出可粘贴的 Markdown 列表。

版本元数据:通道、tag 与发布节奏

发行说明并非孤立环节,它附着在 Zed 的双通道版本体系上,仓库中另有三个脚本佐证这一流程:

  • script/determine-release-channel:在 GitHub Actions 中读取 crates/zed/RELEASE_CHANNEL 与 crate 版本号,校验 tag 命名必须匹配通道——stable 对应 vX.Y.Zpreview 对应 vX.Y.Z-pre,不匹配即中止发布。这与 draft-release-notes 中的 -pre 后缀规则、以及 get-release-notes-since 中以 tagName.includes("-pre") 区分预览/稳定 release 的逻辑完全一致。
  • script/get-release-notes-since:通过 GraphQL 查询指定日期区间内的已发布 release,按 -pre 后缀拆分 preview/stable 两组,再把"全部 stable release + 最新一个 preview release"倒序拼接输出,用于生成跨区间的汇总说明。
  • script/bump-zed-version:触发 bump_zed_version workflow 执行 minor 版本号提升,并带有与文档"每周三"节奏呼应的检查——脚本用 date +%u 判断是否周三,非周三会给出 "Zednesdays" 警告并要求手动确认。

端到端流程概览

综合文档与脚本源码,Zed 发行说明的完整链路为:

  1. 开发者在 PR 中按 模板 填写 Release Notes:(或 N/A);
  2. PR 按通道落入 main(preview)或 stable 分支,commit message 中保留该说明;
  3. 版本提升与打 tag(bump-zed-version / determine-release-channel 校验 vX.Y.Z[-pre]);
  4. 运行 draft-release-notes 在相邻 tag 间抽取、分桶、追加 PR 链接,生成可粘贴的发行说明草稿;
  5. script/create-draft-release 通过 gh release create(preview 通道追加 -p 参数)把草稿落为 GitHub Release 描述。

实践清单

  • 提 PR 时永远保留 Release Notes: 行,无用户可感知变化就填 - N/A,不要留空——留空会被脚本归入 missing 桶。
  • 说明行写给"编辑器用户",写给工程师的内容放到该行以上。
  • 新增/修改设置或 keybinding 时,在说明中直接点名具体项名。
  • Revert 已发布的变更:写说明并解释原因;Revert 未发布的变更:把原 PR 的说明改为 N/A
  • 说明段落内部避免硬换行依赖——脚本会把 Release Notes: 之后到首个空行之间的软换行折叠为空格。

以上规则均可在 docs/src/development/release-notes.md 原文与 script/draft-release-notes 源码中逐条对照验证。

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