深入了解Azure DevOps团队的开发部署方式

0
5599

原文链接:https://docs.microsoft.com/en-us/azure/devops/learn/devops-at-microsoft/release-flow

作者:Edward Thomson, VSTS产品经理(负责Git && VersionControl)

译者: 周文洋,LeansoftX研发总监

每当我跟其他人讨论Git && 版本控制的时候,总会被问到:我们团队是如何使用版本管理以及分支策略来完成应用生产环境部署的。其实这并没有一个准确的答案,虽然我们已经完成了整个公司的统一工程系统落地工作(基于Git && Azure DevOps), 但是还没有让所有人统一分支策略以及开发模式。

Azure DevOps团队使用 “基于主干的分支策略” 来实现产品的持续快速交付。这个策略需要满足我们的开发需求:整个Azure DevOps产品存储在一个代码仓库中、支撑分布在3个办公区域的几百号研发人员、并能部署至在全球的多个Azure数据中心。我们称之为 “Release Flow” (涵盖了整个DevOps的流程:从开发到发布)

开发流程(从创建分支->推送代码->创建拉取请求->合并)

分支

当开发人员想要修复一个缺陷或者是开发一个功能时就会在主集成分支(master分支)上创建一个分支,这里归功于Git轻量级分支模式,每当我们需要修改代码时我们都会创建一个短暂的功能分支 。并且我们鼓励开发人员通过使用 “功能标记” 尽可能的避免功能分支长时间存在。

推送

当开发人员准备好将自己的变更集成并推送给其他团队成员时,他们将本地的分支推送到服务器上,并创建一个拉取请求。由于我们有几百个开发人员同时在一个代码仓库上工作,并且每个人都有很多分支,我们通过定义分支的命名规范来避免混淆,我们称之为 “branch proliferation”, 通常开发人员创建一个本地分支并将它命名为 “users/<username>/feature”, 例如,我创建一个分支在 /users/ethomson 文件夹。

拉取请求

我们通过拉取请求来控制开发人员的功能分支到master分支的合并。通过拉取请求确保代码符合分支策略的要求,首先会执行构建来验证提交的变更并且执行快速测试,大约会在5分钟内完成60,000多个测试的运行(”level 0″ 到 “level 1″的测试套件) ,这并不是我们所有的测试矩阵,但已经足以保证拉取请求的质量了。

下一步我们会邀请Azure DevOps团队的其他成员来进行代码评审以及审批。代码评审会在自动化测试完成后进行,通过代码评审可以比较方便的看到一些静态代码检查看不到的问题,比如架构问题,也可以让团队成员了解彼此的工作情况、最重要的是能帮助我们保证代码质量。

合并

当所有的构建策略满足条件时,并且审阅者也完成了评审后,拉取请求就完成了。
这意味着功能分支被合并到了主集成分支(master分支)

合并后我们会花费一点时间运行额外的验收测试,这看起来像传统的迁入后的测试我们使用它来执行更彻底的检查。这样做的目的是寻求一种平衡:既能在拉取请求阶段完成快速测试、又可以在发布之前保证测试覆盖率。

以上就是开发人员如何将代码变更提交至主分支的,看到这里我们的分支策略是不是有点像 “基于主干的分支策略” 模式。但是跟其他的 “基于主干的分支策略” 又有不同(如:GitHub Flow),我们没有在合并拉取请求之前部署那些变更到生产环境并进行测试,也不是在合并请求完成之后部署至生产环境。

GitHub Flow经常被忽视的一点是拉取请求是在代码合并到Master之前直接部署至生产环境进行测试的。这意味着开发人员在合并拉取请求之前需要等待 “部署队列“ 来测试对应的变更。

Azure DevOps团队有几百号开发人员持续的工作在同一代码仓库工作,并且我们每天会完成200多个拉取请求的合并,如果每一个拉取请求都需要部署到全球的多个Azure数据中心的话,我们的开发人员将会浪费太多时间在等待 “部署队列” 完成部署。从而耽误他们写代码的时间。

相反,我们继续在主分支中进行开发,并将部署集中到三周后,与迭代节奏保持一致。

按迭代里程碑发布

在迭代结束时,我们会通过master分支创建一个发布分支:比如,在 “迭代129” 结束时,我们会创建一个分支 releases/M129(这里分支开头的M是milestone的简写), 然后将 “迭代129” 的分支发布到生产环境。

一旦创建了部署分支,开发人员就可以继续在master分支上合并代码,当然这些变更不会被部署到生产环境,他们都会在下一个迭代进行部署。

快速修复补丁(Hotfixs)

显然有些变更是需要快速部署至生产环境的,我们通常不会将大的功能添加到一个正在进行中的迭代。但是有的时候我们需要修复一些妨碍用户正常使用的一些重要缺陷。比如有的时候我们有一些拼写错误。或者说一些导致不可访问的缺陷,我们称之为 ”线上事故“

当类似事情发生时,我们开始正常的处理流程:在master分支上创建一个分支,并完成代码评审、完成合并请求,注意我们永远是在master分支上做变更,这让我们可以快速的修复问题,并在本地进行测试。

更重要的是,通过遵循这个流程,我们可以保证所有的代码变更都会进入master分支,这个对我们非常重要。如果我们在发布分支上修复缺陷,并且意外的忘记将代码变更反向合并到master分支。我们将会在下一个部署中重现此缺陷(比如在3周后的130发布分支)

这个是非常容易忘记的。所以永远在master分支上完成代码变更,并确保修复的代码同时存在两个分支中msater && release分支。

可以通过拉取请求上的 “挑拣功能” 支撑此流程:在拉取请求页面可以挑拣此拉取请求上的所有提交到其他分支上。为了能快速的将变更部署到生产环境,当我们将拉取请求合并到master分支后,立即挑拣这个变更并应用到release分支。这将会创建一个新的拉取请求到合并到发布分支(将我们刚刚从master分支上修复的补丁合并至发布分支)

创建新的拉取请求后,我们可以通过分支策略的 “工作项链接” 来保证可追溯性以及 “构建验证” 来保证应用的可靠性。Azure DevOps的挑拣功能可以实现快速挑拣:并不需要将relase分支下载到本地进行挑拣,所有的操作都可以在服务器端来完成。并且如果我们需要做变更的话,比如修复合并冲突或者细微的调整我们都可以通过Azure DevOps在线的文本编辑器来实现。当然我们也可以通过使用 “拉取请求合并冲突插件” 更方便的解决冲突。

一旦创建到Release分支合并的拉取请求后,我们需要重新进行代码评审、验证分支策略、测试。合并完成后,将会在几分钟内部署到第一个 “环”,我们将使用 “deployment rings” 逐步的将它部署给越来越多的Azure DevOps用户。随着修复补丁应用给越来越多的用户,我们会持续的监控应用并确保线上问题得以修复,以及没有引起任何其他问题。

继续

3周后,我们将完成 “迭代130” 的功能开发,并且我们已经准备好部署这些变更,我们在master分支上创建一个发布分支 release/M130并部署它。

这个时间点,其实在生产环境会有2个分支:由于我们使用 “ring-based deployment ” 来确保应用安全的部署。fast ring将会部署迭代130的变更。slow ring 依然保留迭代129的变更。

一旦所有的 “环” 被部署后,”迭代129″ 老分支将会被彻底移除。将不会在使用它。因为我们确定在迭代129做的任何变更,比如hofix都已经合并到了master分支。所有那些变更也同样在releases/M130分支存在。

 

总结:

“Release Flow” 是Azure DevOps团队研发模式的核心,它允许我们可以使用简单的 “基于主干的分支策略” 的方式进行开发。避免了开发人员因等待部署队列被搁置, 让开发人员专注于产品研发。

“Release Flow” 让我们可以按照固定的节奏将新的功能部署到全球不同的Azure数据中心以及高效的完成线上问题的修复。