稳定发布版本
最后更新于:2022-04-01 15:45:30
# 稳定发布版本
*稳定化*是让一个发布分支进入发布状态的过程;也就是决定哪些变更将会进入发布版本,并以此为根据修整分支的内容。
“决定”一词有许多潜在的不幸。在协作软件项目中最后一分钟特性冲击是非常常见的现象:当开发者看到软件发布将要发生,他们便混乱的结束当前的变更,不希望错过这班船。当然,这是在发布时你最不想看到的场面。如果人们能在比较以舒适的节奏,无需担心变更是进入这个版本还是下一个版本时完成这个特性,效果会更好。设法在最后一分钟进入发布的变更越多,代码就越不稳定,而且(通常是)也会造成更多的新bug。
大多数软件工程师认可在稳定阶段,变更进入发布版本线时使用严苛标准的理论。很明显,对于严重bug,尤其是没有临时解决办法的bug的修正应该进入。文档更新以及错误信息修改(除非是被认为是界面的一部分,并必须保持稳定的信息)也没问题。许多项目也允许特定类型的低风险或非核心变更在稳定期进入,并提供评估风险的正式指导。但是没有正式的文档可以回避对于人们判断的需要。在很多情况下项目需要为是否将哪个变更纳入发布作出决定。危险的是因为每个人都希望看到自己喜欢的变更进入发布版本,并会激发足够的人赞成这个变更,而不会激发足够的反对者。
因此,稳定一个发布版本也就是要创建一种说“不”的机制。对于开源项目来说,技巧在于如何能在说“不”的同时,尽可能避免造成过多的情绪伤害或失望的开发者,并且还要防止在发布版本中漏掉真正需要的变更。当然有许多不同的方法。可以很容易的设计一个满足这个标准的系统,只要项目能够将其视作重要的标准。在广阔的范围中,这里我仅仅介绍两种最流行的系统,希望这不会让你失去在项目中发挥创造性的激情。有足够多的其他方式也是可能的;但这两个是我在实践中使用过的。
### 发布所有者独裁
团队认可让某人成为*发布所有者*。这个人可以最终确定进入发布版本的变更。当然,有研讨和辩论也是正常和可以设想的,但是最后团队必须赋予所有者足够的权威作出最终的决定。对于此类系统,必须选出一个合适的人,具备理解所有变更的技术能力,具备在避免伤害过多感情的情况下将讨论引入发布的社会威望和社交技巧。
发布所有者场景会说“我不认为这个变更有什么错误,只是我们没有足够的时间测试,所以不能进入这个发布版本。”如果发布所有者对于项目具备广泛的技术知识将会非常有益,这样可以解释为什么这个变更会潜在的导致不稳定性(例如,当与软件的其他部分交互时,或移植性考虑等)。人们有时会为这类决定辩护,或者质问什么样的变更没有这种风险。这种对话不需要是对抗性的,只要发布所有者认为所有的论点都是客观的,而不是条件反射式的坚定自己的立场。
需要注意的是发布所有者与项目领导不必是同一个人(如果有项目领导的话,见[Chapter 4, *社会和政治的基础架构*](# "Chapter 4. 社会和政治的基础架构")的[the section called “慈善独裁者”](# "慈善独裁者"))。实际上,有时要确保他们*不是*同一个人。成为一个优秀项目领导的技巧与成为优秀发布所有者的技巧并不一定相同。在有些时候,与发布过程同等重要的是能有一个人可以成为项目领导判断力的平衡力量。
发布所有者角色与较弱独裁者角色的比较本章后面的[the section called “发布经理”](# "发布经理")。
### 变更表决
发布所有者独裁方式的另一个极端就是为进入发布的变更进行表决。然而,因为发布稳定化最重要功能是*排除*变更,所以势必要设计一种表决系统,只有在大多数开发者表示正面意见时才将变更纳入发布。只有比简单多数更多的赞成才可以引入一个变更(见[Chapter 4, *社会和政治的基础架构*](# "Chapter 4. 社会和政治的基础架构")的[the section called “谁进行表决?”](# "谁进行表决?"))。否则,一个人提出,没有人反对,一个变更就足以进入发布,一个不幸的变化就是每个开发者都会提出自己的变更,而且处于防止他人报复的原因,他们也不会再反对其他人提出的变更。为了避免这个情况,必须安排一些开发者组成子团队,起到将变更纳入发布的协作作用。这并不是意味着让更多的人评审每个变更,而是为了减少每个单独的开发者在反对某个变更时的犹豫,因为她知道赞成该变更的所有人不会将她的反对意见当作人身攻击。子团队参与的人数越多,讨论就会更加集中与变更本身,而不会是关于某个人。
我们在Subversion项目中使用的系统达到了非常好的平衡,所以我在这里将会推荐它。为了让一个变更进入发布分支,必须至少有3位开发者要投票赞成它,而且没有反对者。一个单独的“反对”票足以阻止变更的进入;在发布场景中一个“反对”票等同于否决票(见[the section called “否决权”](# "否决权"))。很自然,这类表决必须伴随着辩护意见,而且如果有足够多的人认为辩护毫无道理,也可以发起一次针对该变更的特别表决。在实践中,这种情况还没有发生过,我也不认为将会发生。人们面对发布时总是趋向于保守,当人们感到可以否决某个变更时,通常是因为有了足够好的理由。
因为,发布规程故意倾向于保守,所以否决时的辩护有时是出于程序上的原因,而非技术上的。例如,一个人认为某个变更写的很好,不太可能导致新bug,但是否决它进入微小版本的意见仅仅是它太大了—或许它引入了新特性,又或者它以微妙的方式违反了兼容性政策。我也偶尔会看到一些开发者仅仅因为有不好的感觉而否决一些东西,他们认为这些变更需要更多的测试,即使无法检查出任何bug。人们总会发些牢骚,但是否决已经成立,而且变更不会进入发布(即使我不记得之后的测试是否发现了bug)。
### 管理协作发布稳定化
如果你的项目选择了一种变更表决系统,一定要确保设置投票和发布表决的物理机制尽可能的便利。尽管有大量开源电子投票软件,在实践中最简单的方式还是在发布分支上设置一个叫做`STATUS`、`VOTES`或诸如此类的文本文件。这个文件列出所有的变更提议—任何开发者可以提出包含某个变更的提议—之后就是同意和反对它的表决,以及注释或评论。 (提出一个变更并不意味着一定要为此投票,尽管两者经常一起出现。)这个文件中任意一个条目的内容类似这个:
~~~
* r2401 (issue #49)
Prevent client/server handshake from happening twice.
Justification:
Avoids extra network turnaround; small change and easy to review.
Notes:
This was discussed in http://.../mailing-lists/message-7777.html
and other messages in that thread.
Votes:
+1: jsmith, kimf
-1: tmartin (breaks compatibility with some pre-1.0 servers;
admittedly, those servers are buggy, but why be
incompatible if we don't have to?)
~~~
在这个情况下,该变更得到了两个赞成票,但是被tmartin否决,他在附加说明中给出了原因。该条目的详细格式并不重要;你的项目如何设置都可以—或许tmartin的解释应该出现在“Notes:”部分,也许变更描述也应该有一个”Description: “头来匹配其他小节。重要的是需要评估这个变更的所有信息都是触手可及的,进行投票的机制也是尽可能的保持轻量级。提议的变更直接用版本库中的修订号码引用(如果是单个修订可能是r2401,当然提议的变更也可能由多个修订组成)。修订可以是引用在主干上的变更;而如果变更就发生在发布分支,可能没必要再表决了。如果你的版本控制系统没有引用某个变更的明确语法,则项目需要建立一个。为了表决的可操作性,每个需要考虑的变更必须是明确可标识的。
这些提议和表决可以保证变更可以干净的进入发布分支,也就是不会发生冲突(见[*冲突(conflict)*](#))。如果有冲突,则该条目应当包含指向一个可以使变更变干净的补丁,或者是包含已修正变更的临时分支,例如:
~~~
* r13222, r13223, r13232
Rewrite libsvn_fs_fs's auto-merge algorithm
Justification:
unacceptable performance (>50 minutes for a small commit) in
a repository with 300,000 revisions
Branch:
1.1.x-r13222@13517
Votes:
+1: epg, ghudson
~~~
这个例子取自真实的生活;来自Subversion 1.1.4发布过程的`STATUS`文件。请注意,它是如何使用原始的修订版本作为变更的标准描述方式,即使有一个分支已经有了修正冲突后的变更版本(为了更简单的将一定会被通过的变更合并到发布版本,分支也将三个trunk的修订版本合并为一个r13517)。这里还是提供了原始的修订版本,作为最早的可以检查的实体,因为他们都提供了原始的日志信息。临时分支不会有那些日志信息,为了避免信息的复制([Chapter 3, *技术基础设施*](# "Chapter 3. 技术基础设施")的[the section called “信息单一性”](# "信息单一性")),分支上r13517的日志信息仅仅是“调整r13222、r13223和r13232回到分支1.1.x。”关于变更的所有其他信息都可以跟踪原始的修订版本得到。
### 发布经理
将已确认变更合并到发布分支的实际过程(见[*合并(又名搬运)(merge, a.k.a. port)*](#))可以由任何开发者执行。不必有一个人专门负责合并变更;如果变更很多,最好能有人分担工作。
然而,尽管表决和合并都以非集中的样式出现,在实践中通常会有一到两个人掌控着发布过程。这个角色有时被正式的称作*发布经理*,但是与拥有最终决定权的发布所有者(见本章前面的[the section called “发布所有者独裁”](# "发布所有者独裁"))有很大的区别。发布经理跟踪当前有多少正在考虑的变更,有多少已经确认,有多少可能会被确认等等。如果他们感到重要的变更未能获得足够的关注,或者可能因为缺少投票而无法进入发布,他们会有礼貌的提醒其他开发者检查并投票。当一组变更经过确认,这些人会自己去将它们合并到发布分支;如果有其他人愿意自己完成这个任务也没有问题,只要所有人都理解如果他们没有明确的声明要自己做,这便不是强制要做的工作。当要将发布公布于众时(本章后面的[the section called “测试和发布”](# "测试和发布")),发布经理将会完成最终发布包的创建,收集数字签名,上传发布包并作出公告。