Jenkinsfile的pipeline配置

我以前的博客《Jenkins 多分支构建》及《Jenkins 多分支构建中的邮件配置》探索了在多分支构建中Jenkinsfile的配置。然而在个人配置中,根节点为node,但里面却没有使用Jenkinsfile的DSL去声明构建的流程,而是经过groovy代码去实现整个的构建逻辑,用try-catch处理构建失败的问题,看起来很混乱。而且,整个构建原本有拉取并检出代码、构建、发布这几个阶段,可是在Jenkinsfile里却没有体现出来,因此当发现构建较慢时也不利于定位问题所在的步骤。本篇文章将彻底处理这些问题。html

简单的stage声明

咱们仍是以以前的代码为例,这里为了专一于具体的配置,我简化一下构建命令及省略掉发邮件的代码,以下:node

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节点就能够了,以下:git

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写法。web

Pipeline DSL

咱们先上一张项目最终的Stage View截图:
Stage Viewexpress

这是实际项目的效果,多了加固和热修复相关阶段,本文暂时跳过。接下来,仍是使用原来的例子,介绍一下如何实现它。网络

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项目,一般整个构建都不会超过半个小时,那咱们就配置超时时间为半个小时,若是它超时了,就会终止此次的构建。所以,咱们的配置修改成以下:app

pipeline {
    agent {
        label 'Android'
    }
    options {
        timeout(time: 30, unit: 'MINUTES')
    }
}12345678

options还有其余配置,好比失败后重试整个pipeline的次数:retry(3)。其余的就不一一介绍了,可翻文档。ide

stages

接下来就是这篇博客的重点之一了。
前面提到,直接添加stage是过期的作法。那么如今未过期的作法是什么呢?那就在在stages里声明。
咱们在pipeline下,增长一个stages节点,而后在这个节点里再增长不一样的stage。须要注意的是,这里咱们已经有默认的检出代码了,因此不须要再写checkout scm。咱们将前面的构建步骤,划分为构建和发布。因此咱们的Jenkins脚本改成以下:post

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_NANErelease/开头时,才执行下面的步骤。
注意这里的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/

相关文章
相关标签/搜索