天天看點

《Jenkins 2.x實踐指南》讀書筆記-Jenkins 2.x pipeline文法1. 大概了解Groovy2. pipeline介紹

[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/