Zed 发行说明(Release Notes)工作流解析:从 PR 模板到自动化聚合脚本
本文基于 Zed 仓库中的开发文档 release-notes.md,完整梳理 Zed 项目"PR 内 Release Notes 标注 → 每周聚合 → 版本发布"的发行说明工作流,并结合 script/draft-release-notes、script/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-notes 与 script/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 行的完整准则,以下逐条保留并结合脚本行为补充解释:
- 只有用户能"看到或感觉到"差异时才写。纯内部重构、依赖升级、CI 调整等不产生
Release Notes行,填N/A。 - 用 Zed 用户能理解的语言写。不要假设读者懂编辑器内部开发术语;把变化表述为"文本编辑器用户"能感知的功能或行为,而不是实现细节。
- 面向团队的技術细节写在
Release Notes行之上。PR 描述的前半部分(Objective/Solution/Testing 等区块)是给其他工程师看的;Release Notes行以下的内容会被原样搬进公开发布的发行说明,因此不能混杂内部术语。 - 文档类改动一律标注
N/A。修改 docs 不影响用户"看到或感觉到"编辑器本身。 - 新增或修改了设置项、按键绑定(keybinding)的 PR,必须点名该设置/按键。不要把用户引导去翻文档或 PR 详情才能发现这一信息(当然文档本身也应当同步更新)。
- 回退(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)。其工作分为四步:
- 参数校验与 patch 限制。脚本校验版本号必须为三段式数字、通道只能是
stable或preview,并显式注释"目前只能为 patch 版本草拟说明"——若 patch 段为0(即 minor/重大版本),直接退出,因为跨 minor 的说明需要人工整理。 - 浅克隆定位 tag。以
git clone --filter=tree:0 --no-checkout --depth 100克隆目标 tag(stable 通道为vX.Y.Z,preview 通道为vX.Y.Z-pre),再验证上一版本 tagvX.Y.Z-1存在。 - 解析 commit message。执行
git log <priorTag>..<tag> --format=DIVIDER\n%H|||%B,对每条 commit 用正则提取Release Notes:(大小写不敏感)之后、到第一个空行之前的段落,并把段内的软换行折叠为空格——这解释了书写规范里"说明行应是单条可读句子"的原因:脚本会把多行文本压成一行。另外,若说明中还残留模板占位符<public_issue_number_if_exists>,脚本会视为"未写",落入missing桶。 - 分桶输出。按上文表格将每条 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.Z,preview对应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_versionworkflow 执行 minor 版本号提升,并带有与文档"每周三"节奏呼应的检查——脚本用date +%u判断是否周三,非周三会给出 "Zednesdays" 警告并要求手动确认。
端到端流程概览
综合文档与脚本源码,Zed 发行说明的完整链路为:
- 开发者在 PR 中按 模板 填写
Release Notes:(或N/A); - PR 按通道落入
main(preview)或 stable 分支,commit message 中保留该说明; - 版本提升与打 tag(
bump-zed-version/determine-release-channel校验vX.Y.Z[-pre]); - 运行
draft-release-notes在相邻 tag 间抽取、分桶、追加 PR 链接,生成可粘贴的发行说明草稿; - 由 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 源码中逐条对照验证。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00