简单来说,持续集成就是用来治疗神经衰弱的软件开发方法 (之一)。我自己的理解是,持续集成需要对每一次代码 提交走一次从代码集成到打包发布的完成流程,以判断提交的 代码会对这整个流程带来什么影响;除此之外,所有对工具和 流程的描述都是浮云,应该根据你自己使用的开发方法和环境 自行选择。

话说为什么要写这个?因为不久前众大爷突然讨论起这 玩意,要说Jenkins什么的话我还是在Ex公司用过的,就 写下来当总结和反省吧……

我的实施方法

  1. 环境:Linux(发布和部署)、Erlang
  2. 开发工具rebar、Subversion
  3. 持续集成工具Jenkins
  4. 团队规模:开发哥x3、测试妹x2

首先我们的项目是用Erlang写的,天生支持热更新,我们的发 布分两种:热更升级包和完整包;所以我在Jenkins里配置了 这样一个工程,它做5件事:

  1. 从开发branch更新代码;
  2. 编译;
  3. 进行简单的自动测试;
  4. 生成完整发布包;
  5. 生成升级包;
  6. 用最新的升级包热更新内部测试用的服务实例。

这样,从代码提交到部署到测试环境的整个过程都被自动化了, 我们的工单可以以最快的速度从开发哥移交到测试妹。

另外,虽然支持热更新,但像系统初始化时执行的代码也只有 重启服务才会生效,所以我将这个工程设置为手动触发,并且 主要由测试部门牵头:测试在向程序确认特定feature的代码 已提交后(通常就是收到工单时),触发自动集成,根据需要 重启服务,就可以进入测试流程了。

上面提到的“测试用的服务实例”部署在内部网络中,除重启外 总是保持在可用状态,新代码如果有问题,基本上可以在这个 实例上第一时间体现出来。

这样的实施方法从本质上是符合持续集成思想的,但是有些细 节会显得比较山寨,而且的确不够高效。

反省缺点

没有单元测试

上面第3步我写的是“简单的自动测试”,而不是“单元测试”, 这是为什么呢?因为我们的确木有单元测试。

项目刚开始的时候其实是有一组单元测试的——基本上都是我写 的——但是其他开发哥都觉得这个东西很多余,甚至有人就直接 说“我写的代码不会有问题的”。妹的没问题你现在还要每天加 班?

“简单的自动测试”其实只是检查数据合法性的东西,和代码逻 辑没有半毛钱关系。

所以项目后期常有“开发哥A把开发哥B的代码行为改掉却没人知 道”这种事情出现,而且到现在都没人知道测试覆盖率到底有多 低;我有点后悔没有强推单元测试。

没错,到现在我还是觉得单元测试是有必要的,没有单元测试 的“持续集成”连半调子都算不上……

没有对feature和bug进行跟踪

何谓“跟踪”?就是做到将每个commit与其对应的feature或者 bug工单联系到一起,在看svn log的时候能知道哪个commit 对应哪个工单,在看工单的时候也能找到对应的svn commit, 这样我们就进而能清楚知道每个自动集成的版本里包含哪些 feature和bug fix.

我们用redmine管理工单,其本身对subversion的支持就很好, 可以通过配置,让其在svn commit时分析程序哥填写的 message,将message和工单联系起来,甚至是自动关闭工单。 反过来,subversion也有相应的redmine插件,能简化一点对 工单的引用。

但是这些东西我们实际上都没用上,因为开发哥里有这样的 人:每次都将不止一个系统的代码一起commit,而且message 写的不是“新系统”就是“改bug”……质问他的时候竟然 还说“分开提交麻烦死了”,“写svn注释麻烦死了会影响效率 的”……

所以我们在做代码合并和真正的发布时,通常都要向代码作 者本人确认每个commit的内容;由于只有3位开发哥,所以这 种做法还勉强可以接受,但是这样做其实效率极其低下而且 不可能自动化,让我再来一遍的话,妹的绝对要把“svn message规范程度”纳入绩效考核。

“实践”通常是……

对现实条件的妥协。你也可以称之为“适应”。而且这里的“现 实条件”通常只是人的因素,和技术完全无关,毕竟推行方法 论的人不可能搞出制约推广的艰深技术,反而是写程序的人 在以各种理由排斥新的东西。

软件开发本质上是一种人的活动,但是“江山易改,本性难移”, 恰恰人又是最难改变的东西之一。