[TOC]
可以通過Groovy教程來了解。
Jenkins pipeline其實就是基于Groovy語言實作的一種DSL(領域特定語言),用于描述整條流水線是如何進行的。流水線的内容包括執行編譯、打包、測試、輸出測試報告等步驟。
<code>pipeline</code>:代表整條流水線,包含整條流水線的邏輯。
<code>stage</code>部分:階段,代表流水線的階段。每個階段都必須有名稱。本例中,<code>build</code>就是此階段的名稱。
<code>stages</code>部分:流水線中多個<code>stage</code>的容器。<code>stages</code>部分至少包含一個<code>stage</code>。
<code>steps</code>部分:代表階段中的一個或多個具體步驟(<code>step</code>)的容器。<code>steps</code>部分至少包含一個步驟,本例中,<code>echo</code>就是一個步驟。在一個<code>stage</code>中有且隻有一個<code>steps</code>。
<code>agent</code>部分:指定流水線的執行位置(Jenkins agent)。流水線中的每個階段都必須在某個地方(實體機、虛拟機或Docker容器)執行,<code>agent</code>部分即指定具體在哪裡執行。
更多更詳細pipeline步驟參考文檔:
https://jenkins.io/zh/doc/pipeline/steps/
以上每一個部分(section)都是必需的,少一個,Jenkins都會報錯。
衆所周知,jenkins好用最大展現它的衆多插件滿足各種需求。并不是所有的插件都支援pipeline的。
jenkins插件相容pipeline清單:
https://github.com/jenkinsci/pipeline-plugin/blob/master/COMPATIBILITY.md
<code>post</code>部分包含的是在整個pipeline或階段完成後一些附加的步驟。<code>post</code>部分是可選的,是以并不包含在pipeline最簡結構中。但這并不代表它作用不大。
根據pipeline或階段的完成狀态,<code>post</code>部分分成多種條件塊,包括:
<code>always</code>:不論目前完成狀态是什麼,都執行。
<code>changed</code>:隻要目前完成狀态與上一次完成狀态不同就執行。
<code>fixed</code>:上一次完成狀态為失敗或不穩定(<code>unstable</code>),目前完成狀态為成功時執行。
<code>regression</code>:上一次完成狀态為成功,目前完成狀态為失敗、不穩定或中止(<code>aborted</code>)時執行。
<code>aborted</code>:目前執行結果是中止狀态時(一般為人為中止)執行。
<code>failure</code>:目前完成狀态為失敗時執行。
<code>success</code>:目前完成狀态為成功時執行。
<code>unstable</code>:目前完成狀态為不穩定時執行。
<code>cleanup</code>:清理條件塊。不論目前完成狀态是什麼,在其他所有條件塊執行完成後都執行。<code>post</code>部分可以同時包含多種條件塊。以下是<code>post</code>部分的完整示例。
顯然,基本結構滿足不了現實多變的需求。是以,Jenkins pipeline通過各種指令(directive)來豐富自己。指令可以被了解為對Jenkins pipeline基本結構的補充。
Jenkins pipeline支援的指令有:
<code>environment</code>:用于設定環境變量,可定義在<code>stage</code>或<code>pipeline</code>部分。
<code>tools</code>:可定義在<code>pipeline</code>或<code>stage</code>部分。它會自動下載下傳并安裝我們指定的工具,并将其加入<code>PATH</code>變量中。
<code>input</code>:定義在<code>stage</code>部分,會暫停<code>pipeline</code>,提示你輸入内容。
<code>options</code>:用于配置Jenkins pipeline本身的選項,比如<code>options {retry(3)}</code>指當<code>pipeline</code>失敗時再重試2次。<code>options</code>指令可定義在<code>stage</code>或<code>pipeline</code>部分。
<code>parallel</code>:并行執行多個<code>step</code>。在<code>pipeline</code>插件1.2版本後,<code>parallel</code>開始支援對多個階段進行并行執行。
<code>parameters</code>:與<code>input</code>不同,<code>parameters</code>是執行<code>pipeline</code>前傳入的一些參數。
<code>triggers</code>:用于定義執行<code>pipeline</code>的觸發器。
<code>when</code>:當滿足<code>when</code>定義的條件時,階段才執行。
在使用指令時,需要注意的是每個指令都有自己的“作用域”。如果指令使用的位置不正确,Jenkins将會報錯。
<code>options</code> 指令允許從流水線内部配置特定于流水線的選項。 流水線提供了許多這樣的選項, 比如 <code>buildDiscarder</code>,但也可以由插件提供, 比如 <code>timestamps</code>.
Required
No
Parameters
None
Allowed
Only once, inside the <code>pipeline</code> block.
buildDiscarder
為最近的流水線運作的特定數量儲存元件和控制台輸出。例如: <code>options { buildDiscarder(logRotator(numToKeepStr: '1')) }</code>
disableConcurrentBuilds
不允許同時執行流水線。 可被用來防止同時通路共享資源等。 例如: <code>options { disableConcurrentBuilds() }</code>
overrideIndexTriggers
允許覆寫分支索引觸發器的預設處理。 如果分支索引觸發器在多分支或組織标簽中禁用, <code>options { overrideIndexTriggers(true) }</code> 将隻允許它們用于促工作。否則, <code>options { overrideIndexTriggers(false) }</code> 隻會禁用改作業的分支索引觸發器。
skipDefaultCheckout
在<code>agent</code> 指令中,跳過從源代碼控制中檢出代碼的預設情況。例如: <code>options { skipDefaultCheckout() }</code>
skipStagesAfterUnstable
一旦建構狀态變得UNSTABLE,跳過該階段。例如: <code>options { skipStagesAfterUnstable() }</code>
checkoutToSubdirectory
在工作空間的子目錄中自動地執行源代碼控制檢出。例如: <code>options { checkoutToSubdirectory('foo') }</code>
timeout
設定流水線運作的逾時時間, 在此之後,Jenkins将中止流水線。例如: <code>options { timeout(time: 1, unit: 'HOURS') }</code>
retry
在失敗時, 重新嘗試整個流水線的指定次數。 例如: <code>options { retry(3) }</code>
timestamps
預謀所有由流水線生成的控制台輸出,與該流水線發出的時間一緻。 例如: <code>options { timestamps() }</code>
newContainerPerStage
當<code>agent</code>為<code>docker</code>或<code>dockerfile</code>時,指定在同一個Jenkins節點上,每個<code>stage</code>都分别運作在一個新的容器中,而不是所有<code>stage</code>都運作在同一個容器中。例如: <code>options { newContainerPerStage() }</code>
指定一個小時的全局執行逾時, 在此之後,Jenkins 将中止流水線運作。
<code>stage</code> 的 <code>options</code> 指令類似于流水線根目錄上的 <code>options</code> 指令。然而, <code>stage</code> -級别 <code>options</code> 隻能包括 <code>retry</code>, <code>timeout</code>, 或 <code>timestamps</code> 等步驟, 或與 <code>stage</code> 相關的聲明式選項,如 <code>skipDefaultCheckout</code>。
在<code>stage</code>, <code>options</code> 指令中的步驟在進入 <code>agent</code> 之前被調用或在 <code>when</code> 條件出現時進行檢查。
在 <code>agent</code> 指令中跳過預設的從源代碼控制中檢出代碼。例如: <code>options { skipDefaultCheckout() }</code>
設定此階段的逾時時間, 在此之後, Jenkins 會終止該階段。 例如: <code>options { timeout(time: 1, unit: 'HOURS') }</code>
在失敗時, 重試此階段指定次數。 例如: <code>options { retry(3) }</code>
預謀此階段生成的所有控制台輸出以及該行發出的時間一緻。例如: <code>options { timestamps() }</code>
指定 Example 階段的執行逾時時間, 在此之後,Jenkins 将中止流水線運作。
聲明式pipeline是不能直接在<code>steps</code>塊中寫Groovy代碼。
Jenkins pipeline專門提供了一個<code>script</code>步驟,你能在<code>script</code>步驟中像寫代碼一樣寫pipeline邏輯。
在script塊中的其實就是Groovy代碼。大多數時候,我們是不需要使用<code>script</code>步驟的。如果在<code>script</code>步驟中寫了大量的邏輯,則說明你應該把這些邏輯拆分到不同的階段,或者放到共享庫中。共享庫是一種擴充Jenkins pipeline的技術。
這裡介紹pipeline内置的一些步驟。
deleteDir
删除目前目錄,它是一個無參步驟,删除的是目前工作目錄。通常它與<code>dir</code>步驟一起使用,用于删除指定目錄下的内容。
dir
切換到目錄。預設pipeline工作在工作空間目錄下,<code>dir</code>步驟可以讓我們切換到其它目錄。例如:<code>dir("/var/logs") { deleteDir() }</code>
fileExists
判斷檔案是否存在。<code>fileExists('/tmp/a.jar')</code>判斷<code>/tmp/a.jar</code>檔案是否存在。如果參數是相對路徑,則判斷在相對目前工作目錄下,該檔案是否存在。結果傳回布爾類型。
isUnix
判斷是否為類Unix系統。如果目前pipeline運作在一個類Unix系統上,則傳回<code>true</code>。
pwd
确認目前目錄。<code>pwd</code>與Linux的<code>pwd</code>指令一樣,傳回目前所在目錄。它有一個布爾類型的可選參數:<code>tmp</code>,如果參數值為<code>true</code>,則傳回與目前工作空間關聯的臨時目錄。
writeFile
将内容寫入指定檔案中。
<code>writeFile</code>支援的參數有:
<code>file</code>:檔案路徑,可以是絕對路徑,也可以是相對路徑。
<code>text</code>:要寫入的檔案内容。
<code>encoding</code>(可選):目标檔案的編碼。如果留白,則使用作業系統預設的編碼。如果寫的是Base64的資料,則可以使用Base64編碼。
readFile
讀取指定檔案的内容,以文本傳回。
<code>readFile</code>支援的參數有:
<code>file</code>:路徑,可以是絕對路徑,也可以是相對路徑。
<code>encoding</code>(可選):讀取檔案時使用的編碼。
stash
儲存臨時檔案。
<code>stash</code>步驟可以将一些檔案儲存起來,以便被同一次建構的其他步驟或階段使用。如果整個pipeline的所有階段在同一台機器上執行,則<code>stash</code>步驟是多餘的。是以,通常需要<code>stash</code>的檔案都是要跨Jenkins node使用的。
<code>stash</code>步驟會将檔案存儲在<code>tar</code>檔案中,對于大檔案的<code>stash</code>操作将會消耗Jenkins master的計算資源。Jenkins官方文檔推薦,當檔案大小為5∼100MB時,應該考慮使用其他替代方案。
<code>stash</code>步驟的參數清單如下:
<code>name</code>:字元串類型,儲存檔案的集合的唯一辨別。
<code>allowEmpty</code>:布爾類型,允許<code>stash</code>内容為空。
<code>excludes</code>:字元串類型,将哪些檔案排除。如果排除多個檔案,則使用逗号分隔。留白代表不排除任何檔案。
<code>includes</code>:字元串類型,<code>stash</code>哪些檔案,留白代表目前檔案夾下的所有檔案。
<code>useDefaultExcludes</code>:布爾類型,如果為<code>true</code>,則代表使用Ant風格路徑預設排除檔案清單。
除了<code>name</code>參數,其他參數都是可選的。<code>excludes</code>和<code>includes</code>使用的是Ant風格路徑表達式。
unstash
取出之前stash的檔案。
<code>unstash</code>步驟隻有一個<code>name</code>參數,即<code>stash</code>時的唯一辨別。通常<code>stas</code>h與<code>unstash</code>步驟同時使用。以下是完整示例。
<code>stash</code>步驟在master節點上執行,而<code>unstash</code>步驟在node2節點上執行。
與指令相關的步驟其實是Pipeline:Nodes and Processes插件提供的步驟。由于它是Pipeline插件的一個元件,是以基本不需要單獨安裝。
sh
執行shell指令。
<code>sh</code>步驟支援的參數有:
<code>script</code>:将要執行的shell腳本,通常在類UNIX系統上可以是多行腳本。
<code>encoding</code>:腳本執行後輸出日志的編碼,預設值為腳本運作所在系統的編碼。
<code>returnStatus</code>:布爾類型,預設腳本傳回的是狀态碼,如果是一個非零的狀态碼,則會引發pipeline執行失敗。如果<code>returnStatus</code>參數為<code>true</code>,則不論狀态碼是什麼,pipeline的執行都不會受影響。
<code>returnStdout</code>:布爾類型,如果為<code>true</code>,則任務的标準輸出将作為步驟的傳回值,而不是列印到建構日志中(如果有錯誤,則依然會列印到日志中)。除了<code>script</code>參數,其他參數都是可選的。
<code>returnStatus</code>與<code>returnStdout</code>參數一般不會同時使用,因為傳回值隻能有一個。如果同時使用,則隻有returnStatus參數生效。
bat、powershell
<code>bat</code>步驟執行的是Windows的批處理指令。<code>powershell</code>步驟執行的是PowerShell腳本,支援3+版本。這兩個步驟支援的參數與sh步驟的一樣。
error
主動報錯,中止目前pipeline。
error 步驟的執行類似于抛出一個異常。它隻有一個必需參數:<code>message</code>。通常省略參數:<code>error("there's an error")</code>。
tool
使用預定義的工具。
如果在Global Tool Configuration(全局工具配置)中配置了工具,那麼可以通過<code>tool</code>步驟得到工具路徑。
<code>tool</code>步驟支援的參數有:
<code>name</code>:工具名稱。
<code>type</code>(可選):工具類型,指該工具安裝類的全路徑類名。
每個插件的<code>type</code>值都不一樣,而且絕大多數插件的文檔根本不寫<code>type</code>值。除了到該插件的源碼中查找,還有一種方法可以讓我們快速找到<code>type</code>值,就是前往Jenkins pipeline代碼片段生成器中生成該<code>tool</code>步驟的代碼即可。
代碼塊逾時時間。
為timeout步驟閉包内運作的代碼設定逾時時間限制。如果逾時,将抛出一個<code>org.jenkinsci.plugins.workflow.steps.FlowInterruptedException</code>異常。<code>timeout</code>步驟支援如下參數:
<code>time</code>:整型,逾時時間。
<code>unit</code>(可選):時間機關,支援的值有<code>NANOSECONDS</code>、<code>MICROSECONDS</code>、<code>MILLISECONDS</code>、<code>SECONDS</code>、<code>MINUTES</code>(預設)、<code>HOURS</code>、<code>DAYS</code>。
<code>activity</code>(可選):布爾類型,如果值為<code>true</code>,則隻有當日志沒有活動後,才真正算作逾時。
waitUntil
等待條件滿足。
不斷重複<code>waitUntil</code>塊内的代碼,直到條件為<code>true</code>。<code>waitUntil</code>不負責處理塊内代碼的異常,遇到異常時直接向外抛出。<code>waitUntil</code>步驟最好與<code>timeout</code>步驟共同使用,避免死循環。示例如下:
重複執行塊
執行N 次閉包内的腳本。如果其中某次執行抛出異常,則隻中止本次執行,并不會中止整個<code>retry</code>的執行。同時,在執行<code>retry</code>的過程中,使用者是無法中止pipeline的。
sleep
讓pipeline休眠一段時間。
<code>sleep</code>步驟可用于簡單地暫停pipeline,其支援的參數有:
<code>time</code>:整型,休眠時間。
<code>unit</code>(可選):時間機關,支援的值有<code>NANOSECONDS</code>、<code>MICROSECONDS</code>、<code>MILLISECONDS</code>、<code>SECONDS</code>(預設)、<code>MINUTES</code>、<code>HOURS</code>、<code>DAYS</code>。
Jenkins提供了一個pipeline代碼片段生成器,通過界面操作就可以生成代碼。(隻有pipeline項目有“Pipeline Syntax菜單”)
VS Code擴充:Jenkins Pipeline Linter Connector,支援對Jenkinsfile的文法檢驗。
使用Workspace Cleanup插件清理空間。
Ant風格路徑表達式。
Apache Ant樣式的路徑有三種通配符比對方法,利用它們可以組合出多種路徑模式:
Wildcard
Description
<code>?</code>
比對任意單字元
<code>*</code>
比對0或者任意數量的字元,不包含<code>/</code>
<code>**</code>
比對0或者更多數量的目錄,不包含<code>/</code>
Ant風格路徑比對執行個體:
Path
<code>/app/*.x</code>
比對(Matches)<code>app</code>路徑下所有<code>.x</code>檔案
<code>/app/p?ttern</code>
比對(Matches) <code>/app/pattern</code> 和 <code>/app/pXttern</code>,但是不包括<code>/app/pttern</code>
<code>/**/example</code>
比對項目根路徑下 <code>/project/example</code>, <code>/project/foow/example</code>, 和 <code>/example</code>
<code>/app/**/dir/file.</code>
比對(Matches) <code>/app/dir/file.jsp</code>, <code>/app/foo/dir/file.html</code>,<code>/app/foo/bar/dir/file.pdf</code>, 和 <code>/app/dir/file.java</code>
<code>/**/*.jsp</code>
比對項目根路徑下任何的<code>.jsp</code> 檔案
需要注意的是,路徑比對遵循最長比對原則(has more characters),例如<code>/app/dir/file.jsp</code>符合<code>/**/*.jsp</code>和<code>/app/dir/*.jsp</code>兩個路徑模式,那麼最終就是根據後者來比對。
參考資料:
[1] 《Jenkins 2.x實戰指南》
[2] https://jenkins.io/zh/doc/book/pipeline/syntax/
[3] https://jenkins.io/zh/doc/pipeline/steps/