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/

相關文章
相關標籤/搜索