Jenkins的一些实践

Sep 11, 2011

持续集成已经是大家都非常熟悉的概念了,可以参考Martin的文章Continuous Integration .而Jenkins(原名hudson)正是业界最为流行的持续集成引擎.本文正是总结了近期工作之中一些使用jenkins的收获.

Keep the Build Fast

保持CI(持续集成服务器)上的工作快速是一个非常重要的方面, 这样才能提供快速的反馈.没有人会忍受一个构建跑上一个小时,毕竟喝上一个小时的茶或者咖啡也还是真是蛮浪费时间的. 之前的持续集成构建都得跑上半个小时,因为这个构建的代码库非常大,不止一个项目.每次构建都会按照一下顺序逐一执行: 可以看出这是一个具有完整构建阶段的流程. 但是每一个阶段都是按照顺序执行,是不是它们之间有严格的依赖了? 比如跑javascript单元测试得先跑quality检查了?   Quality Check大致使用metric_fu等质量检测的工具来进行,包括检查代码复杂度,重复度, 以及jslint语法的检查等等. 这就跟javascript单元测试这个阶段没有直接的耦合.同样的也可以对其他阶段进行分析. 所以能否将每个阶段都抽取出来了作为一个独立的构建, 然后触发时每个构建都同时执行, 而不是顺序执行了?  这里我们可以使用Jenkins的一个插件Join.
This plugin allows a job to be run after all the immediate downstream jobs have completed.   In this way,  the execution can branch out and perform many steps in parallel, and then run a final aggregation step just once after all the parallel work is finished.
Join适合于"钻石"依赖型的项目. 也就是我们上面的构建流程可以转换成:                   可以看到上面的几个阶段之间没有什么依赖,同时它们却都有一个聚合的阶段,便是Build Artifact. 这样的好处在于位于钻石形状上方的构建job是可以并发的执行,相比顺序执行,时间可是节省不少. 对于一个代码库融合了多个项目的情况, 另外一件可以做得事情是, 对于每个特定的阶段按照不同项目或团队划分.比如cucumber构建,它可能是包括好几个项目的features.所以每一次测试失败, 首先是难以知道是哪个项目的feature挂了, 另外一个也是非常慢.  所以可以做得是将之前单独的一个cucumber构建, 按照不同项目进行划分, 比如projectA-cucumber , projectB-cucumber 等等. 对于这种情形,另外一个可以追踪的问题便是能不能把不同项目从同一代码库中抽离出来放在独立的代码库中, 或许上面提到的问题都不存在了.

Everyone can see what's happening

当每次准备好一个Jenkins,看到的构建状态与小球颜色的关系总是让人有点不习惯.为什么? 因为它用蓝色代表成功, 你可能想根据测试驱动开发我们熟悉的节奏"red-refactor-green", 如果构建成功的话,应该是绿色阿.因为蓝色更容易被色盲的人识别.所以如果你们项目没有色盲的人,就非常推荐使用GreenBall这个插件, 这样一来所有构建成功都会显示绿色.             对于团队中的个人而言,每次都得打开Jenkins的地址去查看构建状态,这个有时候太麻烦. 所以你可以尝试使用CCMenu,配合Growl, 你可以时时看到构建的状态. 对于个人,CCMenu可能已经满足了大部分需求. 但是如果团队稍微大一点, 比如4-5个人以上, 同时在一块地方,有没有更好的方式来显示构建的状态了?   我们通常会是有一个独立的显示器,放在大家抬头就能看到的位置, 这个显示器主要是显示构建的状态. 当然你可以是在显示器中打开Jenkins的地址,让大家自己查找想看的构建信息,但是就是噪音太大. 所以你可以尝试使用Jenkins的一个插件: Radiator View Plugin. 你可以增加一个View,然后选择Radiator View,并配置你想监控构建的一些信息.               这个看起来还满不错的, 而且配置简单. 在工作中,客户有好几个专门的显示器,用来显示每个构建的状态.类似于下图, 它是用python写的, 因为我也没学过python,借鉴了用户的UI设计, 就用ruby重写了一下.它每一个构建是一个小方块, 绿色表示构建成功, 红色表示失败, 蓝色表示正在构建,同时在右下端有时间戳表示当前构建的时间.这个项目正在开发,应该马上就会放到github上面.你只要给定jenkins的地址,以及你想关注的job的名字就可以了.这个可以参考jenkins-dashboard项目.                   是的, 除了这个之外, 还有高级的一点的The Hudson Bear Lamps. 用灯的颜色来表示当前构建的状态. 这个比上面的来得更加直观. 但是这个灯不知道国内能否买到. 还有一点从工作中学到的便是,对于大型的而且是分布式的团队而言, 如何让信息交流更通畅. 对于构建而言, 如果某一次提交将构建弄费了, 首先那个弄费的人(当然不一定是那个弄费的人在修构建)赶紧修改代码让构建通过, 同时还得让其他人,那些跟你不在一地的人知道当前失败的构建有人在处理. 在项目实践中, 就有这样的构建,如果某人将构建弄费,他(她)可以通过加bookmarklet小书签的方式来声明"是我将构建弄费,我正在修理中....", 这个小书签就是发出一个ajax请求,将当前声明人的名字,哪一个构建等信息发给服务器,服务器在修改html的结构在对应的构建上打上某人的名字的邮戳. 当然这个问题我是有疑问的, 理论上如果某一次你将构建搞失败了,第一件事应该是在CI上反转你的提交,这样别人就可以提交,而不必等你修理构建之后才能提交,这个实在是浪费别人的时间.当然这个前提上,大家遵守约定,就是必须是在构建为绿色的情况下才提交,不能说在构建失败后还继续提交.