使用SVN+CruiseControl+ANT实现持续集成之一
--持续集成概念及CC原理介绍
该文章上了精华区,特把这个系列(三篇文章)的pdf文件共享给大家,并附送收集持续集成的ppt
1、使用CruiseControl+SVN+ANT实现持续集成之一(持续集成概念及CC原理介绍)
2、使用CruiseControl+SVN+ANT实现持续集成之二(环境搭建和配置介绍)
3、使用CruiseControl+SVN+ANT实现持续集成之三(构建操作及监视)
在前面的文章中,介绍自己当时所在团队的处境(使用.NET开发),一个不到十个人的研发团队在保证正常开发进度同时需要并发支持四、五十个项目问题处理,经常为了程序版本冲突、日常测试版本、发布版本提供等重复枯燥无味的手工劳动,导致团队成员身心俱疲。经历这样痛苦的一段时间,终于忍受不了,通过命令行实现了包括获取、编译、发布过程的集成,大大减轻版本编译的时间,此时还能见到团队成员一边编译程序一边聊天轻松的笑脸,这就坚定了自己持续集成的做法,不过可笑是当时自己对持续集成没有任何的概念,只是当时的状况逼自己走了集成之路。
这个工具在经历半年使用进行了一次升级,提供了更多的选项功能,参见升级版本介绍。另外随着公司业务的发展,2009年自己负责推出一个基于JAVA的产品平台,这个平台中包括了七八个子系统。一个困难就出现在我们面前,为了保持以前每周一次发版,每次编译发布都需要两三个小时,为了摆脱这种困局找了很多资料,学习了很多新的思想,对比了很多工具,最终使用了基于CruiseControl(以下简称CC)实现持续集成。
1. 持续集成概念
对于持续集成(Continuous Integration)这个术语源自 XP(极限编程)的一个最佳实践,随着XP近几年的推广持续集成被大家认可并实践,但持续集成并非 XP 的专利,持续集成完全可以应用在采取非XP 方法的项目里面。持续集成也不是一个新的概念,在这个术语出现之前,日创建(daily build)提供同样的含义,这个典型的代表就是微软,他们每天的工作都开始于每日零点的版本构建。持续集成和日创建主要区别就在于实施的频率上,随着 XP 社区的大师级人物 Martin Fowler等人所著《Continuous Integration》为其正名,持续集成这个术语就越来越多地出现在原来日创建出现的位置。
2. 持续集成优点
在传统开发模式中项目按照模块进行划分,等开发完成后再集成到一起进行测试,这种开发方法在小规模程序开发过程中并没有太大的不足。但随着软件技术的发展,软件规模也在扩大,软件需求越来越复杂,软件已经不能简单地通过划分模块方式来开发,因为很多Bug在项目早期就存在了,如果在最后集成的时候才发现问题,开发者需要在集成阶段花费大量的时间来寻找Bug,由于软件的复杂性,需要花费大量的时间进行定位,甚至有些需要调整底层架构。在这个阶段的除虫会议(bug meetings)特别多,会议的内容基本上都是讨论 bug 是怎么产生的,最后往往发展成为不同模块的负责人互相推诿责任。
持续集成最大的优点是可以避免这种传统模式在集成阶段的除虫会议。持续集成主张项目的开发人员频繁的将他们对源码的修改提交(check in)到一个单一的源码库,并 验证这些改变是否对项目带来了破坏,持续集成包括以下几大要点:
- 访问单一源码库,将所有的源代码保存在单一的地点(源码控制系统), 让所有人都能从这里获取最新的源代码,提倡开发人员频繁提交修改过的代码。
- 支持自动化创建脚本,使创建过程完全自动化,让任何人都可以只输入一条命令或者几次点击就完成系统的创建。
- 测试完全自动化,要求开发人员提供自测试的代码,让任何人都可以只输入一条命令或者几次点击就运行一套完整的系统测试。
- 支持自动化部署,能够按照不同的要求发布到测试、发布服务器,提供测试环境和发布程序包;
- 自动提供集成信息,按照不同情况提供通过邮件、报告等方式提供每次集成结果,并且提供发布平台大家能轻易看到集成的进度和结果
持续集成的关键是完全的自动化,自动读取源代码、编译、测试、部署、信息发布。对于每次成功的创建,要求在这个自动化过程中的每一步都不能出错,而最重要的一步是测试,只有最后通过测试的创建才是成功的创建。
在持续集成里面创建不再只是传统的编译那么简单,创建还应该包括自测试,自测试的代码是开发人员提交源码的时候同时提交的,是针对源码的单元测试,将所有的这些自测试代码整合到一起形成测试集,在所有的最新的源码通过编译之后还必须通过测试集的测试才算是成功的创建。这种测试的主要目的是为了验证创建的正确性,McConnell 称之为“冒烟测试”,在持续集成里面,这叫做集成验收测试Build Verify Test,简称 BVT。BVT 测试是质量的基础,QA 小组不会感受到 BVT 的存在,他们只针对成功的创建进行测试(如功能测试)。
持续集成有一个与直觉相悖的基本要点,那就是“ 经常性的集成比偶尔集成要好”。Martin Fowler 认为对于持续集成来说,集成越频繁,效果越好 ,如果你的集成不是经常进行的(少于每天一次),那么集成就是一件痛苦的事情,如果集成偶尔才进行一次(一周甚至一个月), 等到集成阶段发现bug,然后找原因解决bug,会耗费你大量的时间与精力,而且这种方式有点像传统的集成模式,这违背了持续集成的初衷。
根据 Martin Fowler 的观点,项目 bug 的增加和时间并不是线性增长的关系,而是和时间的平方成正比,两次集成间隔的时间越长,bug 增加的数量越是超过你的预期,解决 bug 付出的工作量也越大,而你越觉得付出的工作量越大,你就越想推迟到以后去集成,企图到最后一次性解决问题,结果 bug 产生的就更多,导致下一次集成的工作量更大,你越感觉到集成的痛苦,就越将集成的时间推后,最后形成恶性循环。
需要注意的是从项目的一开始就引入持续集成可以尽早的发现 bug,但是并不代表持续集成可以帮你抓到所有的 bug。持续集成的排错能力取决于测试技术,众所周知,无法证明已经经过测试的代码就已经找到了所有的错误。
前面列举了持续集成这么多优点,但是创建一个持续集成的环境技术上是比较复杂的,也需要一定的时间,关键是在于持续集成可以“及时”抓到足够多的 bug,从根本上消除传统模式的弊端,这就已经值回它的开销了。
ThoughtWorks 公司开放了其持续集成的工具CC的源代码,持续集成对于大部分开发人员来说就不再只是停留在口头上的漂亮的术语,任何人在掌握了持续集成的基础理论后,都可以使用CC来体会持续集成在项目开发中的巨大威力。
3. 集成框架
下个图描述持续集成的硬件环境,图中包括了一台独立的源码库服务器以及开发人员的终端(同时也是源码库服务器的客户端),出自对性能的考虑,建议CC 在一台独立的服务器上运行。当然你可以将 CC 放在发布服务器上甚至某个开发人员的终端上。
4. CC内部工作架构
下图是CC系统内部工作架构图:
CC主要依赖Build Loop循环构建实现,通过读取Config.xml配置文件信息,在每次轮询中完成源代码的检测、编译,然后把编译的版本发布Web容器中,以此同时把日志信息、发布结果通过RSS、邮件、网站等形式发布给干系人。
4.1. Build Loop
前面在讨论持续集成的时候讲到其最重要的特征之一是自动化,而 CC 的 Build Loop 就是为支持自动化而设计的,Build Loop 也是 CC 的核心。
Build Loop 从字面上理解就是循环创建的意思,CC 提供了一个守护进程( daemon),该进程自动根据配置的时间间隔(也可以指定某个具体时间)读取 CC 配置文件并进行循环创建(build cycle),每次 CC 都会重新加载配置文件(修改了配置文件不用重新启动 CC)。
Build Loop 过程中所做的工作如下:访问源码控制系统,查看是否有代码被修改,如果有,获取源码的新版本,并根据配置对源码进行一次 Build,创建一个日志文件,最后向开发人员通知 build 的结果,活动图如下:
因为 Build Loop 是根据配置文件的内容来进行的,根据上面 BuildLoop 所做的工作,我们可以猜出配置信息主要应该包括:定时创建的时间和源码库的访问信息(检查源码变化情况),创建任务信息(如指定 Ant 文件), 记录日志(创建结果),通知(通知的内容可以定制)。
4.2. CC 插件(Plugin)
CC 设计思想是one-size-fits-all,也 就是CC 是由一个很精小( 但是很强大)的核心( Build Loop)以及一些外部插件组成,这给使用者提供了很大的扩展空间,使用者可以根据需要扩展 CC的功能(提供新的插件),而且 CC 是开源项目,你还可以查看源码并修改CC提供的插件。CC提供了六种不同类型的插件:Listener、Bootstrappe、Modificationset、Schedule、Log以及Publisher,CC 的配置是围绕这些插件展开的,下面对这些插件进行一个简单的介绍:
- Listener:用于处理一些项目有关的事件;
- Bootstrapper:在 CC 进行创建之前运行,是创建前的准备工作
- Modificationset:访问源码控制系统(如 CVS,VSS,ClearCase 等等),查看源码自上一次 Build 之后是否被修改过,并据此决定是否需要进行下一次 Build。
- Builder:对项目进行创建,熟悉 ANT 的使用者应该很清楚创建的含义,这里简单提一下,一次典型的创建包括了对项目源码的编译,测试,打包
- Schedule:设置轮询时间并且指定使用ANT编译所使用的配置文件地址
- Publisher:用于发布创建的结果,可以通过 email 的方式通知开发人员。