我之前的博客《Jenkins 多分支构建》及《Jenkins 多分支构建中的邮件配置》探索了在多分支构建中Jenkinsfile的配置。然而在我的配置中,根节点为node
,但里面却没有使用Jenkinsfile的DSL去声明构建的流程,而是通过groovy代码去实现整个的构建逻辑,用try-catch
处理构建失败的问题,看起来很混乱。并且,整个构建本来有拉取并检出代码、构建、发布这几个阶段,但是在Jenkinsfile里却没有体现出来,所以当发现构建较慢时也不利于定位问题所在的步骤。本篇文章将完全处理这些问题。
简单的stage声明
我们还是以之前的代码为例,这里为了专注于具体的配置,我简化一下构建命令及省略掉发邮件的代码,如下:
node { checkout scm echo "current branch: $BRANCH_NAME" try { if (BRANCH_NAME.startsWith("release/")) { sh "./gradlew clean -Ppublish assemble" } else { sh "./gradlew clean assembleTest" } currentBuild.result = 'SUCCESS' } catch (any) { currentBuild.result = 'FAILURE' throw any } finally { if (currentBuild.result == 'FAILURE') { // send e-mail } } }12345678910111213141516171819
如果说,要把这个流程划分为多个阶段,那还是挺简单的,在node
下增加stage
节点就可以了,如下:
node { stage('Checkout') { checkout scm } stage('Build') { echo "current branch: $BRANCH_NAME" try { if (BRANCH_NAME.startsWith("release/")) { sh "./gradlew clean -Ppublish assemble" } else { sh "./gradlew clean assembleTest" } currentBuild.result = 'SUCCESS' } catch (any) { currentBuild.result = 'FAILURE' throw any } finally { if (currentBuild.result == 'FAILURE') { // send e-mail } } } }1234567891011121314151617181920212223
简单一加,构建一,在Jenkins web页面上就出现了个Stage View了。但是Jenkins会提示我们,这种方式的stage声明已经弃用了。所以接下来介绍一下我所探索的更完整的Jenkinsfile写法。
Pipeline DSL
我们先上一张项目最终的Stage View截图:
这是实际项目的效果,多了加固和热修复相关阶段,本文暂时跳过。接下来,还是使用原来的例子,介绍一下如何实现它。
agent
首先,我们的根节点应声明为pipeline
。
然后在pipeline
下,我们再声明一个agent
节点。这个可就厉害了。比如通常我们会有多个构建从节点,但这多个构建节点的配置可能不同,比如有的只配置了Android环境用于执行Android项目构建,有的只能执行iOS项目构建,有的是用于执行Go项目的。那这么多不同的节点怎么管理及分配呢?那就是通过对节点声明不同的标签label
,然后在我们的构建中指定标签,这样Jenkins就会找到有对应标签的节点去执行构建了。假设我们现在用于执行Android项目构建的节点配置了Android
标签,那么我们的配置将如下:
pipeline { agent { label 'Android' } }12345
options
在pipeline
内,我们还可以定义一个options
,这个可以用于做什么呢?比如我的构建从节点资源有限,所以构建并发数我只定义为2。如果某个构建因为一些网络或其他问题卡住了,build了三天三夜都没停下来,其他要构建的任务(job)就只能排队一个个执行了,如果再来一个构建任务,它又构建了好久没停下来,那么后面的任务就都等不到了。通常遇到这样的情况我们需要手动去取消一下任务,而options
里我们可以为整个构建配置一个超时时间。
比如我们的Android项目,通常整个构建都不会超过半个小时,那我们就配置超时时间为半个小时,如果它超时了,就会终止这次的构建。因此,我们的配置修改为如下:
pipeline { agent { label 'Android' } options { timeout(time: 30, unit: 'MINUTES') } }12345678
options
还有其他配置,比如失败后重试整个pipeline的次数:retry(3)
。其他的就不一一介绍了,可翻文档。
stages
接下来就是这篇博客的重点之一了。
前面提到,直接添加stage
是过时的做法。那么现在未过时的做法是什么呢?那就在在stages
里声明。
我们在pipeline
下,增加一个stages
节点,然后在这个节点里再增加不同的stage
。需要注意的是,这里我们已经有默认的检出代码了,所以不需要再写checkout scm
。我们将前面的构建步骤,划分为构建和发布。所以我们的Jenkins脚本改为如下:
pipeline { agent { label 'Android' } options { timeout(time: 30, unit: 'MINUTES') } stages { stage('Build') { steps { sh './gradlew assembleTest' } } stage('Publish') { steps { sh './gradlew firTest' } } } }1234567891011121314151617181920
注:上面的firTest
是我编写的发布到fir.im的插件里的任务。
但是有一点要注意,所有分支都要执行构建,却只有release
分支才需要发布到fir上供测试人员下载测试。所以我们需要对Publish
阶段增加一个条件,即什么时候下执行,如下:
stage('Publish') { when { expression { BRANCH_NAME ==~ /release\/.*/ } } steps { sh './gradlew firTest' } }12345678
这里用到了groovy的正则匹配的语法,即BRANCH_NANE
以release/
开头时,才执行下面的步骤。
注意这里的steps
,是可以增加多个步骤的。比如构建成功后想要发个消息通知,那就里面增加发个消息通知的命令。
post
上面的stages
完成了我们对构建分阶段步骤的需求,但是我们还需要构建失败时能够发邮件通知到我们,这里就用到了post
节点了。
我们在pipeline
内增加post
节点,它定义的是在阶段运行结束时的操作,它支持这样一些后置条件:
always
总是运行,无论成功、失败还是其他状态。changed
当前状态与上一次构建状态不同时就运行failure
当前失败时才运行success
当前成功时运行unstable
不稳定状态时运行aborted
被终止时运行。
我们这里需要在失败时进行邮件通知,所以我们添加这样的节点内容:
post { failure { // send e-mail } }12345
最终我们的Jenkinsfile如下:
pipeline { agent { label 'Android' } options { timeout(time: 30, unit: 'MINUTES') } stages { stage('Build') { steps { sh './gradlew assembleTest' } } stage('Publish') { when { expression { BRANCH_NAME ==~ /release\/.*/ } } steps { sh './gradlew firTest' } } } post { failure { emailext( subject: "Jenkins build is ${currentBuild.result}: ${env.JOB_NAME} #${env.BUILD_NUMBER}", mimeType: "text/html", body: """<p>Jenkins build is ${currentBuild.result}: ${env.JOB_NAME} #${env.BUILD_NUMBER}:</p> <p>Check console output at <a href="${env.BUILD_URL}console">${env.JOB_NAME} #${env.BUILD_NUMBER}</a></p>""", recipientProviders: [[$class: 'CulpritsRecipientProvider'], [$class: 'DevelopersRecipientProvider'], [$class: 'RequesterRecipientProvider']] ) } } }
本文出自http://www.pianshen.com/article/3494182889/
jenkins2 pipeline插件的10个最佳实践参考链接https://www.cnblogs.com/itech/p/5678643.html