3. Jenkins pipeline 語法
3.1 pipeline 組成
[作者:Surpassme]Jenkins pipeline 是基於Groovy
語言實現的一種DSL
(領域特定語言),用於描述整條流水線是如何進行的。流水線的主要內容包括源碼拉取
、構建
、打包
、部署
、測試
、生成報告
等步驟。
從源碼管理倉庫到生成測試報告這些過程中,可以根據需要分成若干階段,而每個階段僅處理一件事情,而每個階段也可以通過多個步驟來完成,因此我們可以基於這些階段和步驟些進行抽象,形成工程化的pipeline,因此一個基本的pipeline示例如下所示:
pipeline{
agent any
stages{
stage("Sample stage"){
steps {
echo "Hi,Surpass.Welcome visit my blog:https://www.cnblogs.com/surpassme/"
}
}
}
}
以上示例詳細解釋如下所示:
- pipeline:代表整條流水線,包含
整條流水線的邏輯
- agent:指定流水線的
運行位置
流水線的中每個階段都必須在某個地方(例如物理機、虛擬機或容器)運行,因此可能通過指定 agent部分來指定具體在哪裏運行。
- stages:流水線中多個stage的容器。該部分
至少包含一個stage
- stage:表示階段,代表流水線的階段,每個階段必須有名稱
- steps:表示階段中的一個或多個具體步驟的容器
1.steps
至少
包含一個步驟
2.在一個stage中僅有一個steps
以上每一個部分都是必需
的,否則Jenkins都會報錯
3.2 pipeline 支持的命令
[作者:Surpassme]基本的pipeline結構是無法滿足日常現實多變的需求。因此,Jenkins pipeline可以通過各種指令來擴展豐富自己。以下爲Jenkins pipeline支持的命令。
3.2.1 environment
[作者:Surpassme]environment
主要用於設置環境變量
。可以定義在stage
和pipeline
部分。環境變量可以分爲:Jenkins內置變量
和自定義環境變量
。
3.2.1.1 Jenkins 內置環境變量
[作者:Surpassme]在執行pipeline時,可以通過env
命令來獲取Jenkins的全部內置環境變量,其主要使用方法如下所示:
pipeline {
agent any
stages{
stage("PrintEnviroment"){
steps{
// method A
echo "Running ${env.BUILD_ID} on ${env.JENKINS_URL}"
// method B
echo "Running $env.BUILD_ID on $env.JENKINS_URL"
// method C
echo "Running ${BUILD_ID} on ${JENKINS_URL}"
}
}
}
}
默認情況下,env中的所有環境變量都可以直接在pipeline中使用。因此上面三種方法都可以使用,但
不推薦第三種方法
,因爲在出現變量名衝突時,排查問題非常難。
如果需要查看env所有可用的環境變量,可以通過以下方式進行訪問。http://jenkins-master-address/pipeline-syntax/globals
。示例如下所示:
Jenkins 內置環境變量如下所示:
以下爲日常經常使用到的內置環境變量簡介。如下所示:
- BRANCH_NAME
多分支piple 項目支持。可根據不同的分支執行不同的語句。例如當分支爲release時,部署到生產環境,分支爲test時,部署至測試環境。
- BUILD_NUMBER
構建號,同一個項目中,持續累加的數字。
- BUILD_URL
當前構建的URL地址,點擊該URL,可以快速跳轉至構建頁面
- WORKSPACE
構建的工作空間,爲絕對路徑
在調試pipeline時,也可以在pipeline 的開始階段使用以下代碼片斷,打印所有env的環境變量,來進行排查問題。如下所示:
sh "printenv"
3.2.1.2 自定義環境變量
[作者:Surpassme]當內置環境變量無法滿足要求時,我們也可以定義自己的環境變量。這個時候就需要使用environment
命令來自定義環境變量。示例如下所示:
pipeline {
agent any
environment{
NAME="Surpass"
AGE="28"
}
stages{
stage("PrintGolbalEnviroment"){
steps{
echo "Global Enviroment is name is ${env.NAME} age is ${env.AGE}"
}
}
stage("PrintLocalEnviroment"){
environment{
CITY="Shanghai"
FROM="Wuhan"
}
steps{
echo "Global Enviroment is name is ${env.NAME} age is ${env.AGE}"
echo "Local Enviroment is city is ${env.CITY} from is ${env.FROM}"
}
}
}
}
[作者:Surpassme]environment
可以在pipeline
中定義,屬於全局環境變量
,代表整個pipeline均可以使用該環境變量。也可以在stage
中定義,屬於局部環境變量
,僅限於該階段內部有效,外部無法使用。
除了以上幾中自定義環境變量,還可以通過script
來定義全局變量
,示例如下所示:
pipeline {
agent any
environment{
NAME="Surpass"
AGE="28"
}
stages{
stage("Set environment by script"){
steps{
script{
env.SURPASS_NAME="Surpass"
env.SURPASS_AGE=28
}
}
}
stage("PrintGolbalEnvironment"){
steps{
echo "Global Enviroment is name is ${env.NAME} age is ${env.AGE}"
}
}
stage("PrintLocalEnvironment"){
environment{
CITY="Shanghai"
FROM="Wuhan"
}
steps{
echo "Global Enviroment is name is ${env.NAME} age is ${env.AGE}"
echo "Local Enviroment is city is ${env.CITY} from is ${env.FROM}"
}
}
stage("PrintSetEnvironment"){
steps{
echo "print global env by script ${env.SURPASS_NAME}"
echo "print global env by script ${env.SURPASS_AGE}"
}
}
}
}
在自定義環境變量,需要注意的地方如下所示:
- 1.環境變量是不能跨pipeline進行訪問的,即
不同的pipeline間不能共享環境變量
- 2.如果用戶自定義的環境變量與env環境變量重名,則被重命名的環境將被
覆蓋
3.2.1.3 自定義全局環境變量
[作者:Surpassme]env中的環境變量都是內置的,用戶自定義的環境變量是與具體的pipeline相關的。如果需要定義全局並且跨pipeline
自定義環境變量,可以這樣設置。
Manage Jenkins->Configure System-> Global properties,勾選 Environment variables,添加對應的環境變量即可。
以上自定義的全局環境變量,會被加入env環境變量列表中,後續使用時可以使用${env.SURPASS_NAME}
和${env.SURPASS_AGE}
來獲取。
3.2.2 tools
[作者:Surpassme]可定義在pipeline或stage部分。在運行時,會自動下載
並安裝指定的工具和加入PATH變量
中。但在agent none時,會失效
基於在線自動安裝,受限於網絡不可達、網絡速度、網絡策略等因素,一般還是建議,還是提前下載到本地,然後在Jenkins進行配置好之後,在pipeline中直接使用即可。
3.2.2.1 Go 語言環境搭建
其操作步驟如下所示:
-
1.下載golang SDK本地
-
2.在Jenkins 中安裝go插件
-
3.在Jenkins中進行配置
Manage Jenkins->Configure System-> Global Tool Configuration->GO
- 4.編寫pipeline 腳本
pipeline{
agent any
tools {
go "go-1.19"
}
stages{
stage("tools demo"){
steps{
sh "go version"
sh "go env"
}
}
}
}
運行結果如下所示:
3.2.2.2 Python 語言環境搭建
[作者:Surpassme]Python 環境很容易產生版本衝突和第三方庫衝突等問題,因此Python通過會進行工程級別的環境隔離。在Jenkins中,我們可以使用插件Pyenv Pipeline Plugin
(https://plugins.jenkins.io/pyenv-pipeline/)來解決此類問題。其操作步驟如下所示:
- 1.在Jenkins中安裝Python/pip/virtualenv
- 2.安裝插件Pyenv Pipeline Plugin
- 3.編寫pipeline 腳本
pipeline{
agent any
stages{
stage("python virtual env demo"){
steps{
withPythonEnv("/usr/local/bin/python3") {
// Uses the specific python3.5 executable located in /usr/bin
sh "python3 --version"
sh "python3 -c \"print('hello,Surpass')\""
}
}
}
}
}
運行結果如下所示:
3.2.2.3 利用作用域實現多版本編譯
[作者:Surpassme]在實際項目中,同一份源碼可能會存在多個版本的編譯構建等。tools 除了支持pipeline域
也支持stage域
。示例如下所示:
pipeline{
agent any
stages{
stage("build with go 1.19"){
tools {
go "go-1.15"
}
steps{
echo "use go 1.15 build"
}
}
stage("build with go 1.19"){
tools {
go "go-1.19"
}
steps{
echo "use go 1.19 build"
}
}
}
}
3.2.3 input
[作者:Surpassme]input 命令可以實現pipeline中的交互操作
。利用input命令,我們可以一些簡單的場景。
- 實現簡易的審覈流程
在部署環境前,由相應負責人員進行確認
- 排查定位問題
因爲pipeline在遇到input命令時,會暫停執行。因此,我們可以利用這個特性,使運行某個階段前,暫停執行pipeline
3.2.3.1 常用參數
input 命令的常用參數如下所示:
- message
該參數爲必選參數
,input命令的消息提示框消息。
- id
該參數爲可選參數
, input命令標識符,默認爲stage的名稱
- submitter
該參數爲可選參數
,類型爲字符串類型
,可以進行操作的用戶ID或用戶組名稱,使用,
分隔,在,
左右不允許有空格
。可以用來做權限控制。
- submitterParameter
該參數爲可選參數
,類型爲字符串類型
,保存input命令的實際操作者的用戶名的變量名
- ok
該參數爲可選參數
,自定義確定按鈕的文本
- parameters
該參數爲可選參數
,提供參數列表供input命令使用。
3.2.3.2 簡易用法
比如我們現在實現第一種簡易的審覈流程。示例腳本如下所示:
pipeline{
agent any
stages{
stage("input simple use"){
steps{
input message:"Confirm or Cancle ?"
}
}
}
}
當執行到input simple use
階段時,pipeline會暫停,當鼠標移動到該階段虛線視圖上時,會出現一個浮層 ,以供選擇。示意圖如下所示:
3.2.3.3 複雜用法
示例腳本如下所示:
pipeline{
agent any
environment {
DEPLOY_ENV=""
}
stages{
stage("choose deploy nodes"){
steps{
script{
DEPLOY_ENV=input(
message: "準備部署到哪個節點?",
parameters:[choice(
name:'chooseNode',
choices:["node-1","node-2","node-3"],
description:"選擇部署節點")
],
ok:"確定",
submitter:"admin,Surpass",
submitterParameter:"approvers"
)
}
}
}
stage("deply"){
steps{
echo "操作人員:${DEPLOY_ENV['approvers']}"
echo "部署節點:${DEPLOY_ENV['chooseNode']}"
}
}
}
}
因爲input返回的值需要跨階段,因此需要將input的返回值定義爲全局變量。
input 命令返回值類型取決於返回的值個數
,詳情如下所示:
- 僅返回一個值,返回值類型就是這個值的類型
- 返回多個值,則返回值類型爲Map類型
運行結果如下所示:
3.2.4 options
[作者:Surpassme]用於配置pipeline本身
的選項,可以定義在pipeline
和stage
中。常用的配置項如下所示:
- buildDiscarder
[作者:Surpassme]用於配置保存最近歷史構建記錄的數量。示例如下所示:
options{
buildDiscarder(logRotator(numToKeepStr:'5'))
}
此選項只能在pipeline下的 options 中使用
- checkoutToSubdirectory
[作者:Surpassme]Jenkins 從版本控制庫中拉取源碼時,默認會存放到工作空間目錄中,此選項可以指定檢出到工作空間的子目錄中,示例如下所示:
options{
checkoutToSubdirectory('subdir')
}
- disableConcurrentBuilds
[作者:Surpassme]同一個pipeline,Jenkins默認是可以同時執行的,而此選項則是禁止多個pipeline並行執行
,示例如下所示:
options {
disableConcurrentBuilds()
}
- retry
[作者:Surpassme]當發生失敗時進行重試,可以指定整個pipeline的重試次數。示例如下所示:
options{
retry(3)
}
需要注意的是這裏的重試次數是指總次數,即包含第一次失敗。當使用retry選項時,options可以放在stage中
- timeout
[作者:Surpassme]若pipeline執行時間過長,超出了設置的超時時間之後,則Jenkins將中止pipeline。示例如下所示:
options{
timeout(time:1,unit:'SECONDS')
}
1.timeout時間單位有SECONDS、MINUTES、HOURS。
2.當使用timeout選項時,options可以放在stage塊中
- timestamps
[作者:Surpassme]爲控制檯輸出時間戳。示例如下所示:
options {
timestamps()
}
3.2.5 parallel
[作者:Surpassme]在pipeline中使用parallel
可以很方便的實現並行構建。
3.2.5.1 階段並行
示例如下所示:
pipeline{
agent any
stages{
stage("Non Parallel stage"){
steps{
echo "This is non-parallel stage"
}
}
stage("Parallel stage"){
failFast true
parallel{
stage("Parallel A"){
steps{
echo "Parallel A"
}
}
stage("Parallel B"){
steps{
echo "Parallel B"
}
}
stage("Parallel C"){
steps{
echo "Parallel C"
}
}
}
}
}
}
在使用parallel
時,注意事項如下所示:
- parallel
塊本身不允許
包含agent
和tools
- 默認情況下,pipeline要等parallel塊下所有的階段都運行完成,才能確定運行結果。若希望所有並行階段中某個階段失敗後,就即將中止所有階段,則需要在parallel同級位置加入
failFast true
failFast true 簡單來講就是表示,只要有一個並行階段運行失敗,則立即退出。
3.2.5.2 步驟並行
[作者:Surpassme]示例如下所示:
pipeline{
agent any
stages{
stage("Non-parallel steps"){
steps{
echo "Non-parallel steps"
}
}
stage("Parallel steps"){
steps{
parallel(
parallelA:{
echo "parallelA steps"
},
parallelB:{
echo "parallelB steps"
},
parallelC:{
echo "parallelC steps"
}
)
}
}
}
}
[作者:Surpassme]階段並行和步驟並行的主要區別如下所示:
- 寫法區別:在階段並行時,使用的是
大括號
,而步驟並行時,使用的是括號
- 運行區別:階段並行是運行在不同的executor,而步驟並行,則是運行在同一個executorr
原文地址:https://www.jianshu.com/p/f2895e38a824
本文同步在微信訂閱號上發佈,如各位小夥伴們喜歡我的文章,也可以關注我的微信訂閱號:woaitest,或掃描下面的二維碼添加關注: