背景
單純的聲明或者腳本式的流水線語法,能力非常有限,只能搭建起整體運行框架。具體每個step的實現(xiàn)細(xì)節(jié),多是使用腳本進(jìn)行的。
鑒于groovy 與 pipeline語法的不穩(wěn)定性,我的原則是,python/shell 腳本能解決的,不在pipeline中用groovy多做邏輯
如何在pipeline 更好的使用腳本,這里寫了幾個實踐。
groovy腳本使用
這里給一個普通的完整聲明式流水線的demo,執(zhí)行腳本,我們可以直接在steps中執(zhí)行g(shù)roovy腳本,也可以用script關(guān)鍵字,形成整體的groovy腳本代碼塊兒,以便于整體運用,抽象復(fù)用等。
這里要注意的是,使用groovy,有一些細(xì)節(jié)語法問題。
官方groovy語法請參考,使用時閱讀,可避免不必要的問題
http://docs.groovy-lang.org/latest/html/documentation/core-operators.html#_conditional_operators
pipeline {
agent any
stages {
stage('Example') {
steps {
// groovy 腳本
sh 'echo hello'
echo 'Hello World'
script {
// groovy 腳本
def browsers = ['chrome', 'firefox']
for (int i = 0; i < browsers.size(); ++i) {
echo "Testing the ${browsers[i]} browser"
}
}
}
}
}
}
在groovy腳本中使用shell
shell腳本是依托在steps中的groovy腳本而被調(diào)用。
無輸出shell腳本運行
在pipeline中,我們通常用 sh 來執(zhí)行shell,具體語法見 https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script
無輸出的shell 語法如下
// 單引號需要拼接 容易出錯 不推薦使用
sh 'mkdir -p ' + VARIABLE
// 三引號支持變量等內(nèi)容,引號嵌套等 推薦使用
sh """cp ${VARIABLE}/ 'abc' "123" ${VARIABLE_1}/${VARIABLE_2}"""
有輸出的shell腳本
獲取執(zhí)行狀態(tài)
// 執(zhí)行腳本,并獲取腳本的exit狀態(tài),針對不同狀態(tài),做邏輯
def run_status = sh (
script: """cd ${ROOT_BIN_PATH} && \
./run.sh ${env.var1} '${str_param_1}' """,
returnStatus:true
)
print run_status
// 失敗強制退出
if (run_status != 0) {
print '腳本執(zhí)行失敗,強制退出'
sh 'exit 1'
}
獲取標(biāo)準(zhǔn)輸出
// 這里以判斷空文件舉例,獲取行數(shù)
def is_empty_file = sh (
script: """cat ${PROJECT_ROOT_PATH}/${record_filename}.txt | wc -l""",
returnStdout: true
).trim()
print 'is_empty_file: ' + is_empty_file
if ( is_empty_file == '0') {
print '此次錄制生成數(shù)據(jù)文件為空文件,不能上傳生成或者更新case!可在reporter 里面查看原先的請求數(shù)據(jù)文件。'
sh 'exit 1'
}
使用python 腳本
從遠(yuǎn)端git拉取并執(zhí)行python腳本
如果我們把腳本維護(hù)在常用倉庫里面,這樣可以作為依賴包用于pipeline中,這要比維護(hù)在機器上有兩個特點
- 遷移性更好
- 維護(hù),調(diào)試都更方便,支持參數(shù)式指定腳本分支,更靈活
script {
// 對照版本的分支,如果傳入的是master 默認(rèn)替換成最新上線的commit
if (express) {
dir ('./script') {
// 利用git 獲取python工具腳本
git branch: 'master', credentialsId: 'your_git_credential', url: 'git@repository.git'
script {
env.result = sh(script: """echo `python ./path/act.py ${param}` | awk '{print \$NF}' """, returnStdout: true, returnStatus: false).trim()
print '結(jié)果: ' + env.result
}
}
}
}
groovy解析json,更豐富的與python腳本交互
如果python腳本產(chǎn)生的數(shù)據(jù)比較復(fù)雜,這里建議在python腳本中序列化成json,保存在文件中,后者這機print到標(biāo)準(zhǔn)輸出,以供groovy使用
這里給下解析的串聯(lián)
python文本 舉例
#!/usr/bin/python
import json
a = {}
a['name'] = 'John Doe'
# 方式1 輸出到標(biāo)準(zhǔn)輸出
print(json.dumps(a))
# 方式2 輸出到文件
format_json_str = json.dumps(a, default=lambda o: o.__dict__, indent=2).decode('unicode-escape')
with open(./python_result.json, 'a+') as f:
f.write(format_json_str)
groovy文本
// 引用在文件最上面,不放在script中
import groovy.json.JsonSlurper
def json_output = sh(script: """python ./act.py""", returnStdout: true).trim()
def result_json = new JsonSlurper()
// 方法1
def result_map = jsonSlurper.parseText(json_output)
// 方法2
def result_map = readJSON file:'./python_result.json'
print result_map.name