当今典型的软件集成发布模式是,通过类似GitHub的Pull Request或GitLab的MergeRequest的方式管理特性分支(Feature Branch):在通过代码评审等方法确认一条特性分支上的改动没问题后,将其合入集成用的分支。随后,代码改动进入在集成分支上运行的持续交付流水线,直到发布上线。

在阿里巴巴内部,尽管这种工作方式也得到了研发协同工具平台(Aone,对外叫云效)的支持,但广大研发同学选择的主流工作方式却不是它,而是用一种被称之为变更(全称变更请求,英文Change Request)的对象来管理特性分支,直到发布。

初看起来,变更与Pull/MergeRequest有不少相同点,但实际它们在理念上的差别很大。

本文详细介绍它们的相同点和不同点,并探讨用户喜欢变更这种方式的原因,当然也会介绍相应的风险和弱点。或许阅读本文,能给你带来一些思考。

相同点

  • 变更与Pull/MergeRequest的相同点主要在于对特性分支本身的质量和流程的控制:
  • 一个变更,就像一个Pull/MergeRequest一样,大体上对应一条特性分支。
  • 在Pull/Merge Request中,可以看到这条特性分支上代码改动内容,进而进行代码评审(Code Review)。类似的,也可以以变更为粒度进行代码评审。
  • 在特性分支上的代码提交,可以自动触发持续集成工具做构建以及各种自动检测,其结果可以在Pull/Merge Request中展现。类似的,在变更中也可以展现。
  • 可以把Pull/MergeRequest上的最新代码构建部署到它专属的测试环境并运行,以进行测试和调试。在变更中也可以这样做。
  • 在Pull/Merge Request中可以设定通过的条件,比如至少两名评审者同意,且所有的代码评审中发现的问题都已修复或澄清,且特性分支上的持续集成流水线运行成功。在变更中也支持类似设置。

不同点及其主要价值

变更与Pull/MergeRequest的不同之处关键在于,这个特性分支与其他特性分支一起集成和交付的方式。

对于Pull/MergeRequest,随后把特性分支合并到集成用的分支,然后就没有然后了。哦不,是然后就不再以特性分支为粒度去管理了。这条特性分支已经合入集成用的分支,其上的代码改动已经融入集成发布的洪流之中,被裹挟着和其他特性分支上的代码改动一起前进,去闯关通过集成-发布的各个阶段(Stage)。

而变更不同。即便是已与其他变更集成,它仍然具有一定的独立性和灵活性,在确有必要时,可针对单独变更进行操作。下面我们通过两个例子来详细介绍。

第一个例子:简化起见,假定集成交付过程有三个阶段:日常集成测试、在预发布环境测试、正式发布。某应用的变更A到变更E共五个变更,在通过了日常集成测试这个阶段后,进入了在预发布环境测试这个阶段。测试时,发现变更C有一个缺陷。这个缺陷因为受日常测试环境所限,在日常集成测试阶段没有暴露出来。经分析,变更C与其他四个变更间没有依赖关系,不会互相影响。因此,为了让其他四个变更的发布尽量少受影响,决定把变更C从在预发布环境测试这一阶段中摘除出来。其他四个变更在一起再次测试验证,此时该缺陷不再出现,这四个变更在一起通过了在预发布环境测试阶段,进而进入正式发布阶段,发布上线。

在这个例子中,在摘除了变更C后,没有将其他四个变更在一起再次经过日常集成测试阶段,是出于两方面考虑:一是,此时的日常集成测试环境,已经被若干新添的变更所占用。它们的测试需要时间,而且可能也会反复调整。把新添的变更赶出去,或者把这四个变更和新添的变更混在一起,或者让着四个变更等着,都分别有明显的不利之处。另一方面,A、B、D、E四个变更,它们与变更C在一起,已经通过了日常集成测试。而变更C又与它们无关,因此对它们再次进行日常集成测试,发现问题的可能性很低。测试是要讲究性价比的,而不是一味追求保证产品零缺陷。出于以上原因,在具体实战中,开发团队就有可能根据当时实际情况,在评估后决定,在摘除了变更C后,不再将其他四个变更在一起送回日常集成环境,而是直接在预发布环境再次测试。

第二个例子:仍假定集成交付过程有日常集成测试、在预发布环境测试、正式发布三个阶段。某应用的变更A到变更E共五个变更,在通过了日常集成测试这个阶段后,进入了在预发布环境测试这个阶段。此时,根据市场情况变化,需要对变更C所承载的新功能做出少量调整,比如页面说明文案上改几个字。考虑到新的修改与变更C原有内容要么都发布,要么都不发布,所以为便于管理,新的修改就在变更C所在的特性分支上完成。这样形成的变更C的最新内容,与其他四个变更在一起,在预发布环境进行测试,通过后正式发布。

以上两个例子,是在传统的集成-发布方式基础上,加入了一些灵活性:集成-发布过程中,必要时可以中途撤下变更,可以中途修改完善变更。而有些团队在使用变更时,采用了更进一步的方式:不再设集成工程师之类的角色,不再规划统一的集成、发布的计划和时间点。而是每个开发同学负责自己的变更,不仅跟踪它直到把变更的质量提升到可集成的程度,而且由开发同学自己把他负责的变更依次适时推入(也可能是自动进入)集成-发布的各个阶段,跟踪它直到发布上线。也就是说,尽管进入了集成-发布阶段,各个变更仍是被各自的开发者分别跟踪和推进的:它们可能有各自的推进速率和节奏,而不会相互拖累。彼此无关的变更,只是碰巧一同使用某个测试环境,一同批量测试以提高测试效率、一同上线以避免排队而已。据此,尽可能缩短了一个需求从开发到发布上线的时间,并表现为相当频繁的发布上线。同时也契合了DevOps的理念:“谁开发谁运行”(You build it, you run it)。

这一变化趋势其实和软件研发的管理实践中发生的事情类似:瀑布模型时代就不提了。随后迭代方法取代了瀑布模型。典型的,Scrum方法中的Sprint。而更进一步,在精益方法的看板墙上,迭代被弱化,关注的焦点从每个迭代做什么,每个迭代进入到什么阶段,演化为关注每个在制品流动到了哪个阶段,以及每个阶段包含的在制品总量。

类似的,在上述变更管理方法中,从关注某个集成版本进入到集成-发布的哪个阶段,演化为关注每个变更进入到集成-发布的哪个阶段,以及每个阶段包含了哪些变更。

另一方面的价值

以上,介绍的是使用变更管理方式带来的灵活性,以及因为灵活务实而带来的效率提升。变更管理方式,在信息记录和跟踪方面还有一些的好处:

要想方便地知道,本次测试、本次发布,到底包含了哪些特性,只要看看包含了哪些变更就好了。变更本身有说明文字,变更还可以关联需求、任务、缺陷等工作项,更详细地说明变更的目的。而在变更之外,也没有别的代码修改可以通过直接提交到集成分支等途径溜进来。

而从变更的视角,这个变更相关的所有改动,都在该特性分支上,而不会因为多次反馈修改而散乱到各处。因此这些修改总是可以方便地一同查看,一同操作。同时,总是能够清晰地知道这个变更的状态,它到了哪个阶段:开发完毕了吗?进入日常集成测试阶段了吗?已经正式发布了吗?等等。

变更可以关联需求、任务、缺陷等工作项,同时变更的状态是可以自动获取的。因此,看板墙上跟踪的工作项,从原理上就可能被自动移动,以反映其实际状态。协作和进展,在看板墙上一览无余。

弱点和风险

以上谈的都是这样的变更管理方式能带来的好处。那么,它有没有弱点和风险呢?

是的,它有。从大爆炸式集成到持续部署流水线,业界几十年来几乎一直在采用一个基本模式:总是一个集成版本,去顺序经历集成-发布的各个阶段。这样可以保证,下一阶段收到的内容,总是精确的经过了上一个阶段的检验。而本文介绍的变更管理方式所引入的灵活性,意味着颠覆了这一基本模式。灵活性从来都是双刃剑。灵活性意味着风险增加,意味着可能被滥用。

敏捷宣言认为“个体和互动高于流程和工具”,上述变更管理方式暗合了这样的思想。但在实际使用该方式时,需要注意到它对团队成员提出了更高的要求:要求他们在具体场景具体案例中,能够对变更间的相关性及相应风险做出评估,并了解不同选择对效率的影响,最终综合做出特定场景特定案例中的决策。具体来说:

  • 变更对应的代码改动越少,中途撤下变更带来的风险越小。
  • 中途修改完善变更所对应的代码改动越少,带来的风险越小。
  • 软件架构越好,变更中途撤下或修改完善带来的风险越小。
  • 本次变更与其他变更的相关性越小,中途撤下或修改完善带来的风险越小。
  • 越紧急,越考虑灵活处理。
  • 业务角度,对软件质量的要求越高,就越不要考虑灵活处理。

延伸一下,事实上,在微服务甚至函数服务时代,即便不使用上述变更管理方式,也有类似上文的风险,也相应需要团队成员具备类似上文的自主判断能力。为什么这么说呢?

之所以把单体应用拆分为微服务甚至函数服务,一个重要原因就是为了每个服务能单独测试和发布上线。然而,在使用微服务甚至函数服务方式时,被测对象严格地讲并不是一个服务,而是该服务以及测试环境中与其直接或间接打交道的所有其他服务。而当把每个服务单独测试和发布时,就经常会导致本阶段测试时某个其他服务的版本,与下个阶段测试时的版本不同,或者与将来正式发布运行时的版本不同。于是就意味着类似上述变更管理方式中的风险。

相应的,这里面就需要人来判断(当然可以有智能算法的辅助),本次哪些服务上的改动务必要一起测试和上线,而另外几个服务上的改动可以单独运作。而下次可能又是不同情况,要根据下次的具体情况判断。

由此看来,“总是由一个集成版本,去顺序经历集成-发布的各个阶段”这个基本模式,其实已经被悄然突破了。上述变更管理方式,只是使这个突破更加明显了而已。

落地及工具支持

以上是介绍了一种独特的变更管理方式,介绍了优点,也介绍了相应的风险。下面我们来看看它在阿里是如何落地的。

首先需要一套分支方案来支持它。大体上是这样:

  • master分支总是代表最新已发布版本。
  • 代码改动总是在特性分支上完成。特性分支总是从master分支上拉出的,并在必要时从master再次同步。
  • 没有一条长期存在的集成发布用的分支。而是集成发布过程的各个阶段,各对应一条短期的,被自动管理的集成发布分支。从master分支自动拉出该分支,再把各特性分支自动合并到该分支(出现冲突时人工介入),于是它上面就有了用户想要的各特性。
  • 如果发现某个特性需要进一步修改完善,在特性分支上完成,并再次合并到相应的集成发布分支。

《在阿里,我们如何管理代码分支?》这篇文章对上述分支方案有更多介绍。

《云效 > 使用指南 > 持续交付 > 开发模式 > 分支模式》这篇文档是该分支方案的详细说明。

可以看出,这套方案,对工具平台的要求是比较高的:从界面角度,用户只需要管理各个集成发布阶段分别要有哪些变更。而工具平台要将它映射为对集成发布分支的管理,包括创建新分支或复用已有分支、从各特性分支到集成发布分支的合并等等。这里面也包括了不少算法,以尽可能减少相同的合并冲突重复出现。

对工具平台的高要求,或许是这套方法多年来一直只是在阿里巴巴内部被广为使用的原因。

不少曾在阿里巴巴工作过的同学,出去后都念叨着没有这样的工具支持了。不过现在好了,就像Google基于内部的Borg对外提供了Kubernetes,阿里巴巴也基于内部研发协同工具平台Aone对外提供了云效。

云效的公有云版和专有云版,都提供了上述方法的完整支持。不论是你对上述方法抱有兴趣还是怀有疑虑,都可以尝试研究一下。

原文链接

本文为云栖社区原创内容,未经允许不得转载。

转载于:https://juejin.im/post/5c88bc355188257b3b7fae25

阿里在使用一种更灵活的软件集成发布模式相关推荐

  1. 阿里正在使用一种更灵活的软件集成发布模式

    当今典型的软件集成发布模式是,通过类似GitHub的Pull Request或GitLab的MergeRequest的方式管理特性分支(Feature Branch):在通过代码评审等方法确认一条特性 ...

  2. 看看阿里是如何做软件集成发布的

    点击蓝色"程序猿DD"关注我哟 来源:云效 作者:董越(花名荷锄),阿里巴巴研发效能部高级产品专家 拼团活动最后一天:跳槽季,我们一起攻克网络协议和算法吧! 当今典型的软件集成发布 ...

  3. [汇编语言]更灵活的定位内存地址的方法

    目录 一.and和or指令 二.以字符的形式给出数据 三.大小写转化问题 四.[bx+idata] 五.SI和DI 六.[bx+si]和[bx+di] 与 [bx+si+idata]和[bx+di+i ...

  4. 当Kubernetes应用遇到阿里分批发布模式

    对于熟悉Kubernetes的用户来说,应该知道当你的应用程序一旦部署到Kubernetes以后,Kubernetes能够自动帮你管理应用程序,当Pod发生故障后可以自动调度重建,确保服务的持续可用. ...

  5. 阿里云云效技术专家:一文详解kubernetes下5种常见发布模式如何选择

    简介:Kubernetes下5场场景应用发布方式的选择,每种发布模式适合什么样的场景,以及如何在阿里云云效上高效落地. 作者:郑云龙,阿里云云效技术专家 Kubernetes面向通用场景提供了非常灵活 ...

  6. 在阿里外包是一种什么样的体验?

    在阿里外包是一种什么样的体验? 停更了好久,来迟啦.不过依托于前面文章,粉丝数居然不降反升,感谢感谢大家~ 至于为啥好久没更新了,这篇文章就是答案. 开始吧~有点长,耐心看撒~. 从来之前的炎炎夏日酷 ...

  7. 前端工程化精讲第七课 低代码工具:如何用更少的代码实现更灵活的需求?

    在进入到这一课的内容之前先让我们来回顾下,通过脚手架工具生成初始化代码,以及通过 Snippet 工具生成代码片段的方式.两种方案的相同在于,通过简单的输入和选择就能获得预设后的项目代码.这种转化方式 ...

  8. 为进阿里刷面试题-日更

    为进阿里刷面试题-日更(加油打工人) 下面的题目都是自己理解的,如有漏,或者写错的,请指出来!加油! JAVA基础 1.JVM内存分配原理,垃圾回收原理 2.ConcurrentHashMap 和 h ...

  9. 从AI、加密货币到火星任务,一种更强大、更稳定的存储设备

    作者:贺佳 来源:数据实战派 所研究器件之一的显微镜图像,由两个尺寸相同的十字架组成,其中一个具有 IrMn3 柱,第二个仅由 Pt 组成.(来源:西北大学和墨西拿大学) 美国西北大学和意大利墨西拿大 ...

最新文章

  1. SAP PM 入门系列6 - PM常用表
  2. Matlab中gradient函数的使用方法
  3. mysql utf8 4位_mysql中utf8和utf8mb4区别
  4. JavaScript基础之'script'Tag的使用
  5. idft重建图像 matlab_你赞成在医疗图像处理领域使用超分辨率重建技术吗?
  6. AcWing 859. Kruskal算法求最小生成树(稀疏图)
  7. scrollview滑动到某区域执行某种方法
  8. python的全局变量和局部变量
  9. 机器学习 Machine Learning- 吴恩达Andrew Ng 第11~15课总结
  10. GlobalMapper20脚本应用(数据批量自动化处理)
  11. 天猫电视盒子服务器响应错误,电视盒子错误的使用方法,你中招了几条?
  12. 线程池提交任务时submit()和execute()的区别
  13. C变量的直接引用与间接引用区别
  14. Gateway过滤器详解
  15. 软件实训:手把手写一个简单的javaweb项目
  16. nice,​使用python生成专属二维码~
  17. 膨胀卷积(空洞卷积)学习篇
  18. 会声会影2018新功能分屏视频
  19. CAPM 资本资产定价模型
  20. 吉林大学计算机动画与游戏导师,吉林大学计算机 导师联系方式

热门文章

  1. 自定义video控制栏,移动端可行
  2. 除了加强风控,大数据还能为FinTech做些什么?
  3. 一些关于大数据的总结
  4. 基于jquery.fixedheadertable 表格插件左侧固定 对齐
  5. JavaScript 基础(二)
  6. SAP ABAP第一,两,三代出口型BADI实现 解释的概念
  7. Gnome 快捷键汇总
  8. process is bad
  9. 文件操作03 - 零基础入门学习C语言62
  10. 开源组件 Ehcache中被曝严重漏洞,影响多款Jira产品