上篇文章中,基于Jenkins pipeline构建了一个简单的持续交付过程。但这个过程仍有些问题需要完善,并没闭环。
之所以一个持续交付流程闭环的一个重要原因在于:
与其依赖人的自主与自觉性,还不如依赖计算机的自动执行与数据
比如,其中一个点就是:触发这个过程是手动的。这就有问题了,因为这个是需要手工执行的。
当然,如果是针对测试或生产,这个很合理,但如果连开发环境也是手工执行,就会很容易出现一种局面:
随时时间的推移与技术债务的增加,开发人员越来越不愿意主动的手工执行这个过程
本篇,继续从零到一,构建你的持续交付流程,这是第六篇,本系列其它文章为:
- 从零到一,构建你的持续交付流程(一):一个持续交付流程的构思
- 从零到一,构建你的持续交付流程(二):好的工程实践是必要的前提
- 从零到一,构建你的持续交付流程(三):搭建基于Jenkins Docker的持续交付环境
- 从零到一,构建你的持续交付流程(四):利用Docker,将服务容器化
- 从零到一,构建你的持续交付流程(五):使用Jenkins Pipeline,让交付流程与自动化
一)
为什么要闭环?
因为在团队中,推行好的工程实践的一个重要原则是:
约束要具有一定的强制性
如果没有一定的强制性,好的工程实践很难得到执行与贯彻。
比如我们拿单元测试来举例,如果团队取得共识或管理者定下规定:要求编写单元测试。那很显然,这是一个很好的开始。
但如果没有持续的数据跟踪,那慢慢的也许大家就会不再编写单元测试,如果只是依赖个人自觉性,这个坦率的说有点难。但是换种方式,如果能每周,每天甚至是每次提交代码都自动运行所有单元测试,得到覆盖率和执行结果,甚至是能细化到每个人的数据,再把这些数据邮件发送给所有干系人。
可以想像,这样就非常更有约束力了。因为,数据能很好的对事实进行检验。
这就是什么持续交付要闭环的原因所在。
如果你的持续交付,从执行开始就需要手工来点击某个按钮,这意味着很可能到后面,做这个事的频率越来越少,直至大家都不再重视这个交付过程。再如果你的持续交付中,没有单元测试及相关数据的计算并结果汇总,那同样意味着,大家到后面可能会慢慢的不再编写单元测试。
所以,好的工程实践一定要让数据说话。现在基本所有的产品都不存在收集数据方面的问题了。
当然,如果你在公司或对团队并没有太大的话语权,这个事就不要去做。我建议你从自己做起就行了,
二)
在上一章中的持续交付的流程中,有几个点我认为是一定要添加上去,以让整个过程闭环。
- 增加自动执行持续交付过程,持续交付的执行绝不能依赖相关人员心情好手工去触发(这个点不适合测试及生产环境)
- 增加邮件的反馈与通知。失败的交付一定要让大家都知道。
也就是最重要的是,让开始与结束后的提醒都自动化
当然,这两个其实都非常简单。
我简要说明下。
自动执行持续交付过程
我认为持续交付的执行一定是需要自动触发,也就是
在任何人提交代码之后,马上触发持续交付的流程
这样就使整个过程自动化,不需要人手工触发或主动触发这个过程。这是个非常重要的,因为这样这个过程就是自动的,就很容易形成一种强有力的约束,使得开发人员不得不关注自己提交代码的质量,因为很可能引发构建失败或单元测试不通过。
当然,要实现这个目标其实非常简单,主要是利用git中的webhook机制 Jenkins的远程触发URL机制结合起来实现
基本上包括国际上的主流Github或gitlab等,国内gitee以及coding,都支持webhook,允许提交时触发一个远程调用。而在Jenkins中,同样有类似的插件,比如Generic Webhook Trigger就是一个,支持webhook触发构建。
由于这种实现比较简单,就不再详细阐述相关细节。
不过这里有个细节,很多团队或公司可能没有这么多外网环境,所以这个点要考虑使用内网穿透技术,我基本都是使用的zerotier,配合nginx使用,非常方便。有兴趣的可以了解下。
添加邮件通知
如上所述,考虑到提交代码就会触发构建,这会导致构建较为频繁。这是计算机帮我们做的,所以我们并不需要在意它构建很频繁。
但关于邮件通知,第一它是有必要的;但第二,通知不需要像构建一样频繁,我们可能只关心失败的构建,以下上一次失败,下一次恢复成功这样的场景。
Jenkins Pipeline为类似的构建提供了绝佳的支持。
添加邮件通知的Pipeline脚本如下:
代码语言:javascript复制 pipeline {
agent any
stages {
stage('build') {
steps {
sh 'gradle build -x test'
}
}
stage('docker image build'){
steps {
sh 'docker build -t test-backend:1 .'
}
}
stage('start docker'){
steps {
sh 'docker run -dp 8090:8080 test-backend:1'
}
}
}
post {
fixed {
mail body: '构建恢复成功通知,失败的构建已恢复为成功状态',subject: '构建恢复成功', to: 'lingen.liu@gmail.com'
}
failure {
mail body: '项目构建失败,请立刻检查',subject: '构建失败通知', to: 'lingen.liu@gmail.com'
}
}
}
如上述代码所示,添加通知的操作主要在行24到行31。
定义了一个post行为,也就是交付流程执行完成后,当状态处于fixed(上次失败,本次成功)或处于failure(本次构建失败)状态时,发送邮件。
当然,Pipeline本身支持的状态挺多,不只这两个。
但在持续交付中,我们更关注这两个状态。
另外,这个通知生效的前提是在Jenkins中配置了邮件相关的设置。
(代码中的邮件内容是个简单的示例,实际上你可以填充非常丰富的内容,比如上次提交人,提交commit等。)
三)
另外,我在上篇文章中也说过,重启服务的方式是有问题的。
我们希望能做到重启服务,而不是每次docker run一个新的实例,这肯定有问题,而且还存在端口冲突。
一个可行的解决方案,就是使用docker compose
上面这个Pipeline修改过后,变成:
代码语言:javascript复制pipeline {
agent any
stages {
stage('build') {
steps {
sh 'gradle build -x test'
}
}
stage('docker image build'){
steps {
sh 'docker build -t test-backend:1 .'
}
}
stage('start docker'){
steps {
sh 'docker-compose stop'
sh 'docker-compose up -d'
}
}
}
post {
fixed {
mail body: '构建恢复成功通知,失败的构建已恢复为成功状态',subject: '构建恢复成功', to: 'lingen.liu@gmail.com'
}
failure {
mail body: '项目构建失败,请立刻检查',subject: '构建失败通知', to: 'lingen.liu@gmail.com'
}
}
}
可以看到,我使用了 docker-compose来管理docker服务,这个在单机部署上是非常方便的(比如针对开发或测试环境)。但如果是分布式的部署,你得考虑docker swam或k8s,记住我前面说的,要保持和生产一致,虽然不能做到生产的规模,但至少要是一个mini版的生产环境。
五)
当然,上面这个只是针对后端,一个真正的项目肯定包括前端,后端及各种数据存储。那包括所有端的应该是如何配置?
而且这个交付流程仅包含了最简单的,诸如单元测试,验收测试,API文档自动发布等过程均未加上。
这些都没有关系,我们要学会从最简单的开始,然后复杂的在简单的基础上不断丰富它就好了。
记住,解决问题永远有许多种方案。条条大路通罗马。
这个系列就不详细讲解这些细节了,这不是这个系列的目的。
从我前面写的这几篇文章来看,做一个持续交付,事实上简单的令人难以置信。我不认为一个工作几年的程序员会对这个事情觉得难以上手或不知所措。
也就是我的一个结论是:从零到一,易
但真正推行持续交付的,可能并不是非常多,一个容易的又正确的方式,为什么大家都不这么做。类似的包括TDD驱动开发也是同样的处境,这究竟是为什么?
下一篇:从零到一,构建你的持续交付流程(终):从零到一,易;从零到一,难