持续集成之“依赖管理”

发表于:2014-04-22来源:博客园作者:乔梁点击数: 标签:持续集成
在前文《分支策略(续)》中,我们讨论了多组件应用程序的持续集成策略,即:为相对独立的组件创建自己专属的代码库,然后通过现代持续集成工具进行组件间的持续集成。Joe的团队在首次发布之后,开始使用这种方式。然而,没有多久,他们就遇到了一个问题:一

  在前文《分支策略(续)》中,我们讨论了多组件应用程序的持续集成策略,即:为相对独立的组件创建自己专属的代码库,然后通过现代持续集成工具进行组件间的持续集成。Joe的团队在首次发布之后,开始使用这种方式。然而,没有多久,他们就遇到了一个问题:一次提交构建所花费的时间太长。

  一天,Joe就早早地来到了办公室。因为他前一天下班前,他开发的用户故事还有一小点就完事儿了。他想利用早上这点儿时间把它搞完,交给测试人员进行测试。他修改了某个模块的一段代码,在本地构建测试通过以后,就提交了, 然后起身去楼下买些早点。十五分钟后,他回到了电脑前,令他沮丧的是,这次构建还在进行最后的阶段,即所有模块集成测试和系统级测试。他只好又起身去冲了杯咖啡。然后,一边看着屏幕上的构建进度条,一边喝着咖啡。七分钟后,构建终于成功结束了。虽然这是一次成功的构建,但总是觉得不爽,花了二十多分钟才做完提交构建。于是,他开始仔细地查看起构建脚本和构建日志。

  一、一次生成,多次复用

  中午吃过午饭,他把Bob和Alice叫到一起,开始讨论早上他遇到的问题。

  “的确是非常烦人,现在构建时间太长了。”Alice说道。

  “我今天早上查看了一下我们的构建日志,发现构建时间长的原因之一是:每种测试开始之前都要更新代码,再重新编译一次。”Joe说道。

  Bob提出了一个解决方案,并画在了白板上。“我们是否可以建立统一的产物库,每次构建的产物都以一定的规则放在其中?这样,后续的测试需要使用这些二进制产物的话,直接从产物库中获取即可。”(如图1所示)

  “听上去不错。然而,我们是否需要把每次构建中产生的内容都放入产物库,这会非常快地吃掉我们的磁盘空间。”Alice不无担心的说。

  “目前构建完成以后,所有的产物都放在那台构建机器上。我们也遇到过因构建机器硬件问题或误操作将所有重要历史信息都丢失的事情。所以,我们至少需要备份。”Bob回答道,“另外,将每次构建的产物放在统一产物库中,我们就可以解决Joe刚才提出的重复编译问题。当然,我们需要有选择地将重要的构建产物放到统一产物库中,而不是所有内容。通过在每次构建后增加一个上传任务,让各小组将其认为有用的信息上传到产物库,比如构建日志、测试报告、构建后的二进制文件等。但一些临时文件就没有必要了。当然,这只能缓解产物库膨胀的速度。尽管持续构建的次数非常多,但我们并不是需要一直保持所有构建的产物,所以,可以定期删除那些没有保留价值的构建产物,比如对那些重要构建的产物进行标记,其它的就可以删除了。”

  Alice和Joe都点了点头,表示同意。但Joe的眉头马上又皱了起来。“嗯,好象这里还有点儿问题。”

  “什么问题?”Alice和Bob同时问道。

  Joe说道:“对于我们平台中的一些小游戏组件来说,这没有什么问题。因为它们的构建产物都不太大,网络传输带宽和速度都不是问题。但是,对于那些很大的二进制文件或测试数据来说,这么做的话,可能就有问题了。”大家都点了点头,并开始思考这个问题。

  忽然,Joe叫道:“不好意思,其实这不是个真正的问题。首先,我们的测试数据变化就不频繁,原来也没有放在产物库中,而是放在了一个共享目录中进行版本管理。所以,这部分在构建中的做法与之前没有什么不同。其次,对于较大的二进制文件,只要在需要它的构建机器上把它缓存起来。那么在下一次构建时,构建脚本可以对这个本地版本进行验证,如果版本正确且没有被破坏(比如通过MD5验证)就可以继续使用。否则,就再从统一产品库取出正确的文件将其覆盖就行了。”

  “这么做还有一个好处,而且是非常重要的好处。”Alice补充道,“我们的手工测试版本也可以从统一的产物库中拿到,这就保证了自动化测试所有的二进制文件与部署到手工测试环境中的二进制文件是同一个文件了,也就不会出现因重新编译时的环境不同而导致的不一致问题了。而当我们做上线部署时,也从这个统一产品库中获取,从而做到自编译开始直到上线部署的二进制包的一致性啦。”

  于是,Joe与团队一起对其持续集成平台和所有构建进行了改造,将其打造成了一个具有组织级产物库的持续集成和发布管理平台。他们不但有效地缩短了每次构建的时间,还可以轻松地通过产物库追踪到每个上线版本在代码版本控制库中的对应代码,让问题追查变得更容易了。

  二、依赖管理

  一个月后,根据市场的需求反馈,他们开发的一个游戏升级了,反应速度非常快,效果非常好。但引申出来的一个问题是:游戏和平台的升级频率不一致,持续集成应该怎么做。对于Joe的团队来说,是一个非常大的问题,因为他们的开发流程严重地依赖于持续集成平台。于是,Joe和团队的核心成员打算讨论一下,如何应对目前这种情况。

  在会议室的白板前,Joe画出了当前所用的持续集成策略(如前图所示)。

  Bob说道:“到目前为止,我们已经发布了几次,而且最近一次只发布了一个游戏应用。我们如何管理我们的发布流程呢?在我之前工作过的公司中,产品会有几个版本,包括稳定版本、已对外发布或即将发布的版本、最新版本:用于公司内部测试。每当将要发布新版本时,就拉出一个分支,进行内部测试,并修复严重的缺陷。当没有严重缺陷时,才能作为稳定版本公开发布。”

  Alice答道:“对于单个的软件交付产品来说,通常可以通过“按发布拉分支” 的方式进行开发,正如我们最开始所使用的持续集成策略。但是,现在我们的游戏平台与单个交付产品不同。我们有自己的服务器集群,只要测试覆盖率及测试质量足够好,测试速度足够快,我们就可以通过小流量试验部署后再大规模上线的方式进行发布。现在,我们的问题是由于各个游戏组件的发布频率各不相同,组件存在依赖关系,导致很难决定在持续集成过程中,到底应该使用哪个依赖版本。尤其是我们现在还有一个公共库,被多个组件使用。”

原文转自:http://kb.cnblogs.com/page/101101/