持续集成方案调研

要做持续集成,其实就是回答下面几个问题:

  1. 什么是持续集成?
  2. 为什么要做持续集成?
  3. 我们的持续集成方案?

第一个问题:什么是持续集成? 与持续集成相关的,还有两个概念,分别是持续交付和持续部署。

持续集成指的是,频繁地(一天多次)将代码集成到主干。

持续交付(Continuous delivery)指的是,频繁地将软件的新版本,交付给质量团队或者用户,以供评审。

持续部署(continuous deployment)是持续交付的下一步,指的是代码通过评审以后,自动部署到生产环境。

持续集成本身只是一种practice,在任何一种开发模型中都可以采用

 

持续集成的流程:

提交 --> 单元测试  -->  build完成  --> 自动化测试-->  集成到主干 --> 交付测试-->交付运维-->部署生产

这里不容易解释清楚的是交付测试的内容是什么?与集成前的自动化测试是区别在哪里?有没有必要做?

举个例子:

  • 我们的staging分支可以看做是持续集成的主干,开发可以持续的向staging集成代码(必须通过自动化测试)
  • 我们的staging测试环境是每5分钟自动化布署一次,做到了持续布署
  • 持续交付在哪里?如果没有自动化布署,将打包好的程序交付给运维去布署,其实就是交付的过程

 

第二个问题:为什么要做持续集成? 持续集成带来了哪些好处?

持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。Martin Fowler说过,"持续集成并不能消除Bug,而是让它们非常容易发现和改正。"

易于定位错误。也就是当你的持续集成失败了,说明你新加的代码或者修改的代码引起了错误,这样你很容易的就可以知道到底是谁犯了错误,可以找谁来讨论。

及早在项目里取得系统级的成果。因为代码已经被集成起来了,所以即使整个系统还不是那么可用,但至少你和你的团队都已经可以看到它已经在那了。

改善对进度的控制。这点非常明显,如果每天都在集成,当然每天都可以看到哪些功能可以使用,哪些功能还没有实现。如果你是程序员,你不用在汇报任务的时候说我完成了多少百分比而烦恼,而如果你是项目经理的话,那么你也不再烦恼程序员说完成了编码的50%到底是个什么概念。

改善客户关系。理由同上。

更加充分地测试系统中的各个单元。这也是我们常讲的Daily Build与Smoke Test相结合带来的绝大好处。

能在更短的时间里建造整个系统。这点恐怕要你实施以后才能得出结论。就我们而言,持续集成并没有为每个项目都缩短时间,但却比没有实施时,项目更加可控,也更加有保证。

 

随着时间的推移,持续集成带来的更多好处,也逐渐被认识到了,比如说:

有助于项目的开发数据的收集。比如说,项目代码量的变化,经常出错的Tests,经常出错的source code,等等。

与其它工具结合的持续代码质量改进。如与CheckStyle, PMD, FindBugs, Fxcop等等等等的结合。

与测试工具或者框架结合的持续测试。如与xUnit,SilkTest, LoadRunner等等的结合。

便于Code Review。在每个build里,我们都可以知道与前一个build之间有什么改动,然后针对这些改动,我们就可以实施Code Review了。

便于开发流程的管理。比如说,要把一个开发的build提交给测试组作测试,测完满意了,再提交到发布组去发布。

 

个人总结:

不能说持续集成一定好,非持续集成一定不好。非持续集成,即阶段性集成在流程规范,测试合理的情况下也能保证产品质量,取得好的结果

正是因为自动化的介入,提高了集成的频率,所以叫持续集成

持续集成与非持续集成的区别:

  • 自动化测试
  • 集成的频率

主干:用来做持续集成控制的分支

 

第三个问题:适合我们的持续集成方案

解决如下几个主要问题:

  1. 规范开发流程
  2. 确定主干分支(即控制分支,一旦自动化测试失败,则不能集成到主干)
  3. 确定集成频率

注:控制分支也可以有多个,比如即在develop分支做集成控制,又在release分支做集成控制。项目规模越大,参与人员越多,控制流程就越复杂。这里我针对我们现在的开发团队规模,考虑到控制的成本和实施的可行性,只选择了一个分支做为集成控制的主干分支

 

我们当前研发流程的实际情况是:

1. master到staging阶段:走持续集成,自动化测试通过即集成

2. staging到pred阶段:人工介入,目前自动化不能在预生产上执行(防止误操作和垃圾数据带到线上)

3. pred到prodution阶段:预生产测试通过,交付运维,由运维控制发布

参照Git最佳实践,和现有的流程上来看,其实我们staging起到了持续集成控制主干的作用

 

持续集成方案调研

可行的解决方案有三种:

  • 用staging做为主干,只有通过自动化测试的代码才能集成到staging,在staging做交付测试,只有通过交付测试后,代码才会上prod分支,只有prod分支代码允许线上发布
  • 用prod做为主干,通过自动化测试的代码直接集成到prod,用prod的代码部署到预发环境做交付测试,通过交付测试的代码会被打版本号tag,只有被打了版本tag的代码,才允许线上发布
  • 新开release分支做为主干,不控制staging,staging交由开发控制,只有通过自动化测试的代码,才会从staging集成到release分支,交付测试通过后到pord分支,只有prod分支代码允许线上发布

 

三种方案没有本质的区别,区别就是在那个分支进行控制,用什么手段做控制。

我们以staging做为主干为例,探论一下具体的持续集成流程和规范:

  1. 开发每天在master上提交代码,测试以一定的频率跑自动化测试用例,新feature尚未自动化的,需手工测试
  2. 自动化测试通过的代码才可以集成到staging(最好做到自动化测试通过后自动集成)
  3. 集成到staging的代码,可以随时提交付,即进入交付测试阶段,什么时候提交付是由人来控制的,一般是QA
    1. 多个产品线同时集成如何解决?主干开发的意义是减少分支开发带来的合并代码的开销,矛盾是只要任要一个产品线的回归测试通不过,将影响整个持续集成的进度,所以一定是通过自动化测试的才会集成,即保证每个业务线集成到staging的代码都是通过测试的
  4. 集成到staging后不代表没有bug,提交付前发现的bug都还是在master上修,修完后集成到staging,如此循环
  5. 提交付的含义是staging已经基本稳定,不再集成新的提交,只做bugfix,提交付后对staging加锁,进行交付测试,发现的bug在staging上做fix,直到交付测试通过后代码推到prod分支后(此时对staging解锁),才能接受新的提交付
    1. 如果是在staging分支提交付,必须解锁后才能再次集成,再次提交付
    2. 提交付后,如果发现重大问题,或者决策变化,可以撤销,撤销即staging代码回滚至与线上相同,解锁并处于接受新的集成的状态
    3. 一天内可以多次提交付,只要上次提的交付已经通过交付测试,或者被撤销了
  6. 交付测试通过的代码会推到prod分支,并打上版本tag,表示可以发布,这里需要人工介入确认交付测试通过,一般是QA
    1. 交付测试通过的标准是什么?
    2. pord分支一天内可以有多个tag,代表多次交付并通过交付测试

 

以下是关于持续部署的设想(打版本tag的作用):

  1. 自动化布署脚本(每天定时)识别最新的版本tag进行发布
  2. 自动或手工发布后,支持一键回滚至上一个版本

 

集成的频率:推荐daily

以staging做主干为例,在master上每天都跑自动化测试用例,通过后即可集成至staging(最好做到自动集成),然后在staging上执行交付测试,不用等到预发做交付测试

 

有一个问题需要解释一下:就是分支与测试环境看起来是紧耦合的,即master分支对应master环境,prod分支对应生产环境。但其实分支应该与环境无关,即每个分支可以发到任意环境。但是为了方便管理和沟通,我们限定master环境部署的就是master分支,预发环境就是release分支,线上环境只能发prod分支。

 

参考:http://www.ruanyifeng.com/blog/2015/09/continuous-integration.html