大家好,我是藍胖子,相信大家平時專案中或多或少都有用到jenkins,它的piepeline模式能夠對專案的釋出流程進行編排,優化部署效率,減少錯誤的發生,如何去寫一個pipeline指令碼呢,今天我們就來簡單看看pipeline的語法。
先拿一個hello world的pipeline指令碼舉例,我們來看看pipeline指令碼的組成
pipeline {
agent any
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
}
指令碼都是以pipeline的關鍵字開頭,接著看下pipeline內部具體由哪幾部分組成。
agent 部分指明瞭pipeline指令碼在哪臺機器或者容器內執行,因為jenkins的工作模式是master-agent模式,master可以把流水線任務的執行放到其代理節點上執行。
同時jenkins的節點(master節點或者agent代理節點)可以打上標籤,如下表示的是pipeline指令碼需要在標籤為jdk8的節點上執行。
pipeline {
agent {
node {label:'jdk8'}
}
stages {
stage('Hello') {
steps {
echo 'Hello World'
}
}
}
}
agent模組也可以寫到stage裡,表示特定stage模組都在指定的agent節點上執行,如下所示,
pipeline {
agent any
stages {
stage('Hello') {
agent {
node {label:'jdk8'}
}
steps {
echo 'Hello World'
}
}
}
}
在文章開頭的hello world的指令碼中,agent我們指定了any,這表示可以在任意節點上執行pipeline指令碼。agent模組不可省略不寫。
接著來看下stages模組,stages模組由多個stage組成,一個stage表示一個階段,比如我們通常將釋出的整個流程分為編譯,傳輸,部署等幾個階段。
一個階段由多個步驟組成,在pipeline語法中,步驟通過steps模組表示,steps包含了一個或多個步驟,在上述hello world的pipeline指令碼中,echo 'Hello World' 就是一個步驟,比如我們想要執行shell命令就要執行sh步驟,如下所示,
pipeline {
agent any
stages {
stage('Hello') {
steps {
sh 'ping 127.0.0.1'
}
}
}
}
pipeline的步驟是可插拔的,可以通過安裝某些外掛來執行特定的步驟。
除了上述模組,還可以在stages或者steps模組後面定義post模組來表示整個pipeline執行完成或者單個stage完成後需要執行的動作。
如下所示,
pipeline {
agent any
stages {
stage('Build') {
steps {
sh 'echo Build stage ...'
}
post {
always {
echo "post condition executed: always ..."
}
}
}
}
post {
unstable {
echo "post condition executed: unstable ..."
}
failure {
echo "post condition executed: unsuccessful ..."
}
cleanup {
echo "post condition executed: cleanup ..."
}
}
}
post模組可以定義多個條件塊,條件塊裡寫上要執行的步驟,條件塊有以下幾種,
這裡再著重解釋下unstable 狀態,通常我們將測試失敗的狀態設定為unstable,可以把它理解成紀錄檔等級的warn狀態。如下我們可以主動設定stage和構建結果為unstable狀態。
pipeline {
agent any
stages {
stage('Test') {
steps {
warnError('watch it'){
sh '''
echo 'Running tests...'
exit 1
'''
}
}
}
stage('Hello2') {
steps {
echo 'hello'
}
}
}
post {
failure {
echo "failure"
}
success {
echo "success"
}
unstable {
echo "unstable"
}
}
}
最終產生的構建檢視如下:
pipeline除了上述的基本結構外,還提供了一些其他指令作為其基本結構的補充,
Jenkins pipeline支援的指令有:
在使用指令時,需要注意的是每個指令都有自己的「作用域」。如果指令使用的位置不正確,Jenkins將會報錯。
更多的設定案例請參考 流水線語法 (jenkins.io)
在pipeline 宣告式語法中,當需要執行程式碼塊條件判斷時除了使用when指令,還可以使用groovy語法的指令碼,指令碼還可以執行for迴圈的操作,設定程式碼如下,指令碼需要被script塊包括起來
寫script塊內的指令碼需要先簡單瞭解下groovy的語法
pipeline {
agent any
stages {
stage('Example') {
steps {
echo 'Hello World'
script {
def browsers = ['chrome', 'firefox']
for (int i = 0; i < browsers.size(); ++i) {
echo "Testing the ${browsers[i]} browser"
}
}
}
}
}
}
pipeline指令碼同樣可以定義函數,然後通過呼叫函數來執行一段邏輯,函數的定義遵循groovy的語法,如下,我定義了一個hello的函數,然後對其進行呼叫。
注意,函數定義是放到pipeline外面的。因為要接收函數返回值,所以整個函數呼叫是放到了script塊裡,groovy的語法中雙引號中可以用$變數名來參照特定的變數。
def hello(String name){
echo "$name"
return "Yes"
}
pipeline {
agent any
stages {
stage('Hello2') {
steps {
script {
def res = hello('Beatiful')
echo "$res"
}
}
}
}
}
雖然pipeline指令碼能夠定義函數提取重複邏輯,但是如果有100個pipeline指令碼都需要同一個函數,不可能定義100遍這樣的函數,所以jenkins提供了共用庫的機制,來讓我們方便去定義一個函數可以供多個pipeline指令碼使用。下面介紹下寫一個共用庫的基本步驟,
我們要寫的函數就定義在vars目錄下,在vars目錄中的檔名如果有多個單詞需遵循駝峰格式的命名,到時候參照函數的函數名和vars目錄下的檔名一致。
BoxJenkins
├── README.md
├── src
└── vars
├── hello.groovy
hello.groovy 的檔案內容如下,注意裡面的函數名call是固定的,不可變動。
def call(String name){
echo "$name"
}
在Jenkins的Manage Jenkins→Configure System→Global Pipeline Libraries中設定共用庫的git地址。
其中Name則是到時候我們要引入的庫名稱
引入共用庫的語法為 在pipeline塊外部使用@Library('lanpangzi-lib@master') _ ,以下是設定範例,其中@master 中的master代表庫的版本,可以由分支名,tag名,乃至commit id代替。
@Library('lanpangzi-lib@master') _
pipeline {
agent any
stages {
stage('Hello2') {
steps {
hello('wudi')
}
}
}
}
關於共用庫還有更多的用法,例如在共用庫中定義pipeline模板,以及使用共用庫中src的程式碼,這裡就不再展開了。
這一節,基本上對jenkins的pipeline指令碼語法做了比較完整的介紹,在以後再看pipeline指令碼時,可能還會接觸到許多外掛提供的函數或更多的指令,但是它們都逃不開pipeline指令碼的基本結構,掌握了基礎語法,後面才能更上一層樓。