简单来说,持续集成就是用来治疗神经衰弱的软件开发方法 (之一)。我自己的理解是,持续集成需要对每一次代码 提交走一次从代码集成到打包发布的完成流程,以判断提交的 代码会对这整个流程带来什么影响;除此之外,所有对工具和 流程的描述都是浮云,应该根据你自己使用的开发方法和环境 自行选择。
话说为什么要写这个?因为不久前众大爷突然讨论起这 玩意,要说Jenkins什么的话我还是在Ex公司用过的,就 写下来当总结和反省吧……
我的实施方法
首先我们的项目是用Erlang写的,天生支持热更新,我们的发 布分两种:热更升级包和完整包;所以我在Jenkins里配置了 这样一个工程,它做5件事:
- 从开发branch更新代码;
- 编译;
- 进行简单的自动测试;
- 生成完整发布包;
- 生成升级包;
- 用最新的升级包热更新内部测试用的服务实例。
这样,从代码提交到部署到测试环境的整个过程都被自动化了, 我们的工单可以以最快的速度从开发哥移交到测试妹。
另外,虽然支持热更新,但像系统初始化时执行的代码也只有 重启服务才会生效,所以我将这个工程设置为手动触发,并且 主要由测试部门牵头:测试在向程序确认特定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规范程度”纳入绩效考核。
“实践”通常是……
对现实条件的妥协。你也可以称之为“适应”。而且这里的“现 实条件”通常只是人的因素,和技术完全无关,毕竟推行方法 论的人不可能搞出制约推广的艰深技术,反而是写程序的人 在以各种理由排斥新的东西。
软件开发本质上是一种人的活动,但是“江山易改,本性难移”, 恰恰人又是最难改变的东西之一。