EmDash Changeset 编写与评审指南:从补丁记录到面向读者的发布文档
【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址: https://gitcode.com/gh_mirrors/emdas/emdash
EmDash 是一个基于 Astro 的全栈 TypeScript CMS,采用 Changesets 工具链管理多包仓库的版本发布与 CHANGELOG 生成。本指南基于仓库根目录下.changeset/README.md的完整规范,结合仓库内config.json配置与真实 changeset 案例,系统讲解何时添加 changeset、如何撰写面向读者的变更描述、如何选择 bump 类型,以及如何像评审文档一样评审 changeset。读完本文,你将掌握为 EmDash 及其子包(如emdash、@emdash-cms/admin、@emdash-cms/cloudflare)提交高质量变更记录的全部实操方法。
Changeset 是什么,为什么它如此重要
在 Changesets 工作流中,一个 changeset 决定了两件事:
- 版本号如何提升:它声明被影响的包和 bump 类型(
patch/minor/major),发布时据此计算新版本号; - CHANGELOG 的正文来源:它的描述会作为该包 CHANGELOG 中的公开文档条目,被读者在决定“要不要升级、怎么升级”时反复阅读。
因此,.changeset/README.md开篇给出的核心写作准则非常关键:
Write and review it for someone who runs the package, not someone who has read the pull request or diff.
即:为“运行这个包的人”而写,而不是为“看过 PR 或 diff 的人”而写。读者没有你的 PR 上下文,他们只能从这段描述判断这次发布是否与自己相关、升级后需要做什么。
仓库的每个变更记录都以 Markdown 文件形式存放在 .changeset/ 目录下,文件名通常是无意义的随机短语(如fuzzy-lions-check.md、quiet-workers-start.md),真正的信息都在文件 frontmatter 与描述正文里。例如:
--- "emdash": minor --- Adds `GET /_emdash/api/health` so external tools can confirm an EmDash site is reachable and whether its plugin registry is enabled.frontmatter 声明了受影响的包与 bump 类型,正文则描述用户可感知的新能力。
何时需要添加 Changeset
必须添加的场景
任何对已发布包行为或 API 的改动都需要 changeset,包括 bug 修复、新特性,以及改变行为的重构。文档中特别强调:没有 changeset 的改动不会触发发布("Without one, the change will not trigger a release")。
多包场景的规则如下:
| 场景 | 规则 |
|---|---|
| 改动涉及多个包 | 只需一个 changeset,在 frontmatter 中列出所有受影响包 |
| 一个 PR 包含多个独立改动 | 可以每个改动一个 changeset,各自成为独立的 CHANGELOG 条目 |
| 多个 PR 共同构建同一特性(如互相依赖的 PR 栈) | 只写一个描述完整用户可见能力的 changeset,放在栈中某一个 PR 里,而不是记录实现顺序 |
| 独立可发布的 PR | 除非发布协调能保证所有 PR 同时发布,否则每个 PR 需要各自的 changeset |
不需要添加的场景
仅涉及文档、测试、CI/工具链、demo 和模板的改动不需要 changeset。原因是这些改动不改变已发布包对外的行为。
这一规则在 .changeset/config.json 中有直接体现——ignore数组明确列出了从发布流程中排除的包,包括各类 demo(@emdash-cms/demo-cloudflare、@emdash-cms/playground)、模板(@emdash-cms/template-blog、@emdash-cms/template-marketing等)、测试用插件(@emdash-cms/plugin-api-test)以及docs包。这些包不参与版本发布,自然也不需要 changeset。
创建 Changeset 的命令
在仓库根目录执行:
pnpm changeset随后编辑生成的 Markdown 文件,在 frontmatter 中由 PR 作者选择受影响的包和 bump 类型。
从.changeset/config.json可以看到该仓库的 Changesets 配置细节:
changelog使用@changesets/changelog-github插件,仓库为emdash-cms/emdash,生成的 CHANGELOG 会关联 GitHub PR/issue;fixed数组将emdash、@emdash-cms/admin、@emdash-cms/auth、@emdash-cms/blocks、@emdash-cms/cloudflare、@emdash-cms/gutenberg-to-portable-text、@emdash-cms/x402、create-emdash绑定为同一版本组——这意味着这些包在发布时会一起提升版本,因此涉及它们的变更通常要写进同一个 changeset;commit: false表示不会自动把 changeset 提交到版本控制;baseBranch为main。
选择 Bump 类型:patch、minor 与 major
在 changeset frontmatter 中需要选择版本提升类型,规则如下:
patch:用于 bug 修复和小改进;minor:用于新的向后兼容特性;major:EmDash 在 1.0 之前不接受majorbump("EmDash does not currently acceptmajorbumps while it is pre-1.0")。
破坏性变更或重大默认值变更需要事先获得维护者批准,并且要使用与维护者商定的包与 bump 策略。这一点在规范中反复出现:不要自行决定破坏性变更的发布方案。
仓库中的真实案例印证了这套规则。例如 .changeset/quiet-workers-start.md 是一个典型的patch:它修复了 Cloudflare Worker 的启动性能问题(懒加载依赖、降低启动 CPU),不改变外部行为,因此使用patch并同时列出@emdash-cms/cloudflare与emdash两个受影响包。而 .changeset/editor-link-search.md 是新增的向后兼容能力(富文本编辑器链接输入框按标题搜索已有内容),因此声明为minor。
以发布行为开头:第一句话就要说清“发生了什么”
规范要求 changeset 描述以现在时动词开头,如Fixes、Adds、Updates、Removes、Deprecates。开篇句子需要做到:
- 当读者能识别时,点名用户可见的 API、选项、命令、组件或行为;
- 说明谁受影响、他们现在能做什么,或描述被修复的可观察问题;
- 描述发布后的行为,而不是文件名、私有函数、重构细节、查询或实现选择。
细节的多少要与影响成正比:
- 一个
patch通常一句具体的话就足够; - 一个重要的
minor特性通常需要包含:能力说明、基本用法、默认值与兼容性、受影响环境,以及读者需要采取的任何行动; - 最重要的能力要放在最前面,不要埋没在附带修复或实现细节之下。
破坏性变更与默认值变更必须“不容误解”
规范强调:Breaking changes and default changes must be unmistakable。必须说明:
- 谁受影响;
- 之前的行为和当前的行为;
- 迁移所需采取的行动;
- 在可能的情况下,如何恢复之前的行为。
优先提供最小配置示例或 before-and-after 示例,而不是笼统的警告。在维护者批准包的发布策略之前,不要提交破坏性变更。
三个完整的撰写示例解析
规范给出了三个可以直接套用的完整示例,下面逐一解析其结构。
示例一:patch 条目——点名命令与可观察问题
--- "emdash": patch --- Fixes `emdash migrate --json` so progress messages go to stderr, allowing scripts to parse stdout as JSON.要点:点名了受影响的命令emdash migrate --json,并描述了脚本作者能观察到的具体问题(进度消息污染了 stdout,导致无法把 stdout 当作纯 JSON 解析)。这正是“为运行包的人而写”的典范——脚本作者读完立刻知道这个修复对自己意味着什么。
示例二:minor 特性——能力、用法与退出码契约
--- "emdash": minor --- Adds `--check` to `emdash migrate` so deployment pipelines can detect pending or unknown migration records without changing the database. Run the check after deploying the application artifact that produced the migration manifest: ```sh pnpm exec emdash migrate --check ``` The command exits with `0` when the database matches the build, `2` when known migrations are pending, and `3` when the database contains migration records unknown to the build. It works with every database adapter supported by the migration manifest.要点:先说明新能力与它的价值(让部署流水线在不修改数据库的情况下检测迁移状态),再给出最小可用命令,然后完整定义退出码契约(0一致、2有已知迁移待执行、3存在构建未知的迁移记录),最后说明适用范围(迁移清单支持的所有数据库适配器)。这类“退出码契约”信息对部署流水线的维护者是关键决策依据。
示例三:经批准的默认值变更——影响与回退路径显式化
--- "emdash": minor --- Updates `memoryCache()` to use a five-minute default TTL instead of one hour, so sites using the in-memory object cache refresh cached pages more frequently after an upgrade. Sites that depend on the previous one-hour lifetime can keep it explicitly: ```ts objectCache: memoryCache({ defaultTtl: 3600 }); ``` #### What should I do? Set `defaultTtl: 3600` before upgrading if the shorter cache lifetime would add unacceptable load to your site.要点:默认值变更被提升为minor(已获批准)。描述包含:前后行为对比(五分钟 vs 一小时)、受影响用户(使用内存对象缓存的站点)、迁移动作(显式设置defaultTtl: 3600)、以及恢复旧行为的方法。文档中还示范了较长条目使用 Markdown 标题的规范——从 h4(####)开始,因为 changeset 会被嵌入到生成的 CHANGELOG 标题之下,使用 h2/h3 会破坏文档层级结构。
破坏性变更的同等要求
规范明确指出,破坏性变更需要同样级别的细节:第一句话点名被移除或改变的 surface,然后给出最小可行的迁移方案。在维护者批准其包与发布策略之前,不得提交破坏性变更。
好与坏的描述对比:把“技术相关”变成“发布文档”
规范给出了三组 diff 对比,直观展示两类描述的区别:
- Fixes a bug in media handling. + Fixes R2 media uploads larger than 10 MB failing before the upload begins.- Refactors `hydrateEntryBylines` to chunk SQL IN clauses. + Fixes D1 errors when loading an entry with more bylines than the database bind-parameter limit.- Updates migration status handling and exit codes. + Adds `emdash migrate --check` so deployment pipelines can detect pending or unknown migrations without changing the database.左侧是“技术相关的散文”,描述了内部机制(重构、chunk SQL IN 子句、处理迁移状态);右侧是“有用的发布文档”,描述用户能观察到的行为变化(R2 上传大于 10 MB 失败、D1 绑定参数超限错误、新增的检查命令)。这正是评审 changeset 时要做的核心判断。
仓库中的真实条目同样遵循这一风格。例如 .changeset/forms-webhook-deferred.md 描述表单 webhook 静默失效的根因与修复:fetch只在传输层错误时 reject,因此 4xx、5xx 以及认证端点重定向后的登录页都被当作“成功”处理、不留痕迹;修复后通过after()注册到 host 保证执行完成,并通过比较最终 URL(而非Response.redirected,因为插件 HTTP 访问自行跟随重定向、总是报告redirected: false)识别重定向场景。而 .changeset/calm-datetimes-normalize.md 则示范了修复类条目如何同时说明迁移行为:所有内容 datetime 以固定毫秒的 UTC ISO 字符串存储,管理端按站点时区转换,API/MCP/CLI 写入要求Z或显式 UTC 偏移;迁移在修改前报告非规范值,遇到夏令时重复/跳过的时段会停止写入并报告需要显式偏移的行。
不要只把解释写在 changeset 里
规范有一条容易被忽略但很重要的要求:
Do not keep useful explanations or examples only in a changeset or PR description. Add them to the canonical feature or upgrade documentation too; the CHANGELOG is usually read once, while the docs remain the reference.
即:不要把有用的解释或示例只留在 changeset 或 PR 描述里。CHANGELOG 通常只被读一次,而官方文档是长期参考。因此,重要的特性或升级说明必须同步写入正式的功能文档或升级文档。
像评审文档一样评审 Changeset
评审 changeset 时,frontmatter 的有效性和技术准确性是必要但不充分的条件("Frontmatter validity and technical accuracy are necessary but not sufficient")。遇到以下情况应要求重写:
- 描述含糊不清;
- 只描述内部机制;
- 读起来像 commit message;
- 把重要能力埋在附带细节之下;
- 无助于读者判断“这次发布对我是否重要”。
正确的做法是:把描述当作文档来评审,与 bump 类型和包列表一并审查。
实践建议:把规范落到 EmDash 日常贡献中
结合上述规范与仓库实际情况,提交 EmDash 变更时建议按以下流程操作:
- 在仓库根目录运行
pnpm changeset生成新的变更文件; - 在 frontmatter 中列出所有受影响包(若涉及
fixed版本组中的包,注意它们会一起发布);bug 修复用patch,向后兼容新特性用minor,1.0 之前不使用major,破坏性变更先与维护者确认策略; - 正文以Fixes / Adds / Updates / Removes / Deprecates开头,点名用户可见的命令、API 或行为,描述发布后的行为而非实现细节;
- 需要时补充最小可用示例与默认值/退出码等契约信息;默认值变更与破坏性变更必须写明前后行为、迁移动作与恢复方法;
- 超过一段的条目用
####及以上标题组织,避免破坏生成的 CHANGELOG 层级; - 把重要的用法说明同步补充到正式文档,而不是只留在 changeset 中。
对于不发布版本的包(见 .changeset/config.json 的ignore列表)以及纯文档、测试、CI/工具链、demo 和模板改动,则无需创建 changeset。
遵循这套规范,EmDash 的每个 CHANGELOG 条目都会成为一份独立可读、信息完整、面向升级决策者的发布文档——这正是.changeset/README.md以及整个 Changesets 工作流想要达成的目标。关于 Changesets CLI 与配置的更多行为细节,可参阅 Changesets 官方文档(仓库内.changeset/config.json即其配置的落地实例)。
【免费下载链接】emdashEmDash is a full-stack TypeScript CMS based on Astro; the spiritual successor to WordPress项目地址: https://gitcode.com/gh_mirrors/emdas/emdash
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考