另一种持续集成策略——延迟提交
常见的持续集成策略是这样的:开发人员修改本地,然后执行本地构建,如果本地构建通过则提交变更至源码服务器。当然提交的时候可能遇到冲突需要合并,那么合并完成后需要再次执行本地构建并确保其通过。
在这种传统的策略下,开发人员执行本地构建是必须的,这样很多问题就能在本地得到快速的反馈,并且不会干扰其他开发人员的工作。试想一下,如果每个开发人员每天提交一次破坏构建的变更到源码服务器,7个人的团队一天就是7次,那持续集成服务器一天的状态几乎都是红色了。事实上,即使所有人都执行本地构建,持续集成服务器有时候还是会出问题,这些问题主要是由开发机器和持续集成机器的环境不一致引起的,当然,一般来说出现这样问题的几率不会太高。
现在,假如因为某些原因,开发人员没有在执行本地构建就直接提交变更到源码服务器了,这时面对千疮百孔的持续集成服务器状态我们应该如何面对?
开发人员不执行本地构建的因素可以有很多,例如:
- 构建规模太大,本地构建需要等待的时间太长。
- 项目规模比较大,不是所有开发人员都能很好地遵守这个习惯。
- 本地缺乏必要的构建环境。
理想情况下我们应该解决根本的问题,例如让开发机器的环境和持续集成机器的环境一致、让集成的时间变短、培训大家有持续集成的意识等等。下面我要说的是,当上述问题不能够得以简单解决的时候,可以考虑的另一种持续集成测试,那就是延迟提交。
简单来说,延迟提交就是让代码变更在被提交进源码仓库之前,先由持续集成服务器执行一次单独的构建,只有在这次构建成功之后,才让代码变更真正的进入源码仓库,进行真正的集成。
这么做相当于把本地构建的工作转移给持续集成服务器,但不论如何,变更进入源码仓库之前都需要一层构建保障。延迟构建如何实现呢?基本上有这么两种方式:
- 把变更集直接发送给持续集成服务器,持续集成服务器为其执行一次单独构建,构建成功后把变更集提交进源码仓库。
- 开发人员提交代码至一个单独的源码分支,持续集成服务器监视该分支,发现有变更则执行单独构建,构建成功后把变更合并到主干分支。(合并可以由持续集成服务器自动完成或者由开发人员手动完成)
下面让我们以TeamCity和Git为例来看一下如何实现第二种方式。(之所以不使用更流行的Jenkins而是用TeamCity是因为我发现TeamCity对延迟提交的支持更好,详见 http://www.jetbrains.com/teamcity/features/delayed_commit.html 。)
首先,除了Git的master分支,我们还需要一个单独的分支来做延迟提交:
起名为 remote-run/exp1 是为了符合TeamCity的命名规范,TeamCity有一个名为 Branch Remote Run Trigger 的东西监视特定的 Git 分支,而它默认的模式就是 remote-run/* :
当我修改 remote-run/exp1 分支的内容,例如破坏了构建,这时显然不会对 master 产生任何影响,因此一般人查看TeamCity页面的时候不会看到任何变化。然而,当我自己以用户 juven 登陆 TeamCity (我的Git提交 username 也是 juven ),就能从 MyChanges 页面看到一个失败的构建:
从图中能看到这次构建是基于 exp1 分支的,点击页面中的其他链接我能得到进一步的信息,例如文件变更diff,构建日志等等,这都能帮助我分析构建失败的原因。上图中给我们还能看到另一次名为 fixed 的构建,其对应的颜色是绿色,那是我之后又在 exp1 分支进行了提交,这次提交修复了构建。
最后,在确认我的几次变更没有问题之后,我可以安心的把这些变更合并到 master 分支:
这会触发 master 分支的集成,这个时候的集成当然也非常安全了。当然这样的合并大部分事件持续集成服务器应该也能完成,虽然目前 TeamCity 不支持,但也 在计划中了。
整个过程其实也不复杂,当然这里有个前提,就是持续集成服务器需要提供很多能够执行单独构建的 Agent ,如何自动化管理这些 Agent ,让它们的环境保持一致,这不是简单的事情。TeamCity 服务器其实只是个调度器,具体的构建工作都交由 Agent 完成,这一点,换成 Jenkins 也是差不多的原理。
除了这种用单独分支的方式,我们也可以直接发送变更集给持续集成服务器,TeamCity 的实现方式使用 IDE 插件,具体信息可以参考 TeamCity 的维基页面。
其实有了像 Git 这样创建分支特别容易的版本控制工具,在 Jenkins 上用第一种方式实现延迟提交也不会比用 TeamCity 困难到哪里去,但我还是比较惊讶于 TeamCity 的易用性,这一改了我以前对商业工具软件的偏执看法,当然,这也就是不是本文所讨论的范畴了。
最后要提的是,如果你的项目不大,代码不是特别多,人员不是特别多,基本用不到延迟提交,应该把关注点放在快速集成、保持开发环境与击穿环境一致、以及良好的开发习惯上面。