我以前的博客《Jenkins 多分支構建》及《Jenkins 多分支構建中的郵件配置》探索了在多分支構建中Jenkinsfile的配置。然而在個人配置中,根節點爲node
,但裏面卻沒有使用Jenkinsfile的DSL去聲明構建的流程,而是經過groovy代碼去實現整個的構建邏輯,用try-catch
處理構建失敗的問題,看起來很混亂。而且,整個構建原本有拉取並檢出代碼、構建、發佈這幾個階段,可是在Jenkinsfile裏卻沒有體現出來,因此當發現構建較慢時也不利於定位問題所在的步驟。本篇文章將徹底處理這些問題。html
咱們仍是以以前的代碼爲例,這裏爲了專一於具體的配置,我簡化一下構建命令及省略掉髮郵件的代碼,以下: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
咱們先上一張項目最終的Stage View截圖:
express
這是實際項目的效果,多了加固和熱修復相關階段,本文暫時跳過。接下來,仍是使用原來的例子,介紹一下如何實現它。網絡
首先,咱們的根節點應聲明爲pipeline
。
而後在pipeline
下,咱們再聲明一個agent
節點。這個可就厲害了。好比一般咱們會有多個構建從節點,但這多個構建節點的配置可能不一樣,好比有的只配置了Android環境用於執行Android項目構建,有的只能執行iOS項目構建,有的是用於執行Go項目的。那這麼多不一樣的節點怎麼管理及分配呢?那就是經過對節點聲明不一樣的標籤label
,而後在咱們的構建中指定標籤,這樣Jenkins就會找到有對應標籤的節點去執行構建了。假設咱們如今用於執行Android項目構建的節點配置了Android
標籤,那麼咱們的配置將以下:併發
pipeline { agent { label 'Android' } }12345
在pipeline
內,咱們還能夠定義一個options
,這個能夠用於作什麼呢?好比個人構建從節點資源有限,因此構建併發數我只定義爲2。若是某個構建由於一些網絡或其餘問題卡住了,build了三天三夜都沒停下來,其餘要構建的任務(job)就只能排隊一個個執行了,若是再來一個構建任務,它又構建了很久沒停下來,那麼後面的任務就都等不到了。一般遇到這樣的狀況咱們須要手動去取消一下任務,而options
裏咱們能夠爲整個構建配置一個超時時間。
好比咱們的Android項目,一般整個構建都不會超過半個小時,那咱們就配置超時時間爲半個小時,若是它超時了,就會終止此次的構建。所以,咱們的配置修改成以下:app
pipeline { agent { label 'Android' } options { timeout(time: 30, unit: 'MINUTES') } }12345678
options
還有其餘配置,好比失敗後重試整個pipeline的次數:retry(3)
。其餘的就不一一介紹了,可翻文檔。ide
接下來就是這篇博客的重點之一了。
前面提到,直接添加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_NANE
以release/
開頭時,才執行下面的步驟。
注意這裏的steps
,是能夠增長多個步驟的。好比構建成功後想要發個消息通知,那就裏面增長髮個消息通知的命令。
上面的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']] ) } } }