团队或应用规模是否会影响发布流程?这取决于具体情况。让我们来想象一下一个小型团队的创业公司。在这种情况下,通常是团队开发一个功能,然后直接发布。现在我们再来想象一个大型项目,比如一个银行应用程序,有很多团队在同时开发。在这种情况下,可能需要一套完整的流程、发布周期,甚至一些行政手续。如果没有这些,就会造成混乱。
那么,到底什么时候才能明确意识到需要为应用程序建立这样的流程呢?
在本文中,我将分享我们在Dodo Pizza应用程序(Android和iOS)中实施发布列车的经验,以及我们面临的问题,这些问题促使我们团队开始实施发布列车。
如果你是一个Android或iOS项目的团队负责人/技术负责人,并且你的项目正在快速发展,但尚未建立起有效的发布流程,我希望我们的经验可以对你有所帮助。
在2021年,我们的团队已经采用了主干式开发(Trunk-based Development,TBD)方法。我们使用功能开关覆盖代码,分解任务,运行单元测试和UI测试。我们的功能分支不会存在太长时间,同时我们也建立了持续集成(CI)环境。
发布流程非常简单:凡是准备好发布自己功能的人就可以进行发布。
以下大致是我们的分支工作流程。多个团队(灰色、蓝色、橙色和绿色)同时开发不同的功能。由于我们采用主干式开发,每个功能可以经历多个连续的分支。例如,灰色团队在四个步骤中完成他们的功能,蓝色和橙色团队在一个步骤中完成他们的功能,绿色团队在两个步骤中完成他们的功能。
当一个团队完成了一个功能,他们可以发布一个版本。例如,如果蓝色团队完成了一个功能,他们就可以发布一个版本。然后橙色团队会完成一个功能,再发布另一个版本。
我们原本认为我们的流程是完美的。它一直运作得很好,但所有好事都有一个终点。
问题出现了:困难、拥挤和不可预测
我们遇到的第一个问题是发布版本开始积累了很多功能,变得过于庞大。
团队并不总是想立即发布他们的功能。发布和回归测试需要耗费时间,需要3-4天的时间。因此,如果你的功能很小而且不紧急,你并不总能自己发布它,因为可能其他团队很快就会发布一个版本,并且它将被包含在那个版本中。大致上看起来像这样:
这种安排非常脆弱,特别是当团队数量开始增长时。许多团队开发了许多小功能,每个新版本中的新代码总量变得巨大。当有人要发布他们的重要功能时,他们必须同时发布一个庞然大物。
庞然大物的版本发布导致了以下问题:
我们需要使得即使像例子中的蓝色和橙色团队不想发布,发布仍然能够进行。
每个团队都是独特的,每个功能也都不同。有时候情况会以这样的方式发生,几个团队会在同一时间完成他们的功能。在这种情况下,会有很多“等我一下,我明天早上合并,我保证!”这样的情况发生。
最终,这些瓶颈导致了以下问题:
我们需要进行两个关键的改变:
想象一下,蓝色团队开发了一个小功能,并期望橙色团队很快发布。但是出了些问题,橙色团队由于自身的问题也没有进行发布。结果,蓝色团队告诉业务方该功能很快就会上线,但实际上却不够快。因此,无法预测该功能何时能够投入使用。
这并不意味着蓝色团队不负责任。如果他们有一个非常重要或紧急的功能,那么当然他们会自己发布。但在其他情况下,无法准确预测该功能何时对用户可用。
正如你所猜测的,我们经常遇到这样的问题。无论功能的大小或紧急程度如何,我们都需要能够准确告知客户何时能够在生产环境中使用该功能。这三个问题(庞然大物的发布、瓶颈和缺乏可预测性)密切相关并相互补充。然而,其中最根本和最重要的问题可能是缺乏可预测性。它会引发其他问题。
我们受够了,是时候进行改变了。发布列车应该帮助我们做到这一点。
发布列车这个术语有不同的含义:一个按计划进行的发布流程,或者一个专门负责管理发布流程的团队。在这里,我们将讨论按计划进行的发布流程。我喜欢马丁·福勒(Martin Fowler)在《代码分支管理的模式》一文中对发布列车的描述方式,还有Thoughtworks在他们的技术雷达中给出的定义(也许这个定义也属于马丁)。
这是我们为自己定义的发布列车:
发布列车是协调团队之间发布的过程。所有的发布都按照固定的时间表进行,不管功能是否准备就绪。列车不会等待任何人。如果你迟到了,就得等待下一班。
让我们通过几个使用我们的彩色团队进行示例来详细解释。
发布列车按计划进行,不依赖于谁将什么合并到主分支中。在下面的示例中,蓝色和橙色团队的功能将被发布。其余的功能将等待下一班列车。我们可以再等一会儿,但那样会变成庞然大物。
同时,发布列车帮助我们更有效地规划工作。假设蓝色团队最初计划稍后完成一个功能。但由于每个人都知道发布日期,他们可以稍微重新安排计划,提前完成该功能。或者相反,他们可以意识到他们绝对赶不上下一班列车,因此他们可以安全地完成该功能,因为他们知道整个时间表。
在下面的示例中,蓝色团队希望参与发布,并在发布之前合并了所有的更改。否则,可能会出现瓶颈。
最重要的是,发布列车通过设计为我们提供了可预测性。
这些示例对某些人可能显而易见,但我们在问题出现时解决问题。当发布没有问题时,我们就不会费心使用发布列车。当问题积累到一定程度时,我们意识到时机已经成熟。
我们做的第一件事是起草一份RFC(请求评论)。RFC既指流程本身,也指许多公司在开始项目前使用的设计文档。有些公司专门使用RFC,有些公司使用架构决策记录(ADR),有些只是用更通用的术语设计文档来称呼它们。在Dodo Engineering,我们同时使用RFC和ADR。
我们的RFC流程如下:
我们发布列车的RFC文件结构如下:
在起草RFC时,我们依靠其他公司的经验:
首先,我们设计了这个流程:
发布团队:
在周三创建一个新的发布分支;
制定一个季度计划,说明何时轮到每个团队发布。一个季度后聚集在一起,延长时间表。
一个月后,我们发现虽然最初的经验感觉很好,但是:
每周进行回归测试并在周五之前完成真的很难;
没有时间进行热修复,而有时这种情况确实发生了。
2021年,我们的回归测试平均需要3-4天。2022年,我们设法将其缩短到2-3天,但有时会超过这个时间范围。我们继续用e2e测试覆盖回归测试案例,但我们还没有100%的覆盖率。我们分别在每个平台上覆盖了大约70%和60%的回归测试案例。
这表明,只要回归测试需要几天才能完成,每周运行一个发布周期可能会不太舒适。
我们最终转向两周发布周期,现在发布列车看起来像这样:
每两周发布一次;
在周三早上创建发布分支;
在周五进行回归测试,并将应用程序发送给审核人员;
在周一开始推出发布。
发布团队:
一个功能团队中的一个iOS和一个Android开发人员;
两个QA工程师。
制定一个季度计划,说明何时轮到每个团队发布。一个季度后聚集在一起,延长时间表。
逐步推出发布;
如果需要,现在可以进行热修复;
一周后的周三创建一个新的发布分支。
这是如果一切按计划进行的流程。
整个流程看起来像是一个每周的周期,除了有足够的时间来处理潜在的热修复。以下是在回归测试时间延长的情况下的流程示意:
也没什么大不了的,甚至还有时间处理热修复。
我们的主要目标是提高可预测性。这可以分为两个部分:
我们通过实施发布列车流程回答了“何时会有发布”的问题。现在,每个团队都可以在规划和评估功能时独立地回答“我的功能将在哪个版本中发布”的问题。以前无法确定地回答这个问题,因为另一个团队可能会或可能不会进行发布。现在一切都只取决于该团队自己的计划。
为了进一步确认这一点,我们在移动开发人员、质量保证和产品经理之间进行了调查,除了其他问题外,我们还问了以下问题:
发布列车还帮助我们进行了代码冻结和发布冻结。除了新年前夕(例如9月1日和一些节假日),我们还有其他几个冻结日期。现在,有了发布列车,我们不需要根据这些日期调整创建发布分支、回归测试等工作。发布按计划进行,我们只是稍后在应用商店中打开它们。
除了解决问题,我们还测量了一些指标。让我们看一下主要的指标。
我们测量的第一个重要指标是从提交到发布的交付时间。
这是图表的样子。我用箭头标出了我们开始使用发布列车流程的点。
图表显示交付时间降至约6天左右。6天是长时间还是短时间?
谷歌的基准
对于这个指标,谷歌有一些基准,但主要是针对后端。按照他们的尺度,他们区分以下几组:
我认为对于标准移动应用程序,交付时间理想情况下应该瞄准发布周期的一半。这相当于每天将任务合并到主分支。也就是说,如果发布周期为14天,交付时间应该瞄准7天。
我们追踪的另一个指标是每个回归中的缺陷数。它描述了发布候选的稳定程度。如果上一个发布很久以前,那么我们可能创建了很多新代码,可能包含大量的错误,我们可能需要花费更多的时间进行回归和修复。
有一段时间这个指标降至三个错误。具体的数字并不是那么关键,但总体上可以看到趋势已经下降。
我将简要介绍作为发布列车一部分监测的其他指标。
我们喜欢当前的流程,因为我们认为它已经实现了自己的目标。同时,我们也知道如何进一步改进它:
当我们规模相对较小时,我们不需要发布列车。当我们面临不能预测发布、发布数量和大小的事实时,我们决定实施发布列车。起初,我们尝试了每周发布周期,但由于耗时的回归测试,我们不得不转向两周发布周期。从那以后,我们一直以这种方式生活。
现在我们有了发布的可预测性,指标显示出积极的动态。我们计划增加端到端测试的回归覆盖率,自动化分支处理过程,并优化翻译流程。
我希望这篇文章和我们的经验能够帮助你,尤其是如果你已经面临了类似的问题,并让你思考发布流程。