《Jenkins 2.x實踐指南》讀書筆記-Jenkins 2.x pipeline語法

[TOC]html

1. 大概瞭解Groovy

能夠經過Groovy教程來了解。java

2. pipeline介紹

Jenkins pipeline其實就是基於Groovy語言實現的一種DSL(領域特定語言),用於描述整條流水線是如何進行的。流水線的內容包括執行編譯、打包、測試、輸出測試報告等步驟。node

2.1 pipeline最簡結構

pipeline {
    agent any 
    stages {
        stage('Stage 1') {
            steps {
                echo 'Hello world!' 
            }
        }
    }
}
  • pipeline:表明整條流水線,包含整條流水線的邏輯。
  • stage部分:階段,表明流水線的階段。每一個階段都必須有名稱。本例中,build就是此階段的名稱。
  • stages部分:流水線中多個stage的容器。stages部分至少包含一個stage
  • steps部分:表明階段中的一個或多個具體步驟(step)的容器。steps部分至少包含一個步驟,本例中,echo就是一個步驟。在一個stage中有且只有一個steps
  • agent部分:指定流水線的執行位置(Jenkins agent)。流水線中的每一個階段都必須在某個地方(物理機、虛擬機或Docker容器)執行,agent部分即指定具體在哪裏執行。

更多更詳細pipeline步驟參考文檔:
https://jenkins.io/zh/doc/pipeline/steps/git

以上每個部分(section)都是必需的,少一個,Jenkins都會報錯。github

衆所周知,jenkins好用最大致現它的衆多插件知足各類需求。並非全部的插件都支持pipeline的。
jenkins插件兼容pipeline列表:
https://github.com/jenkinsci/pipeline-plugin/blob/master/COMPATIBILITY.mddocker

2.2 post

post部分包含的是在整個pipeline或階段完成後一些附加的步驟。post部分是可選的,因此並不包含在pipeline最簡結構中。但這並不表明它做用不大。
根據pipeline或階段的完成狀態,post部分分紅多種條件塊,包括:shell

  • always:不論當前完成狀態是什麼,都執行。
  • changed:只要當前完成狀態與上一次完成狀態不一樣就執行。
  • fixed:上一次完成狀態爲失敗或不穩定(unstable),當前完成狀態爲成功時執行。
  • regression:上一次完成狀態爲成功,當前完成狀態爲失敗、不穩定或停止(aborted)時執行。
  • aborted:當前執行結果是停止狀態時(通常爲人爲停止)執行。
  • failure:當前完成狀態爲失敗時執行。
  • success:當前完成狀態爲成功時執行。
  • unstable:當前完成狀態爲不穩定時執行。
  • cleanup:清理條件塊。不論當前完成狀態是什麼,在其餘全部條件塊執行完成後都執行。post部分能夠同時包含多種條件塊。如下是post部分的完整示例。
pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                sh 'echo Build stage ...'
            }
            post {
                always {
                    echo "post condition executed: always ..."
                }
                changed {
                    echo "post condition executed: changed ..."
                }
                aborted {
                    echo "post condition executed: aborted ..."
                }
                regression {
                    echo "post condition executed: regression ..."
                }
            }
        }

        stage('Test'){
            steps {
                sh 'echo Test stage ...'
            }
            post {
                aborted {
                    echo "post condition executed: aborted ..."
                }
                failure {
                    echo "post condition executed: failure ..."
                }
                success {
                    echo "post condition executed: success ..."
                }
            }
        }

        stage('Deploy') {
            steps {
                sh 'echo Deploy stage ...'
            }
        }
    }
        post {
        unstable {
            echo "post condition executed: unstable ..."
        }
        unsuccessful {
            echo "post condition executed: unsuccessful ..."
        }
        cleanup {
            echo "post condition executed: cleanup ..."
        }
    }
  }

2.3 pipeline支持的指令

顯然,基本結構知足不了現實多變的需求。因此,Jenkins pipeline經過各類指令(directive)來豐富本身。指令能夠被理解爲對Jenkins pipeline基本結構的補充。
Jenkins pipeline支持的指令有:閉包

  • environment:用於設置環境變量,可定義在stagepipeline部分。
  • tools:可定義在pipelinestage部分。它會自動下載並安裝咱們指定的工具,並將其加入PATH變量中。
  • input:定義在stage部分,會暫停pipeline,提示你輸入內容。
  • options:用於配置Jenkins pipeline自己的選項,好比options {retry(3)}指當pipeline失敗時再重試2次。options指令可定義在stagepipeline部分。
  • parallel:並行執行多個step。在pipeline插件1.2版本後,parallel開始支持對多個階段進行並行執行。
  • parameters:與input不一樣,parameters是執行pipeline前傳入的一些參數。
  • triggers:用於定義執行pipeline的觸發器。
  • when:當知足when定義的條件時,階段才執行。

在使用指令時,須要注意的是每一個指令都有本身的「做用域」。若是指令使用的位置不正確,Jenkins將會報錯。app

2.4 配置pipeline自己

2.4.1 全局options

options 指令容許從流水線內部配置特定於流水線的選項。 流水線提供了許多這樣的選項, 好比 buildDiscarder,但也能夠由插件提供, 好比 timestamps.curl

Required No
Parameters None
Allowed Only once, inside the pipeline block.

可用選項

buildDiscarder
爲最近的流水線運行的特定數量保存組件和控制檯輸出。例如: options { buildDiscarder(logRotator(numToKeepStr: '1')) }

disableConcurrentBuilds
不容許同時執行流水線。 可被用來防止同時訪問共享資源等。 例如: options { disableConcurrentBuilds() }

overrideIndexTriggers
容許覆蓋分支索引觸發器的默認處理。 若是分支索引觸發器在多分支或組織標籤中禁用, options { overrideIndexTriggers(true) } 將只容許它們用於促工做。不然, options { overrideIndexTriggers(false) } 只會禁用改做業的分支索引觸發器。

skipDefaultCheckout
agent 指令中,跳過從源代碼控制中檢出代碼的默認狀況。例如: options { skipDefaultCheckout() }

skipStagesAfterUnstable
一旦構建狀態變得UNSTABLE,跳過該階段。例如: options { skipStagesAfterUnstable() }

checkoutToSubdirectory
在工做空間的子目錄中自動地執行源代碼控制檢出。例如: options { checkoutToSubdirectory('foo') }

timeout
設置流水線運行的超時時間, 在此以後,Jenkins將停止流水線。例如: options { timeout(time: 1, unit: 'HOURS') }

retry
在失敗時, 從新嘗試整個流水線的指定次數。 例如: options { retry(3) }

timestamps
預謀全部由流水線生成的控制檯輸出,與該流水線發出的時間一致。 例如: options { timestamps() }

newContainerPerStage
agentdockerdockerfile時,指定在同一個Jenkins節點上,每一個stage都分別運行在一個新的容器中,而不是全部stage都運行在同一個容器中。例如: options { newContainerPerStage() }

Example
pipeline {
    agent any
    options {
        timeout(time: 1, unit: 'HOURS') 
    }
    stages {
        stage('Example') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

指定一個小時的全局執行超時, 在此以後,Jenkins 將停止流水線運行。

2.4.2 階段option

stageoptions 指令相似於流水線根目錄上的 options 指令。然而, stage -級別 options 只能包括 retry, timeout, 或 timestamps 等步驟, 或與 stage 相關的聲明式選項,如 skipDefaultCheckout

stage, options 指令中的步驟在進入 agent 以前被調用或在 when 條件出現時進行檢查。

可選的階段選項

skipDefaultCheckout
agent 指令中跳過默認的從源代碼控制中檢出代碼。例如: options { skipDefaultCheckout() }

timeout
設置此階段的超時時間, 在此以後, Jenkins 會終止該階段。 例如: options { timeout(time: 1, unit: 'HOURS') }

retry
在失敗時, 重試此階段指定次數。 例如: options { retry(3) }

timestamps
預謀此階段生成的全部控制檯輸出以及該行發出的時間一致。例如: options { timestamps() }

Example
pipeline {
    agent any
    stages {
        stage('Example') {
            options {
                timeout(time: 1, unit: 'HOURS') 
            }
            steps {
                echo 'Hello World'
            }
        }
    }
}

指定 Example 階段的執行超時時間, 在此以後,Jenkins 將停止流水線運行。

2.4.3 在聲明式pipeline中使用腳本

聲明式pipeline是不能直接在steps塊中寫Groovy代碼。
Jenkins pipeline專門提供了一個script步驟,你能在script步驟中像寫代碼同樣寫pipeline邏輯。

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                script {
                    result = sh (script: "git log -1|grep 'Release'", returnStatus: true) 
                    echo "result: ${result}"
                }
            }
        }
    }
}

在script塊中的其實就是Groovy代碼。大多數時候,咱們是不須要使用script步驟的。若是在script步驟中寫了大量的邏輯,則說明你應該把這些邏輯拆分到不一樣的階段,或者放到共享庫中。共享庫是一種擴展Jenkins pipeline的技術。

2.5 pipeline內置基礎步驟

這裏介紹pipeline內置的一些步驟。

2.5.1 文件目錄相關步驟

deleteDir
刪除當前目錄,它是一個無參步驟,刪除的是當前工做目錄。一般它與dir步驟一塊兒使用,用於刪除指定目錄下的內容。

dir
切換到目錄。默認pipeline工做在工做空間目錄下,dir步驟可讓咱們切換到其它目錄。例如:dir("/var/logs") { deleteDir() }

fileExists
判斷文件是否存在。fileExists('/tmp/a.jar')判斷/tmp/a.jar文件是否存在。若是參數是相對路徑,則判斷在相對當前工做目錄下,該文件是否存在。結果返回布爾類型。

isUnix
判斷是否爲類Unix系統。若是當前pipeline運行在一個類Unix系統上,則返回true

pwd
確認當前目錄。pwd與Linux的pwd命令同樣,返回當前所在目錄。它有一個布爾類型的可選參數:tmp,若是參數值爲true,則返回與當前工做空間關聯的臨時目錄。

writeFile
將內容寫入指定文件中。
writeFile支持的參數有:

  • file:文件路徑,能夠是絕對路徑,也能夠是相對路徑。
  • text:要寫入的文件內容。
  • encoding(可選):目標文件的編碼。若是留空,則使用操做系統默認的編碼。若是寫的是Base64的數據,則可使用Base64編碼。

readFile
讀取指定文件的內容,以文本返回。
readFile支持的參數有:

  • file:路徑,能夠是絕對路徑,也能夠是相對路徑。
  • encoding(可選):讀取文件時使用的編碼。
script {
    // "amVua2lucyBib29r" 是"jenkins book"進行Base64編碼後的值
    writeFile(file: "base64File", text: "amVua2lucyBib29r", encoding: "Base64")
    def content = readFile(file: "base64File", encoding: "UTF-8")
    echo "${content}"
    // 打印結果: jenkins book
}

2.5.2 製品相關步驟

stash
保存臨時文件。
stash步驟能夠將一些文件保存起來,以便被同一次構建的其餘步驟或階段使用。若是整個pipeline的全部階段在同一臺機器上執行,則stash步驟是多餘的。因此,一般須要stash的文件都是要跨Jenkins node使用的。

stash步驟會將文件存儲在tar文件中,對於大文件的stash操做將會消耗Jenkins master的計算資源。Jenkins官方文檔推薦,當文件大小爲5∼100MB時,應該考慮使用其餘替代方案。

stash步驟的參數列表以下:

  • name:字符串類型,保存文件的集合的惟一標識。
  • allowEmpty:布爾類型,容許stash內容爲空。
  • excludes:字符串類型,將哪些文件排除。若是排除多個文件,則使用逗號分隔。留空表明不排除任何文件。
  • includes:字符串類型,stash哪些文件,留空表明當前文件夾下的全部文件。
  • useDefaultExcludes:布爾類型,若是爲true,則表明使用Ant風格路徑默認排除文件列表。

除了name參數,其餘參數都是可選的。excludesincludes使用的是Ant風格路徑表達式。

unstash
取出以前stash的文件。
unstash步驟只有一個name參數,即stash時的惟一標識。一般stash與unstash步驟同時使用。如下是完整示例。

pipeline {
    agent none
    stages {
        stage('stash') {
            agent { label "master" }
            steps {
                script {
                    writeFile file: "a.txt", text: "$BUILD_NUMBER"
                    stash(name: "abc", include: "a.txt")
                }
            }
        }
        stage("unstash") {
            agent { label "node2" }
            steps {
                script {
                    unstash("abc")
                    def content = readFile("a.txt")
                    echo "${content}"
                }
            }
        }
    }
}

stash步驟在master節點上執行,而unstash步驟在node2節點上執行。

2.5.3 命令相關步驟

與命令相關的步驟實際上是Pipeline:Nodes and Processes插件提供的步驟。因爲它是Pipeline插件的一個組件,因此基本不須要單獨安裝。

sh
執行shell命令。
sh步驟支持的參數有:

  • script:將要執行的shell腳本,一般在類UNIX系統上能夠是多行腳本。
  • encoding:腳本執行後輸出日誌的編碼,默認值爲腳本運行所在系統的編碼。
  • returnStatus:布爾類型,默認腳本返回的是狀態碼,若是是一個非零的狀態碼,則會引起pipeline執行失敗。若是returnStatus參數爲true,則不論狀態碼是什麼,pipeline的執行都不會受影響。
  • returnStdout:布爾類型,若是爲true,則任務的標準輸出將做爲步驟的返回值,而不是打印到構建日誌中(若是有錯誤,則依然會打印到日誌中)。除了script參數,其餘參數都是可選的。

returnStatusreturnStdout參數通常不會同時使用,由於返回值只能有一個。若是同時使用,則只有returnStatus參數生效。

bat、powershell
bat步驟執行的是Windows的批處理命令。powershell步驟執行的是PowerShell腳本,支持3+版本。這兩個步驟支持的參數與sh步驟的同樣。

2.5.4 其餘步驟

error
主動報錯,停止當前pipeline。
error 步驟的執行相似於拋出一個異常。它只有一個必需參數:message。一般省略參數:error("there's an error")
tool
使用預約義的工具。
若是在Global Tool Configuration(全局工具配置)中配置了工具,那麼能夠經過tool步驟獲得工具路徑。
tool步驟支持的參數有:

  • name:工具名稱。
  • type(可選):工具類型,指該工具安裝類的全路徑類名。

每一個插件的type值都不同,並且絕大多數插件的文檔根本不寫type值。除了到該插件的源碼中查找,還有一種方法可讓咱們快速找到type值,就是前往Jenkins pipeline代碼片斷生成器中生成該tool步驟的代碼便可。

timeout
代碼塊超時時間。
爲timeout步驟閉包內運行的代碼設置超時時間限制。若是超時,將拋出一個org.jenkinsci.plugins.workflow.steps.FlowInterruptedException異常。timeout步驟支持以下參數:

  • time:整型,超時時間。
  • unit(可選):時間單位,支持的值有NANOSECONDSMICROSECONDSMILLISECONDSSECONDSMINUTES(默認)、HOURSDAYS
  • activity(可選):布爾類型,若是值爲true,則只有當日志沒有活動後,才真正算做超時。

waitUntil
等待條件知足。
不斷重複waitUntil塊內的代碼,直到條件爲truewaitUntil不負責處理塊內代碼的異常,遇到異常時直接向外拋出。waitUntil步驟最好與timeout步驟共同使用,避免死循環。示例以下:

timeout(50) {
    waitUntil {
        script {
            def r = sh script: 'curl http://example', returnStatus: true
            retturn (r == 0)
        }
    }
}

retry
重複執行塊
執行N 次閉包內的腳本。若是其中某次執行拋出異常,則只停止本次執行,並不會停止整個retry的執行。同時,在執行retry的過程當中,用戶是沒法停止pipeline的。

steps {
    retry(20) {
        script {
            sh script: 'curl http://example', returnStatus: true
        }
    }
}

sleep
讓pipeline休眠一段時間。
sleep步驟可用於簡單地暫停pipeline,其支持的參數有:

  • time:整型,休眠時間。
  • unit(可選):時間單位,支持的值有NANOSECONDSMICROSECONDSMILLISECONDSSECONDS(默認)、MINUTESHOURSDAYS

2.5.5 小貼士

  1. Jenkins提供了一個pipeline代碼片斷生成器,經過界面操做就能夠生成代碼。(只有pipeline項目有「Pipeline Syntax菜單」)
  2. VS Code擴展:Jenkins Pipeline Linter Connector,支持對Jenkinsfile的語法檢驗。
  3. 使用Workspace Cleanup插件清理空間。
  4. Ant風格路徑表達式。

Apache Ant樣式的路徑有三種通配符匹配方法,利用它們能夠組合出多種路徑模式:

Wildcard Description
? 匹配任意單字符
* 匹配0或者任意數量的字符,不包含/
** 匹配0或者更多數量的目錄,不包含/

Ant風格路徑匹配實例:

Path Description
/app/*.x 匹配(Matches)app路徑下全部.x文件
/app/p?ttern 匹配(Matches) /app/pattern/app/pXttern,可是不包括/app/pttern
/**/example 匹配項目根路徑下 /project/example, /project/foow/example, 和 /example
/app/**/dir/file. 匹配(Matches) /app/dir/file.jsp, /app/foo/dir/file.html,/app/foo/bar/dir/file.pdf, 和 /app/dir/file.java
/**/*.jsp 匹配項目根路徑下任何的.jsp 文件

須要注意的是,路徑匹配遵循最長匹配原則(has more characters),例如/app/dir/file.jsp符合/**/*.jsp/app/dir/*.jsp兩個路徑模式,那麼最終就是根據後者來匹配。

參考資料:
[1] 《Jenkins 2.x實戰指南》
[2] https://jenkins.io/zh/doc/book/pipeline/syntax/
[3] https://jenkins.io/zh/doc/pipeline/steps/

相關文章
相關標籤/搜索