对于持续集成(Continuous Integration)及其相关的一系列工具,比如 Jenkins、Travis CI 等等,我想所有的程序猿都是耳熟能详、如雷贯耳了,但是真正能够在项目中用好的却又实在是屈指可数、凤毛麟角啊。可能有人会把这个问题归罪于国内 IT 业的急功近利,但事实上远在大洋彼岸的美国也好不了多少。
上图是今年在旧金山的持续交付(Continuous Delivery)会议上,针对 100 个企业做的调查。哇哦,100%,所有的企业都在使用 Jenkins!
然并卵!再看下图,没有一个企业觉得自己的持续集成很酷,仅有 17% 的企业觉得还凑合。
是什么原因造成这么巨大的差异呢?究其原因,排除企业组织架构的因素,从技术层面上来说,最主要的可能有以下几点:
持续集成远远不是 Jenkins、Travis CI 等工具的组合,也没有什么放之四海而皆准的银弹,而是需要切实根据自身项目的情况,按照持续集成的思想,努力的去解决上面提到的不稳定、批量化和反馈慢等等问题。本文不准备从方法论的角度,展开探讨各种敏捷开发的技巧,而是从一个实际的案例,来分享一下在 DaoCloud 上构建基于 Docker 的持续集成的过程中,我们是如何应对上述问题的,希望以此给大家一些小小的启发。
Docker 作为目前最流行的容器化技术的代表,可以完美的解决各种由于系统配置问题而导致的不稳定。系统运行的操作系统版本被定义了,系统运行所依赖的库及其版本被定义了,甚至系统执行所需要的第三方系统(比如数据库、消息中间件、分布式缓存系统等等)及其版本也被定义了。最重要的是,这些都是通过类似 Dockerfile 这样的代码文件来定义的,并且都可以进入版本库进行保存。这样的话,所谓的Software Architecture as Code
就得以实现,从而为持续集成奠定了坚实的基础。
DaoCloud 是业界领先的企业级容器云平台和解决方案提供商,致力于以 Docker 为代表的容器技术,为企业打造面向下一代互联网应用的交付和运维平台。
DaoCloud 提供了与主流的代码托管平台的无缝整合,支持如 Github、Bitbucket、Coding、GitCafe 等国内外开发平台。我们使用一个 Github 上的共享项目为例,在 DaoCloud 中可以非常便捷的从这个 Github 项目中导入代码,然后以此为基础,创建一个 Docker 镜像(Image),并且启用持续集成的功能,如下图所示:
这样,每次对于 Github 上项目的 commit,都会触发一次 DaoCloud 上的持续集成过程,这样就避免了批量化提交更新的问题,使得问题可以更快更早的被暴露出来。同时,DaoCloud 也支持根据 commit message 来动态决定是否要进行持续集成,从而提高了灵活性。
目前,DaoCloud 使用自主研发的 CI 执行引擎,支持诸如 Golang、Python、Ruby、Java 等多种语言和 MySQL、Redis、MongoDB 等多种外部服务,并且这个语言和服务的名单还在持续增加中。正如我们之前提到的,持续集成并没有银弹,无需 Jenkins 那么庞大的系统和复杂的插件,DaoCloud CI 已经提供了基于 Docker 构建持续集成的必要条件。下面,让我们来深入看看它是如何工作的。
DaoCloud CI 通过解析和执行代码库根目录下的daocloud.yml
文件来完成持续集成,一个典型的文件如下所示:
image: daocloud/ci-golang:1.4
services:
- mysql
env:
- TESTSERVER = "1.2.3.4"
install:
- echo "Run scripts to setup a base environment"
- echo "e.g., apt-get install -y git-core"
before_script:
- echo "Run scripts to prepare our test environment"
- echo "e.g., scp php-sample.zip $TESTSERVER | ssh $TESTSERVER 'docker build' | ssh $TESTSERVER 'docker run'"
script:
- echo "Run unit tests, integration tests and end-to-end tests here"
- echo "e.g., phpunit test"
- echo "We use cloud test automation powered by SWATHub.com for end-to-end tests"
- curl --user support:3641623E61464C31A5D --data-urlencode "platform=Windows + Firefox" -d nodeName=swathub -d nodeType=swathub -d tags=DaoCloud -d isSequential=false http://cn.swathub.com/api/support/samples/sets/131/run
DaoCloud CI 提供了详细的日志信息,方便调试,如下图所示,持续集成各个步骤都成功执行,并且触发了 SWATHub 上的一个端到端的自动化测试 Job,在Windows + Firefox的平台上,并发的执行所有的测试用例。相关的测试用例和结果都可以在 SWATHub 网站上找到,只需要注册 SWATHub 用户,登录后即可在共享的 samples 项目中看到。
自动化测试是持续集成过程中至关重要的一个环节,否则系统的质量就无法保证,因为在高速迭代的开发过程中,完全依赖人工进行功能的验证无异是天方夜谭。按照经典的「测试金字塔」理论,从底层的单元测试、到模块之间的集成测试,再到基于 UI 的端到端测试,不同层次、不同类型的自动化测试,是互为补充、缺一不可的,相对于更偏重于开发人员的单元测试和集成测试,SWATHub 为端到端测试,提供了一种非编码的、云端的、多平台并行的实现方式,极大的提升了端到端测试的速度,加快了持续集成中自动化的反馈。
SWATHub 是云端的自动化测试 SaaS 平台,通过创新的非编码的流程搭建和执行方式,SWATHub 能够帮助团队简单、高效地保障互联网服务的质量。
如下图所示,SWATHub 中还集成了包括邮件、简聊、纷云等各种消息通知方式,每次持续集成中触发的自动化端到端测试,都会发送相应的消息给用户,并且在执行完毕之后,将执行结果整理成简要的报告通知用户,进一步提升了反馈响应的速度。
细心的同学可能注意到了,在上述的daocloud.yml
中有个准备测试环境的 before_script,我们是通过将最新的代码 push 到外部测试服务器,然后再通过 Docker 搭建测试环境的。其实,最完美的方法应该是直接利用 DaoCloud 来构建最新的 Docker 镜像,然后部署到 DaoCloud 的集群上去,这样就可以直接基于这个集群节点进行自动化测试。
好消息是,DaoCloud 的攻城狮们正是这么想的,上述自动构建并部署的 API 接口已经在开发中,预计很快就可以付诸实现,一个更快、更好、更稳定的基于 Docker 的持续集成指日可待!