Jenkinsfile的pipeline配置
Posted 浩码农
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Jenkinsfile的pipeline配置相关的知识,希望对你有一定的参考价值。
本篇文章目测1700字,实际看完可能还不用6分钟。
我之前的博客《》及《》探索了在多分支构建中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
}
}
}
如果说,要把这个流程划分为多个阶段,那还是挺简单的,在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
}
}
}
}
简单一加,构建一,在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'
}
}
options
在pipeline
内,我们还可以定义一个options
,这个可以用于做什么呢?比如我的构建从节点资源有限,所以构建并发数我只定义为2。如果某个构建因为一些网络或其他问题卡住了,build了三天三夜都没停下来,其他要构建的任务(job)就只能排队一个个执行了,如果再来一个构建任务,它又构建了好久没停下来,那么后面的任务就都等不到了。通常遇到这样的情况我们需要手动去取消一下任务,而options
里我们可以为整个构建配置一个超时时间。
比如我们的Android项目,通常整个构建都不会超过半个小时,那我们就配置超时时间为半个小时,如果它超时了,就会终止这次的构建。因此,我们的配置修改为如下:
pipeline {
agent {
label 'Android'
}
options {
timeout(time: 30, unit: 'MINUTES')
}
}
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'
}
}
}
}
注:上面的firTest
是我编写的发布到fir.im的插件里的任务。
但是有一点要注意,所有分支都要执行构建,却只有release
分支才需要发布到fir上供测试人员下载测试。所以我们需要对Publish
阶段增加一个条件,即什么时候下执行,如下:
stage('Publish') {
when {
expression { BRANCH_NAME ==~ /release\/.*/ }
}
steps {
sh './gradlew firTest'
}
}
这里用到了groovy的正则匹配的语法,即BRANCH_NANE
以release/
开头时,才执行下面的步骤。
注意这里的steps
,是可以增加多个步骤的。比如构建成功后想要发个消息通知,那就里面增加发个消息通知的命令。
post
上面的stages
完成了我们对构建分阶段步骤的需求,但是我们还需要构建失败时能够发邮件通知到我们,这里就用到了post
节点了。
我们在pipeline
内增加post
节点,它定义的是在阶段运行结束时的操作,它支持这样一些后置条件:
always
总是运行,无论成功、失败还是其他状态。changed
当前状态与上一次构建状态不同时就运行failure
当前失败时才运行success
当前成功时运行unstable
不稳定状态时运行aborted
被终止时运行。
我们这里需要在失败时进行邮件通知,所以我们添加这样的节点内容:
post {
failure {
// send e-mail
}
}
最终我们的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']]
)
}
}
}
关注并后台回复“qq群”,获取Android高级开发群群号。
以上是关于Jenkinsfile的pipeline配置的主要内容,如果未能解决你的问题,请参考以下文章
Jenkins高级用法 - Jenkinsfile 介绍及实战经验
jenkins-使用Jenkinsfile来定义pipeline
在 Jenkins Pipeline/Jenkinsfile 中获取 git 分支名称