发布说明实践

缺陷修复发布说明:怎样写出读者真正会用的条目

阅读约 1 分钟

好的缺陷修复发布说明,描述的是用户看到了什么出错,而不是代码哪里出了错。每一条都要说明谁受到了影响、从什么时候开始、修复是否彻底,以及读者是否需要做什么,哪怕只是一句”无需任何操作”。

大多数团队都是直接从提交信息里抄一行。下面的表格给出六个改写示例,表格之后的各节则解释其中的规则。

修改前(提交信息)修改后(症状)
Fixed null pointer in export handler当项目没有标签时,导出不再失败并提示”出错了”。请重新运行自 9 月 3 日以来失败的所有导出。
Resolved race condition in sync worker在几秒钟内于两台设备上所做的编辑,不再互相覆盖。无需任何操作。
Fix timezone bug定时报表现在会在你设定的时间运行。自 8 月 12 日以来,UTC 以东的账户看到的报表最多提前了一天。无需更改任何设置。
Patched XSS in comment renderer安全修复:一条精心构造的评论可能在其他用户的浏览器中运行脚本。请今天就升级到 4.2.1。我们在日志中没有发现被利用的迹象。
Fixed regression from 4.1.0包含连字符的查询又可以搜索了。该问题出现在 4.1.0,已在 4.1.1 中修复。
Bug fixes and performance improvements请说明具体是哪些。见最后一节。

如何在发布说明里写一条缺陷修复?

先用用户自己的话写症状,再写谁受到影响、从什么时候开始,然后写修复的状态,最后写要采取的行动。通常一两句话就够了。代码层面的原因应该写在 pull request 里,工程师会去那里找。

读者扫读时只找一件事:“这是我遇到的吗?“四个部分几乎涵盖了所有条目:

  1. **症状。**屏幕上、API 响应里或者发票上出现了什么。如果有错误文字,就原样引用,因为人们会去搜索它。
  2. **范围。**哪个套餐、平台、API 版本或数据形态。“行数超过 50,000 的账户”是可以核对的,“部分用户”则不行。
  3. **时间窗口。**从哪个版本或哪个日期开始,这样读者就能判断昨天那个奇怪的结果是不是这个缺陷造成的。
  4. **行动。**重新运行、重新同步、升级、移除变通方案,或者什么也不用做。

如果用户已经搭建了变通方案,行动那一行就是告诉他们可以删掉它的地方。

发布说明和体验日志有什么区别?

体验日志是完整的、持续更新的变更记录。发布说明则是针对一次发布、经过挑选和改写的消息,写给那些要判断是否值得关心的人。就缺陷修复而言,体验日志列出每一项修复,而发布说明则以读者可能注意到的那些修复为主。

工具提示里的一个错别字,只需要写进体验日志。发票上的税率错误,则两边都要写。完整的区分见体验日志与发布说明的区别,一套好的发布说明应有的样子见如何写出用户真正愿意花时间读完的发布说明。

Keep a Changelog 是记录这一侧一个很方便的约定。它把”Fixed”留给所有缺陷修复,并为漏洞单独设置一个”Security”标题,这与本文面向读者所做的划分是一致的。

缺陷修复算更新吗?

算。缺陷修复改变了产品,所以发布它就是一次更新。按照语义化版本,向后兼容的修复属于补丁版本,例如从 4.2.0 到 4.2.1。

读者是否需要做什么,是另一个问题,说明里应该回答它。一个改变了正确调用方所观察到的结果的修复,已经接近破坏性变更,破坏性变更一文解释了这条界线在哪里。

什么时候一项修复该有独立条目,什么时候算小修复?

当用户可能注意到了这个缺陷、因它损失了时间或数据,或者围绕它搭建了变通方案时,就给这项修复一个独立条目。当团队之外没有人可能看到它时,就把它归入一个简短的”小修复”列表。判断的依据是读者的体验,而不是改动的大小。

有独立条目放进小修复列表
由客户报告,或者很多人遇到一个很少被打开的界面里的外观小毛病
导致输出错误、任务失败或工作丢失错别字、间距、一个没对齐的图标
需要读者采取行动内部工具或管理页面中的修复
近期某个版本带来的回归只在测试环境中出现的故障
涉及账单、权限或数据日志措辞,以及对用户没有影响的依赖升级

分组里的每一行仍然要说点什么:“修复了一些界面问题”只是一个占位符。

如何撰写关于回归的说明?

点明引入它的那个版本,称它为回归,并给出修复它的版本。遇到这个缺陷的人本来就知道它坏了,所以简短而直接的承认,比含糊的措辞对他们更有帮助。

例如:“包含连字符的查询,在 4.1.0 中返回的搜索结果为空。该问题已在 4.1.1 中修复。如果你为了避开连字符而改过查询,现在可以改回来了。”

对于因这个缺陷浪费了一下午的人来说,“提升了搜索的可靠性”读起来像是在回避。如果原因仍在确认中,就如实说明,正如紧急发布说明的指导所说:说明的口气,永远不要比团队实际掌握的更肯定。

如何公布一项安全修复?

要平实地说明严重程度,写出受影响的版本以及修复它们的版本,说明升级有多紧迫,如果存在 CVE 编号,也要写上。只有当用户能够据此采取行动时才公布细节,如果有报告者参与,就遵循协调披露流程。

顺序很重要:报告者私下告知你,你发布修复,等用户可以保护自己时再发布公开说明。CISA’s coordinated vulnerability disclosure process 负责协调漏洞的报告、分析和公开披露。CVE Numbering Authority rules 规定了 CVE 记录如何分配和发布,而在 GitHub 上,repository security advisory 让你可以私下起草公告并申请编号。

一条安全条目通常包含四项事实:

  • 攻击者能做什么,用一句话说明,不附带概念验证。
  • 受影响的版本,以及修复它的版本。
  • 有多紧迫:“今天就升级”还是”在下一次发布时升级”。
  • 你是否看到了被利用的迹象,如果报告者同意,还要致谢。

不要写出利用的步骤。

数据丢失的修复,说明里应该写什么?

说明哪些数据受到了影响,如何判断自己的数据是否受影响,以及能否恢复。在这里”无需任何操作”很少是真的,而读者的第一个问题是”我的数据是不是没了”。

一条可用的条目,要给出丢失数据的条件(“在同步运行期间删除文件夹”)、可能发生的时间窗口、检查的办法(“打开回收站,查找日期在 9 月 3 日到 9 日之间的项目”),以及恢复的途径。如果数据无法恢复,就如实说明。也要直接联系受影响的客户,因为发布说明不应该是某个人得知自己的数据受到影响的唯一地方。

为什么”错误修复与性能改进”是一条糟糕的说明?

它没有给读者任何可以采取行动的东西,还把有人一直在等的修复藏了起来。报告过崩溃的客户,无法判断它是否已经修好,而有变通方案的客户,也无法判断是否该移除它。

有两种坦诚的替代做法。如果一次发布里没有任何读者能注意到的内容,就不要为它发布说明,让体验日志保存记录。如果有修复,就用读者的话把它们列出来:

修改前:
  错误修复与性能改进。

修改后:
  已修复:没有标签的项目无法导出 CSV。
  已修复:深色模式下评论框里的光标不可见。
  更快:包含超过 100 个项目的工作区,
  仪表盘打开得更快了。

缺陷修复说明从哪里来?

它们来自修复这个缺陷的 pull request,以及触发它的那份报告。如果报告者的原话随着修复一起流转,症状就已经写好了一半。

功能请求还是缺陷解释了为什么正确地给报告打上标签,决定了由谁来负责它。在 Changeloop 中,通过小组件提交的缺陷会变成一个带有 bug 标签的 GitHub issue,体验日志条目则从已合并的 pull request 起草,并留给人批准后再发布。手写时,发布说明模板给你同样的条目结构:症状、范围、时间窗口、行动。

FAQ

缺陷修复发布说明应该包含什么? 每一条都应该写明用户看到的症状、谁受到了影响、从哪个版本或哪个日期开始、修复是否彻底,以及读者需要做什么,包括”什么也不用做”。

每一项缺陷修复都应该列在发布说明里吗? 不需要。列出那些用户可能注意到的、让他们损失过时间的或者他们绕开过的修复,并把外观上的或内部的修复归入一个简短的”小修复”列表。体验日志会保留每一项修复,供需要查找的人使用。

如果缺陷是自己引入的,发布说明该怎么写? 说明它是一次回归,点明引入它的版本和修复它的版本,并告诉读者是否可以移除任何变通方案。平实的陈述比委婉的措辞读起来更好。

如何查看自己所用产品的发布说明? 在产品的帮助菜单、页脚或文档里找体验日志或发布说明页面的链接,开源项目则可以看仓库的 releases 标签页。


本文的技术内容未经独立审核。如有错误,请告诉我们,我们会更正。

changeloop 相关页面: 发布说明模板

changeloop
打造闭环 changelog 的团队。用户提出需求,你的团队交付,提出需求的人得知结果。