Jenkins實踐指南-05-Jenkins pipeline 語法01

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都會報錯

官方參考文檔:https://www.jenkins.io/doc/pipeline/steps/

3.2 pipeline 支持的命令

    [作者:Surpassme]基本的pipeline結構是無法滿足日常現實多變的需求。因此,Jenkins pipeline可以通過各種指令來擴展豐富自己。以下爲Jenkins pipeline支持的命令。

3.2.1 environment

    [作者:Surpassme]environment主要用於設置環境變量。可以定義在stagepipeline部分。環境變量可以分爲: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。示例如下所示:

http://192.168.188.133:9090/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本身的選項,可以定義在pipelinestage中。常用的配置項如下所示:

  • 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時間單位有SECONDSMINUTESHOURS
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 塊本身不允許包含agenttools
  • 默認情況下,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,或掃描下面的二維碼添加關注:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章