计划给内部好好写一篇CICD相关的博客,详细聊聊CI过程中可以玩的有意思的东西,先整理回顾一下之前的事情。

第一次亲密接触

第一次非正式接触 CI (Continuous Integration) 是在公司内部。

有人用一台虚拟机搭建了 Jenkins 来“联动”代码提交,进行前端自动构建,还记得要填写一堆配置脚本,每个脚本里还有一些写死的配置项(当时缺少配置服务平台),更新起来比较麻烦,起码要修改两处,在项目初期偶有修改项目结构的场景下,很多时候宁愿手动。

定制化的云端构建

后边团队有了云端统一构建服务,CI 功能集成到统一的“开发服务器”上,一方面构建环境的差异得到了有效抹平,另一方面,有了自动化过程,大家开始逐步添加核心逻辑的测试代码,以及开始顺手跑一下诸如 jshintjslint 之类的质量工具,线上构建结果、线下代码质量都有了一定的保障。

开源项目标配

与此同时,15年不经意之间接触到了 travis-ci ,惊叹原来 CI 工具的体验原来可以是这样的。

极少的配置,通用的阶段描述,剩下的都由工具来做,而且除了定制 Runtime ,还能够定制执行系统,对于想做跨平台开发的人,非常友好:构建环境和构建产物可以一致、稳定。

翻到当时的一个集成构建记录:jquery-city-select ,展示了使用不同 Node 0.10、0.12、iojs 分别对一个前端组件进行构建。

尝试第一次折腾

可能是出于对自动化的着迷,当时特别想拥有一套自己的开发环境,居然还跑去知乎还提了一个问题:你理想中的前端开发环境是怎么样的?现在使用的方式有什么缺点?

后面实在忍不住,折腾了一个demo,基于虚拟机的跨平台开发环境,包含了前端的自动构建。https://github.com/Pantimos

把下面提到的问题解决了一大半:

欢迎讨论和补充甚至广告,但是请简要说明:

大概想到以下场景:

❶ 单人开发完整项目。
❷ 单人开发组件模块。
❸ 多个前端协同开发业务模块。
❹ 前后端一起开发以及联调,以及冒烟前的自测。
❺ 离线开发,不强依赖线上服务。
❻ 评审等时候的临时显示需求。
❼ 多个不同环境依赖的项目同时进行。(update)
❽ 项目前后端不完全分离。

大家面对以上情况时候,在使用以及期望的理想环境是如何的?

补充问题:

① 考虑多人协作操作系统文件编码可能产生不一致,多人本地使用工具构建结果可能产生不一致的问题(不涉及编码风格),中心机构建有时不利于日常/线上调试的问题。
② 考虑非发布以及bugfixs,必须进行版本控制提交时候的开发(试验性质测试以及开发过程中的状态)。
③ 考虑后端童鞋可能接手简单的前端项目的开发或者调试时候的使用,但是不愿意去尝试复杂的前端发布流程。
④ 多个不同环境依赖的项目同时进行时,本地开发时因为使用的代理软件和语言runtime版本和线上不一致,或者不便模拟线上环境的时候,得到的相似(不是近似)环境可能带来的影响。
⑤ 本地虚拟化服务来在某些时刻替代中心机服务,是否对于本地开发过重,如果本地虚拟化可以比较完善的解决上面的问题,那么值得使用么。

然而离线不是必选,尤其是随着网络基础设施的进化,网络质量越来越好是大趋势,交付效率的提升、交付质量的提高之外,更应该关注协同效率。

尝试第二次折腾

随后来到美团,团队起步阶段想做各种 MVP Demo,发现公司内部缺少 PaaS (新浪云不要太爽),构建过程缺少CI(淘宝不要太爽),开发时感觉十分痛苦,忍耐着使用了本地起Nginx、开发服务器同步本地构建产物等一次性方案解决了这个问题。

不久之后,看到有一个前端的小伙伴做了一套山寨的 Travis CI,但是好像只支持按照一定特殊使用规范下的项目接入,能用但是感觉不够好用,这个显然不是我想要的自动化工具。

随后技术工程部入职了一位来自 Google 的大神,海波大神想要重新打造一套先进的基础设施,包含代码仓库、持续集成、运行环境等。其中持续集成便是基于 docker 的容器化excuter ,可以看做特异化的 compose,这个是我想要的,但是和公司特殊场景耦合太重,自己想做一个小东西的时候,太麻烦了。

短暂思考之后,发现这这个设施应该是极度贴近代码仓库,那解决方案也就呼之欲出了:支持WebHook的代码仓库+WebHook+docker-compose,实验过程产物common-webhook-template

围绕代码仓库进行的自动化

WebHook

Jira、GitHub、GitLab等软件的功能是不同的,故实现标准也是不同的,需要额外维护数据接入层,比较麻烦。

最好是能够使用官方维护的推荐工具,诸如:GitLab-Runner。

构建过程

最开始使用过WebHook调用远程服务器脚本,诸如:

  • openresty+none-block sock
  • PHP等语言提供的system调用等

但是随着接入项目一多,尤其是跨语言的项目多了之后,维护构建脚本十分麻烦,比如初始化PHP fpm、HHVM cgi、node.js+pm2、Java Jetty完全不是一个套路,后面有新的技术栈的时候,这个构建脚本就得多一套。

然后尝试把这类东西打包成docker fat镜像,(docker当虚拟机用),发现几个额外的问题:

  • 镜像基础环境更新,性能提升或者安全补丁修正,是必要重打一次完整镜像。
  • 基础运行代码打到镜像里,频繁改动的时候,镜像也得重构建,浪费时间,浪费资源。
  • 镜像里的应用进程得自己进行维护,而且要把每个镜像维护出一个foreground running的进程。
  • 涉及到应用之间交换数据的时候,除非靠母鸡起一个网关交换流量,不然维护起来也很麻烦。

然后接触到了compose,从1.x开始,到2.x,再到现在的3.x,功能越来越强大,(docker + compose)性能也越来越好。

从使用 docker-compose up,使用回调方案异步告知构建过程结束,到配置文件定义机器资源配置,直接使用docker-compose run同步等待构建结果完成,中间的折腾也是不足为外人道了。

内外差异

内部CI系统的标杆

GitLab是一个好软件,盘点了一下,基本贯穿了正式工作以来的多数公司:

  • 新浪云12还是13年就把SVN迁移成了Git,使用GitLab进行代码管理,个人同一时间开始使用虚拟机跑GitLab的方案折腾一些小东西。
  • 淘宝从14年开始,逐步把SVN迁移到了Git,使用GitLab进行代码管理;
  • 美团记忆中好像还是jira的那套,不太确定了,个人开始使用dockerize GitLab继续折腾。
  • 阿里云也是14年开始就在使用Git了,使用GitLab进行代码管理。
  • 小赢好像是在我来到之前,就迁移了Git,使用GitLab进行代码管理。

对于团队,或者对于家里有机柜的同学来说,起步4G的内存没什么,随便一台老笔记本、老服务器、mini NAS都能跑的起来。

但是如果你有公网需求,代码又是介于公开和私有状态的半成品,但是又要联动 CI,想要进行自动化构建,跑基于构建结果的定时任务…

公网跑一台2C4G的云服务器,还是比较奢侈的,要知道虚拟CPU的云服务器,尤其是国内服务器,除了带宽,贵就贵在“储存”上,这里可以使用秒级付费的产品,但是构建实时性势必又有妥协了。

外部CI系统轻量

那么,不如稍稍差异化,在构建方案保持使用 docker 容器进行执行,严格保障构建环境一致的原则下,替换掉重型的GitLab+GitLab Runner:

  • 使用 GitHub(考虑敏感性可以使用 GH 私仓)或者自建 gogs 进行代码托管。
  • 使用 Drone 进行简单的 CI 集成。

目前除了不好实现并发的任务过程,文档存在一些缺失,实际使用要偶尔翻一下源码,总体来说体验还是不错的。

后续

稀稀疏疏地按照时间线展开了不少内容,后面有机会再补充一些其他的吧:

  • CI 过程的流程分层设计
  • CI 过程的数据敏感处理
  • CI 过程的构建产物贮存

暂时搁笔。

–EOF