一.簡介
步驟是pipeline里執行的最小單位了,這里列舉內置的相關步驟方便使用,省的去寫很多shell,也不方便維護。
二.文件相關
刪除當前目錄
無參步驟,刪除的是當前工作目錄。通常它與dir步驟一起使用,用於刪除指定目錄下的內容。
deleteDir
切換到目錄
默認pipeline工作在工作空間目錄下(/root/.jenkins/workspace/xx項目名),dir步驟可以讓我們切換到其他目錄。
dir('/xx') {
deleteDir
}
判斷文件是否存在
判斷/tmp/a.jar文件是否存在
fileExists('/tmp/a.jar')
輸出狀態
script {
def status=fileExists('/tmp/a.jar')
print "${status}"
}
判斷是否為類Unix
如果當前pipeline運行在一個類Unix系統上,則返回true
script {
def status=isUnix
print "${status}"
}
返回當前目錄
pwd與Linux的pwd命令一樣,返回當前所在目錄
script {
def dir=pwd
print "dir"
}
將內容寫入文件
writeFile支持的參數有:
- file:文件路徑,可以是絕對路徑,也可以是相對路徑。
- text:要寫入的文件內容。
- encoding(可選):目標文件的編碼。如果留空,則使用操作系統默認的編碼。如果寫的是Base64的數據,則可以使用Base64編碼。
writeFile(file: "/etc/pass", text: "xxxx", encoding: "UTF-8")
讀取文件內容
readFile支持的參數有:
- file:路徑,可以是絕對路徑,也可以是相對路徑。
- encoding(可選):讀取文件時使用的編碼。
當前例子,用writeFile寫入內容,再用readFile讀取內容到變量,最終打印變量
fileContents = readFile(file: "/etc/passwd", encoding: "UTF-8")
echo "$fileContents"
二.制品相關
存取臨時文件
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參數,其他參數都是可選的。excludes和includes使用的是Ant風格路徑表達式。
unstash步驟取出之前stash的文件。只有一個name參數,即stash時的唯一標識。通常stash與unstash步驟同時使用。
stash步驟在master節點上執行,而unstash步驟在node2節點上執行。
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}"
}
}
}
}
}
三.命令相關
script
直接執行groovy的命令會報錯,需要用script括起來。與命令相關的步驟其實是Pipeline:Nodes and Processes插件提供的步驟。由於它是Pipeline插件的一個組件,所以基本不需要單獨安裝。
script {
def browsers = ['chrome', 'firefox']
for (int i = 0; i < brosers.size(); ++i) {
echo "this is ${browsers[i]}"
}
}
sh
執行shell命令
sh步驟支持的參數有:
- script:將要執行的shell腳本,通常在類UNIX系統上可以是多行腳本。
- encoding:腳本執行后輸出日志的編碼,默認值為腳本運行所在系統的編碼。
- returnStatus:布爾類型,默認腳本返回的是狀態碼,如果是一個非零的狀態碼,則會引發pipeline執行失敗。如果returnStatus參數為true,則不論狀態碼是什么,pipeline的執行都不會受影響。
- returnStdout:布爾類型,如果為true,則任務的標准輸出將作為步驟的返回值,而不是打印到構建日志中(如果有錯誤,則依然會打印到日志中)。除了script參數,其他參數都是可選的。
- returnStatus與returnStdout參數一般不會同時使用,因為返回值只能有一個。如果同時使用,則只有returnStatus參數生效。
sh "ls"
sh(script: "/root/test.sh", returnStdout: true)
bat、powershell
bat步驟執行的是Windows的批處理命令。powershell步驟執行的是PowerShell腳本,支持3+版本。這兩個步驟支持的參數與sh步驟的一樣。
四.調用其它pipeline
在Jenkins pipeline中可以使用build步驟實現調用另一個pipeline功能。build步驟是pipeline插件的一個組件,所以不需要另外安裝插件,可以直接使用。
build步驟其實也是一種觸發pipeline執行的方式,它與triggers指令中的upstream方式有兩個區別:
1.build步驟是由上游pipeline使用的,而upstream方式是由下游pipeline使用的。
2.build步驟是可以帶參數的,而upstream方式只是被動觸發,並沒有帶參數。
調用本章開頭的例子,可以steps部分這么寫:
steps {
build(
job:"parameters-example",
parameters: [
booleanParam(name:'userFlag', value:true)
]
)
}
build步驟的基本2個參數
job(必填):目標Jenkins任務的名稱
parameters(可選):數組類型,傳入目標pipeline的參數列表。傳參方法與定參方法類似
parameters: [
booleanParam(name:'DEBUG_BUILD', value:true),
password(name:'PASSWORD', value:'prodSECRET'),
string(name:'DEPLOY_ENV', value:'prod'),
text(name:'DEPLOY_TEXT', value:'a\n\b\nc\n'),
string(name:'CHOICES00', value:'dev')
]
我們注意到choice類型的參數沒有對應的傳參方法,而是使用string傳參方法代替的。
除此之外,build步驟還支持其他三個參數
propagate(可選): 布爾類型,如果值為true,則只有當下游pipeline的最終結構狀態為SUCCESS時,上游pipeline才算成功;如果值為flase,則不論下游pipeline的最終構建狀態是什么,上游pipeline都忽略。默認值為true
quietPeriod(可選): 整形,觸發下游pipeline后,下游pipeline等待多久執行。如果不設置此參數,則等待時長由下游pipeline確定,單位為秒。
wait(可選): 布爾類型,是否等待下游pipeline執行完成。默認值為true。
如果你使用了Folder插件,那么就需要注意build步驟的job參數的寫法了。
使用Folder插件,可以讓我們像管理文件夾下的文件一樣來管理Jenkins項目。我們的Jenkins項目可以創建在這些文件夾下。如果目標pipeline與源pipeline在同一目錄下,則可以直接使用名稱; 如果不在同一目錄下,則需要指定相對路徑,如 ../sister-folder/downstream 或絕對路徑。
五.處理復雜判斷邏輯
有些場景要求我們根據傳入的參數做一些邏輯判斷。很自然的,就想到在script函數內實現
stage("deploy to test"){
steps{
script {
if (params.CHOICES == 'test') {
echo "deploy to test"
}
}
}
}
這樣寫起來很不優雅,Conditional BuildStep插件可以讓我們像使用when指令一樣進行條件判斷。一下代碼是安裝后的寫法
pipeline {
agent any
parameters {
choice(name:'CHOICES', choices:'dev\ntest\nstaging', description:'請選擇部署的環境')
}
stages {
stage("deploy test") {
when {
expression {return params.CHOICES == 'test'}
}
steps {
echo "deploy to test"
}
}
stage("deploy staging") {
when {
expression {return params.CHOICES == 'staging'}
}
steps {
echo "deploy to staging"
}
}
}
}
現實中,我們會面對更復雜的判斷條件。而expression表達式本質上就是一個Groovy代碼礦,大大提高了表達式的靈活性。
或邏輯
when {
// A or B
expression {return A || B}
}
與邏輯
when {
// A or B
expression {return A && B}
}
從文件中取值
when {
expression {return readFile('pom.xml').contains('mycomponent')}
}
正則表達式
when {
expression {return token ==~ /(?i)(Y|YES|T|TRUE|ON|RUN)/}
}
六.其他步驟
error
主動報錯,中止當前pipeline。error 步驟的執行類似於拋出一個異常。它只有一個必需參數:message。
error("there's an error")
tool
使用預定義的工具。
如果在Global Tool Configuration(全局工具配置)中配置了工具,那么可以通過tool步驟得到工具路徑。
steps {
script{
def t = tool name: 'docker', type: 'org.jenkinsci.plugins.docker.commons.tiils.ockerTool'
echo "${t}" //打印 /var/lib/docker
}
}
tool步驟支持的參數有:
- name:工具名稱。
- type(可選):工具類型,指該工具安裝類的全路徑類名。
每個插件的type值都不一樣,而且絕大多數插件的文檔根本不寫type值。除了到該插件的源碼中查找,還有一種方法可以讓我們快速找到type值,就是前往Jenkins pipeline代碼片段生成器中生成該tool步驟的代碼即可。
timeout
代碼塊超時時間。為timeout步驟閉包內運行的代碼設置超時時間限制。如果超時,將拋出一個org.jenkinsci.plugins.workflow.steps.FlowInterruptedException異常。
timeout(5)
timeout步驟支持如下參數:
- time:整型,超時時間。
- unit(可選):時間單位,支持的值有NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS、MINUTES(默認)、HOURS、DAYS。
- activity(可選):布爾類型,如果值為true,則只有當日志沒有活動后,才真正算作超時。
waitUntil
等待條件滿足。
不斷重復waitUntil塊內的代碼,直到條件為true。waitUntil不負責處理塊內代碼的異常,遇到異常時直接向外拋出。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
sleep步驟可用於簡單地暫停pipeline
其支持的參數有:
- time:整型,休眠時間。
- unit(可選):時間單位,支持的值有NANOSECONDS、MICROSECONDS、MILLISECONDS、SECONDS(默認)、MINUTES、HOURS、DAYS。
sleep(120) //120秒
sleep(time:'2', unit:"MINUTES") //2分鍾
自動清理空間
通常,當pipeline執行完成后,並不會自動清理空間。如果需要(通常需要)清理工作空間,則可以通過Workspace Cleanup插件實現。
注意:需要ws-cleanup插件
在post部分加入插件步驟
post {
always {
cleanWs()
}
}
七.ANT風格表達式
Ant是比Maven更老的Java構建工具。Ant發明了一種描述文件路徑的表達式,大家都習慣稱其為Ant風格路徑表達式。Jenkins pipeline的很多步驟的參數也會使用此變道時。
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兩個路徑模式,那么最終就是根據后者來匹配。