写给小团队的软件发布管理


/**
 * 谨献给会“越狱”的小黑
 *
 * 原文出处:https://www.toptal.com/devops/guide-release-management-for-small-teams
 * @author dogstar.huang <chanzonghuang@gmail.com> 2016-04-02
 */

使发布管理流程正规化(如果还没有的话)

在某些团队配备里,尤其是那些在初创公司的,当发布一个新产品版本时,既没有DevOps也没有基础设施工程师来提供支持。

况且,不像有着定义正式流程的大型官僚公司,在初创公司的CTO或者软件开发团队的一把手并不总是可以意识到 软件发布管理流程的复杂性;在公司的少数开发人员可能意识到了流程的复杂细节,但并不是每个人。如果没有很 好地文档化这块知识,我相信会导致不少困惑。

在此篇文章中,我会尝试专门从开发人员的视角,提供关于如何正规化发布流程的一些技巧。

进入软件发布清单

你可能了解写给某些外科专家的清单概念,根据由阿图•葛文德编著的《清单革命》一书。 我相信一个正规的发布流程(像软件开发世界里很多其他的任务)为开发人员提供了实现此协议的机遇。发布流程 清单应该保持在某个共享文档里,最好是在共同的wiki的表单,或者在Google Drive云端硬盘上的电子表格。

通过与团队分享这份重要的文档,并且通过分配编辑权限,每个成员都接入了正式定义的发布流程。这使得他们 能够明白整个流程是如何工作的。再者,随着和其他团队成员不断讨论,它授权团队时不时地进行完善和改进。 这应该会带来透明度以及允许整个团队可以实时掌握在发布过程中发生了什么,哪些步骤是已完成的并由谁完成。

通过查看这份电子表格,根据步骤的结果,利益相关者可以决定“GO”还是“NO GO”。例如,如果在测试环境的压力 测试出现了问题,项目管理者可能会根据此事件决定取消产品发布。

一份简单的,考虑周详的电子表格清单可以在你的软件发布管理流程中产生巨大影响。

建议使用的基础步骤

在这部分,我会提出一些你可以用于为发布流程构建自己清单的步骤。其中一步骤决不是强制性的 。每个应用 都不同并且每个组织工作的方式也不同,所以请自行调整并且做出更适合你团队工作流的改变。

1. 创建一个发布分支

很可能你已经熟悉Git工作流的内容,或者发布 分支的概念,在先前发布的一篇博客里已对此作出了解释。

理想的情况下,你应该至少有三个分支:
+ master: 这个分支应该反映了当前生产环境的状态。每一个在master 上的新提交都应该仅由一个新的发布构成。
+ develop: 这个分支应该包括已完成的(并且通过测试的)即将到来的特性。通常会为每个特性创建一个分隔的分支并且当特性准备好后才把它合并到develop
+ release: release 分支是准备发布到生产环境的提交的集合,加上一些额外的与发布相关的次要bug修复。

注意到一旦发布完成后应该移除release 分支,所以这些分支一直在创建和销毁,不像masterdevelop ,通常都是一样的。

为了创建一个新的 release 分支,在你的git终端上从develop 分支输入:

$ git checkout -b release/x.y.z

使用命名惯例是很方便的,例如上面定义的这个,根据你的需要(它是在团队中定义并坚持下去的策略)用主要.次要.补丁版本号来替换x.y.z

同样,说明这一点也是重要的:如果你修复bug的一些代码合并到了release分支,别忘了把他们也合并回develop 分支。 release分支最主要的目的是能对app投入到生产环境后是如何运作的有一个预览快照。

组织和保持对不同发布分支的追踪是发布管理中关键的一面。

2. 版本提升

下一步将要做的是提升(修改或者增加)release 分支中的版本号。

你应该打开AndroidManifest.xml / package.json / pom.xml / 或者任何在你的项目中(YMMV)存放应用版本的地方, 然后更新版本号,并且提交这些修改到当前release 分支。

更新版本号是很重要的,原因有二。

首先,你可以追踪以及匹配在每个版本中引入的特性;其次,你会意识到用户正在使用的版本中会遇到哪些问题或 者他们会联系你以寻找支持。如果正在构建的是手机app,你在这一步更新的版本号通常会在用户终端上显示, 在关于 部分或者在 Google Play 或者 苹果应用商店 。这一步也是一个更新环境依赖配置(environment-dependent-configuration) 文件(尽管我建议在分离职责中保持这些)的好机会,例如在生产环境数据制作分支点,或者任何其他在构建过程 所需要的调整。

最后,推荐把release 分支push到origin,以便其他开发人员可以获取到最新代码:

$ git push -u origin release/x.y.z

3. 合并release分支到master并打标签

仅有master 分支应该部署到生产环境,所以在这一步,我们需要合并release 分支到master

$ git checkout master
$ git merge --no-ff release/x.y.z
$ git push

参数--no-ff是可选的,然而,推荐使用它以便强制创建一个新的提交对象,即使可以使用fast-forward技术 来完成合并。

接下来,是时候在master 分支上打上发布的标签了:

$ git tag -a x.y.z -m 'description of new version, features or fixes included'

标签是有用的因为你正在把这个特定的点持久化在git仓库的历史中,并且你稍候可以回过头来重新创建某个特定 标签的隔离分支。

3. 使用pull request合并release分支

另一个经常使用的变种是,使用pull request来把release 分支到master

这种方式有数不清的好处。它创建了一片针对协作的新空间,在这里团队可以讨论大量与发布相关的问题。这点是 为结合代码审查流程添加一个额外大门的好时机,并且也有更多的眼球来监控将要引入的代码,以及讨论潜在的修改。

一些允许你在工作流中实现pull request的工具有GitHubBitbucketGitLab(当他们稍候调用时合并请求)。通过这些工具,你不用手动输入git的命令, 取而代之的是,你使用一个页面接口来设置源分支(release )和目的分支(master ),然后添加一个或多个 reviewer,全部这些reviewer都可以对这些新修改写针对代码行的评论,改进建议等。

当全部的reviewer认可这次pull request后,你可以通过在UI上按下一个按钮就自动地把这些修改合并到master

4. 部署master到生产环境

在这个阶段,部署应用前在团队中有一位做冒烟测试(这点可以在分离的清单中定义)的测试人员是一个好的 实践。一个好的建议是把master 分支部署到一个隔离的测试环境。测试人员随后可以执行一些基本的操作以便 确保合并后的最新构建上没有任何不对劲的东西。如何进行冒烟测试超出了本章的范围,但你可以在网上找到大量 关于它的资料。冒烟测试的结果可以集成到发布清单/电子表格,文档化任何不对劲的东西。

此时,你准备部署这些修改并且赋给他们生命。来吧,部署master 分支。这一步将会依赖于你正在使用的基础 设施栈。它可能包括了连接到Amazon EC2实例以上传app,或者推送一个Heroku远程,或者通过ssh连接到VPS以便 复制这个新版本,或者其他任何流程。

进行冒烟测试,部署master分支到一个隔离的测试环境,确保部署是成功的。

app上传好后,确保它部署成功并且如期地工作。

5. 合并回develop 并且删除release 分支

现在发布基本上大功告成了,你会想把release 分支合并到develop ,以便稍候更新版本号并且把全部修复 的bug传送到主要的开发分支。

$ git checkout develop
$ git merge release/x.y.z

现在,是时候删除release 分支了:

$ git branch -d release/x.y.z

6. 生成Changelog

在你的项目根目录下应该有一个叫做CHANGELOG.md(或者等效的)文件,在这里不管何时有新发布你都可以添加 一个新条目以便能够文档化包含在内的所有东西,像修复bug,新特性,已知问题,和任何其他发布说明相关信息。 这一点对于用户和贡献者 能看到在项目每个发布(或者版本)之间有哪些变化真的是很有用

changelog条目包含日期,版本号和一些关于发布的说明。条目应该以按时间顺序反向罗列。这是一份我用过的
简单模板,你可以根据你的项目自行调整:

<app's name or component released> <version x.y.z> | <date>  
<developer's name in charge of release> | <developer's email>  
Features:  
* <ticket/issue number>: <ticket/issue summary> (<link to issue tracker>)
* ...
Bugs fixed:  
* <ticket/issue number>: <ticket/issue summary> (<link to issue tracker>)
* ...
Enhancements:  
* <ticket/issue number>: <ticket/issue summary> (<link to issue tracker>)
* ...
Optional: known issues plus other release notes.  

此外,这一步也能实现自动化完成,可以通过编码一个基本的转换git日志以及自动生成changelog条目的脚本, 或者通用使用完成同样事情的工具,例如:
+ skywinder的Github changelog生成器
+ fojuth的ReadmeGen
+ lalitkapoor的github-changes

但请记住,你所得到的自动化程度与信息提交格式的严格性是成正比的。我相信团队认可有一个指定的信息提交 格式通常是一个好的实践。通过遵循信息提交风格的准则,他们将会更更容易解析并且此后你更能自动化changelog的 生成。

7. 和利益相关者沟通

通常你应该做一些这样的事情:
+ 让团队通过某个内部消息工具(例如:Slack)知道已完成一个新的发布。我推荐为沟通发布相关事件的每个目 的分别创建一个新的频道(例如:#releases )。在Slack中在某个行为发生后添加一个发布一条消息的钩子是 很容易的。 + 另外,发送一封带有changelog链接的邮件给利益相关者,或者附上changelog文件。
+ 编写发布一篇博客(如果你有针对应用或者项目的博客)或者一条tweet。

根据你的组织特质还可以有更多的行动。重要的事情是别忘了宣传告知你的项目有一个新版本可获得。

8. 疏导问题跟踪器

执行一次发布后,你很可能需要更新某些投票的状态来保持对当前产品中的bug修复,或者特性进行跟踪。通常地, 这包含了改变某些标签(对于小项目我使用一个release-pending 标签,并在发布完成后移除)。

如果你为每次新版本使用里程碑,你很可能需要更新他们的状态或者标记他们为已完成。某些问题跟踪器甚至能 让你计划发布并与冲刺对齐,跟踪一某个bug是否阻塞了发布,以及一些其他有用的信息。

这一切都依赖于你如何使用工具。我想简单指明的是更新问题跟踪器的信息应该包含在你的发布清单里。

关于自动化发布流程

读者可能已经留意到,除了上面高亮的changelog步骤外,前面描述的很多步骤也可以实现自动化。

自动化发布流程中的某些部分的能力是一个巨大的胜利并且节省了大量的时间。我建议创建脚本,或者找出如何自 动化个别步骤然后向持续交付目标前进。持续交付可以 减少风险,降低成本,并且缩短开发人员需要在管理发布中所花费的时间。所以,你将能够更频繁地发布并且在分配 给开发的时间里更有生产力。

神圣的DevOps可以通过按下一个按钮(或者运行一条命令)触发自动化发布流程,从而加载一个新版本,甚至更 进一步,一个可以在特定时间发布你的软件新版本的系统。当然,实现起来很困难因为你还需要自动化大量的测试 过程,但一切皆有可能。

一个完全自动化的软件发布?一些人认为它并不是遥不可及的。

拥抱最佳实践

在这部分我会描述一对我已从中找到便利的推荐实践,或是能使发布流程更加流畅,或是针对进行安全地评估以 防出错。

找到最适合实施发布的日期

我通常在我工作的星期二发布应用,介于中午和业务尾声之间。

如果你从周一工作到周五,在周五启动不是一个好主意。如果在发布后有些东西出现故障,你直到周一才有时间 来修复它(除非你想在周末期间工作加班)。这就是为什么在周二进行发布更加便利,因为你有周一来监控将要 部署的新自焚,修改任何问题,或者做进行回滚。

另外一个需要提及的重要事情是如果你正在管理一个网页应用,需要知道你主要用户坐落在哪个时区。你应该 在访问低的期间进行发布以便如果某些东西失败能最小化潜在的损失。有时,当你的基本用户群(user-base) 分布在全球各地时可以投机取巧,但不管怎样,你都应该做一些调查并决定最佳时机。

在新发布前备份数据库

如果你还没有定期的数据库备份计划,我强烈建议添加一个步骤到你的发布流程以便在开始发布前执行一次备份。

分阶段推出(Staged Rollouts)

有没曾疑惑过为什么,当一个发布者宣布他们已经推出了一个新特性,但需要数天,或者甚至数周,你的手机上才 能获得此特性?这是因为很多公司使用了分阶段推出。

Facebook做这个已经做了很长时间。它会在5%或者10%的用户中测试新特性,然后逐步增长直到覆盖了100%基本用户群。
在分阶段推出期间,你需要仔细查看用户反馈和崩溃报告。通过这些信息,你可以在他们影响每一个用户前推迟发 布,或者修复错误。

对于Android应用,在Android开发者控制台有一个很好的工具实现了分阶段推出。

在分阶段推出里,传播是逐渐增长的。随着时光流逝,有最新版本的用户数量会慢慢提高。

持续集成

出于众多原因持续集成是一个 值得拥抱的实践。首先,它允许你尽早发现错误,提高成功发布率。其次,它是在实现持续交付和前面描述的完全 自动化前第一个逻辑步骤。

Martin Fowler是一位鼓吹持续集成的大人物。
他描述了当使用这个实践时会有超级大量的好处可以添加到你的发布流程上。这是一个巨大的话题而且有很多关于 这点的书和发布的博客,而我在这里提及它是因为我相信它能在操作中给你更多的信心。在众多使用CI的好处中你会发现: 降低风险,提升识别哪些是正常工作的可视化程度,尽早发现bug,提高部署频率,以及更多。

要实现CI的起点是设置一个“持续集成服务器;”一些可以尝试的不错的工具有:CruiseControl,Bamboo,Jenkins和Travis。

Exitlude: 它行得通

我們都非常積極地,保護我們扮演的角色,遺憾的是,時間的來給你在你的路上,我們已經看到這一切: 從篝火的
信任山洪暴發的疼痛的影響,真的沒關係;你別擔心,它行得通。

Exitlude, The Killers
(译者注:歌詞大意参考自:http://www.songaah.com/tw/lyrics/exitlude.html)

总而言这,我想说的是对于你的应用拥有一个定义良好的发布流程是非常重要的,不管它的复杂性,用户群,或者 你的组织有多小。

如果你不想,我建议你开始思考一些基本的步骤,使用这份引导或其他像这样的,以及和你的团队就提出第一个草 案进行头脑风暴。在你下一次发布试一下,然后迭代。最后,你会构建起你自己的发布流程。

这样以后,开始考虑如何自动化流程中的部分 。想一下那些可以提升的地方。通过结合细小的优化探索减少发 布时间的方式。自动化应该是你的终极目标;然而,不要一开始就这样计划,否则你会因尝试如此大的一个飞跃而 失败。正如每个流程,最好是逐步提高。

关于推出应用新版本你还有没其他任何谋略或者准则?如果有,请告诉我。我不是来自DevOps 世界,我只是一位恰好碰到组织化和结构化的开发人员,但相比于很多老兵,我还是这方面的菜鸟,所以如果你有 东西要添加欢迎来评论或者联系我。

dogstar

一位喜欢翻译的开发人员,艾翻译创始人之一。

广州