Jenkins之聲明式流水線語法

1 流水線

1.1 簡(jiǎn)介

jenkins 有 2 種流水線分為聲明式流水線腳本化流水線校焦,腳本化流水線是 jenkins舊版本使用的流水線腳本劈榨,新版本 Jenkins(2.5之后引入) 推薦使用聲明式流水線啥酱。

jenkins流水線語法和gradle語法很類似挡爵,都是基于了groovy的閉包語法

1.2 聲明式流水線簡(jiǎn)介

在聲明式流水線語法中姆泻,流水線過程定義在Pipeline{}中,Pipeline塊定義了整個(gè)流水線中完成的所有工作

參數(shù)說明:

  • agent any:在任何可用的代理上執(zhí)行流水線或它的任何階段硼补,也就是執(zhí)行流水線過程的位置驮肉,也可以指定到具體的節(jié)點(diǎn)
  • stage:定義流水線的執(zhí)行過程(相當(dāng)于一個(gè)階段),比如下文所示的 Build已骇、Test离钝、Deploy票编, 但是這個(gè)名字是根據(jù)實(shí)際情況進(jìn)行定義的,并非固定的名字
  • steps:執(zhí)行某階段具體的步驟

示例:

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
    stages {
      stage('Build') {
        steps {
          echo 'Build'
        }
      }
      stage('Test') {
        steps {
          echo 'Test'
        }
      }
      stage('Deploy') {
        steps {
          echo 'Deploy'
      }
    }
  }
}

上面示例中pipeline是一個(gè)閉包卵渴,里面的也是閉包慧域,比如:stage('TEST'){...},就是閉包傳參語法浪读,在groovy中吊趾,如果方法中最后一個(gè)參數(shù)是閉包,那么閉包可以放在小括號(hào)的外面

1.3 腳本化流水線簡(jiǎn)介

在腳本化流水線語法中瑟啃,會(huì)有一個(gè)或多個(gè) Node(節(jié)點(diǎn))塊在整個(gè)流水線中執(zhí)行核心工作

參數(shù)說明:

  • node:在任何可用的代理上執(zhí)行流水線或它的任何階段,也可以指定到具體的節(jié)點(diǎn)
  • stage:和聲明式的含義一致揩尸,定義流水線的階段蛹屿。Stage 塊在腳本化流水線語法中是可選的,然而在腳本化流水線中實(shí)現(xiàn)stage 塊岩榆,可以清楚地在 Jenkins UI 界面中顯示每個(gè) stage 的任務(wù)子集错负。

示例:

//Jenkinsfile (Scripted Pipeline)
node {
  stage('Build') {
    echo 'Build'
  }
  stage('Test') {
    echo 'Test'
  }
  stage('Deploy') {
    echo 'Deploy'
  }
}

上面示例中node是一個(gè)閉包,里面的stage也是閉包勇边,比如:stage('TEST'){...}犹撒,就是閉包傳參語法,在groovy中粒褒,如果方法中最后一個(gè)參數(shù)是閉包识颊,那么閉包可以放在小括號(hào)的外面

2 聲明式流水線

2.1 規(guī)范

聲明式流水線必須包含在一個(gè) Pipeline 塊中,比如是一個(gè) Pipeline 塊的格式

pipeline {
  /* insert Declarative Pipeline here */
}

在聲明式流水線中有效的基本語句和表達(dá)式遵循與Groovy的語法同樣的規(guī)則奕坟,但有以下例外:

  • 流水線頂層必須是一個(gè) block祥款,即 pipeline{}
  • 分隔符可以不需要分號(hào),但是每條語句都必須在自己的行上
  • 塊只能由 Sections月杉、Directives刃跛、Steps 或 assignment statements 組成
  • 屬性引用語句被當(dāng)做是無參數(shù)的方法調(diào)用,比如 input 會(huì)被當(dāng)做 input()苛萎。

2.2 Sections

聲明式流水線中的 Sections 不是一個(gè)關(guān)鍵字或指令桨昙,而是包含一個(gè)或多個(gè) Agent、Stages腌歉、 post蛙酪、Directives 和 Steps 的代碼區(qū)域塊。

2.2.1 Agent

Agent表示整個(gè)流水線或特定階段中的步驟和命令執(zhí)行的位置究履,該部分必須在 pipeline 塊的頂層被定義滤否,也可以在 stage 中再次定義,但是 stage 級(jí)別是可選的

2.2.1.1 any

在任何可用的代理上執(zhí)行流水線最仑,配置語法

pipeline {
  agent any
}

2.2.1.2 none

表示該 Pipeline 腳本沒有全局的 agent 配置藐俺。當(dāng)頂層的 agent 配置為 none時(shí)炊甲, 每個(gè) stage 部分都需要包含它自己的 agent。配置語法

pipeline {
  agent none
  stages {
    stage('Stage For Build'){
      agent any
    }
  }
}

2.2.1.3 label

以節(jié)點(diǎn)標(biāo)簽形式選擇某個(gè)具體的節(jié)點(diǎn)執(zhí)行 Pipeline 命令欲芹,例如:agent { label 'my-defined-label' }卿啡。節(jié)點(diǎn)需要提前配置標(biāo)簽。

pipeline {
  agent none
    stages {
      stage('Stage For Build'){
        agent { label 'role-master' }
        steps {
          echo "role-master"
        }
      }
    }
}

2.2.1.4 node

label 配置類似菱父,只不過是可以添加一些額外的配置颈娜,比如customWorkspace(設(shè)置默認(rèn)工作目錄)

pipeline {
  agent none
    stages {
      stage('Stage For Build'){
        agent {
          node {
            label 'role-master'
            customWorkspace "/tmp/zhangzhuo/data"
          }
        }
        steps {
          sh "echo role-master > 1.txt"
        }
      }
    }
}

2.2.1.5 dockerfile

使用從源碼中包含的 Dockerfile 所構(gòu)建的容器執(zhí)行流水線或 stage。此時(shí)對(duì)應(yīng)的 agent寫法如下

agent {
   dockerfile {
     filename 'Dockerfile.build'  //dockerfile文件名稱
     dir 'build'                  //執(zhí)行構(gòu)建鏡像的工作目錄
     label 'role-master'          //執(zhí)行的node節(jié)點(diǎn)浙宜,標(biāo)簽選擇
     additionalBuildArgs '--build-arg version=1.0.2' //構(gòu)建參數(shù)
   }
}

2.2.1.6 docker

相當(dāng)于 dockerfile官辽,可以直接使用 docker 字段指定外部鏡像即可,可以省去構(gòu)建的時(shí)間粟瞬。比如使用 maven 鏡像進(jìn)行打包同仆,同時(shí)可以指定 args

agent{
  docker{
    image '192.168.10.15/kubernetes/alpine:latest'   //鏡像地址
    label 'role-master' //執(zhí)行的節(jié)點(diǎn),標(biāo)簽選擇
    args '-v /tmp:/tmp'      //啟動(dòng)鏡像的參數(shù)
  }
}

2.2.1.7 kubernetes

需要部署 kubernetes 相關(guān)的插件裙品,官方文檔https://github.com/jenkinsci/kubernetes-plugin/
Jenkins 也支持使用 Kubernetes 創(chuàng)建 Slave俗批,也就是常說的動(dòng)態(tài) Slave。配置示例如下

  • cloud: Configure Clouds 的名稱市怎,指定到其中一個(gè) k8s
  • slaveConnectTimeout: 連接超時(shí)時(shí)間
  • yaml: pod 定義文件岁忘,jnlp 容器的配置必須有配置無需改變,其余 containerd 根據(jù)自己情況指定
  • workspaceVolume:持久化 jenkins 的工作目錄区匠。
  • persistentVolumeClaimWorkspaceVolume:掛載已有 pvc干像。
    workspaceVolume persistentVolumeClaimWorkspaceVolume(claimName: "jenkins-agent", mountPath: "/", readOnly: "false")
  • nfsWorkspaceVolume:掛載 nfs 服務(wù)器目錄
    workspaceVolume nfsWorkspaceVolume(serverAddress: "192.168.10.254", serverPath: "/nfs", readOnly: "false")
  • dynamicPVC:動(dòng)態(tài)申請(qǐng) pvc,任務(wù)執(zhí)行結(jié)束后刪除
    workspaceVolume dynamicPVC(storageClassName: "nfs-client", requestsSize: "1Gi", accessModes: "ReadWriteMany")
  • emptyDirWorkspaceVolume:臨時(shí)目錄辱志,任務(wù)執(zhí)行結(jié)束后會(huì)隨著 pod 刪除被刪除蝠筑,主要功能多個(gè)任務(wù) container 共享 jenkins 工作目錄。
    workspaceVolume emptyDirWorkspaceVolume()
  • hostPathWorkspaceVolume:掛載 node 節(jié)點(diǎn)本機(jī)目錄揩懒,注意掛載本機(jī)目錄注意權(quán)限問題什乙,可以先創(chuàng)建設(shè)置 777 權(quán)限,否則默認(rèn) kubelet 創(chuàng)建的目錄權(quán)限為 755 默認(rèn)其他用戶沒有寫權(quán)限已球,執(zhí)行流水線會(huì)報(bào)錯(cuò)臣镣。
    workspaceVolume hostPathWorkspaceVolume(hostPath: "/opt/workspace", readOnly: false)
agent {
  kubernetes {
      cloud 'kubernetes'
      slaveConnectTimeout 1200
      workspaceVolume emptyDirWorkspaceVolume()
      yaml '''
kind: Pod
metadata:
  name: jenkins-agent
spec:
  containers:
  - args: [\'$(JENKINS_SECRET)\', \'$(JENKINS_NAME)\']
    image: '192.168.10.15/kubernetes/jnlp:alpine'
    name: jnlp
    imagePullPolicy: IfNotPresent
  - command:
      - "cat"
    image: "192.168.10.15/kubernetes/alpine:latest"
    imagePullPolicy: "IfNotPresent"
    name: "date"
    tty: true
  restartPolicy: Never
'''
  }
}

2.2.2 agent 的配置示例

2.2.2.1 kubernetes 示例

pipeline {
  agent {
    kubernetes {
      cloud 'kubernetes'
      slaveConnectTimeout 1200
      workspaceVolume emptyDirWorkspaceVolume()
      yaml '''
kind: Pod
metadata:
  name: jenkins-agent
spec:
  containers:
  - args: [\'$(JENKINS_SECRET)\', \'$(JENKINS_NAME)\']
    image: '192.168.10.15/kubernetes/jnlp:alpine'
    name: jnlp
    imagePullPolicy: IfNotPresent
  - command:
      - "cat"
    image: "192.168.10.15/kubernetes/alpine:latest"
    imagePullPolicy: "IfNotPresent"
    name: "date"
    tty: true
  - command:
      - "cat"
    image: "192.168.10.15/kubernetes/kubectl:apline"
    imagePullPolicy: "IfNotPresent"
    name: "kubectl"
    tty: true
  restartPolicy: Never
'''
    }
  }
  environment {
    MY_KUBECONFIG = credentials('kubernetes-cluster')
  }
  stages {
    stage('Data') {
      steps {
        container(name: 'date') {
          sh """
            date
          """
        }
      }
    }
    stage('echo') {
      steps {
        container(name: 'date') {
          sh """
            echo 'k8s is pod'
          """
        }
      }
    }
    stage('kubectl') {
      steps {
        container(name: 'kubectl') {
          sh """
            kubectl get pod -A  --kubeconfig $MY_KUBECONFIG
          """
        }
      }
    }
  }
}

2.2.2.2 docker 的示例

pipeline {
  agent none
  stages {
    stage('Example Build') {
      agent { docker 'maven:3-alpine' }
      steps {
        echo 'Hello, Maven'
        sh 'mvn --version'
      }
    }
    stage('Example Test') {
      agent { docker 'openjdk:8-jre' }
      steps {
        echo 'Hello, JDK'
        sh 'java -version'
      }
    }
  }
}

2.2.3 Post

Post 一般用于流水線結(jié)束后的進(jìn)一步處理,比如錯(cuò)誤通知等智亮。Post 可以針對(duì)流水線不同的結(jié)果做出不同的處理忆某,就像開發(fā)程序的錯(cuò)誤處理,比如 Python 語言的 try catch

Post 可以定義在 Pipelinestage 中阔蛉,目前支持以下條件:

  • always:無論 Pipeline 或 stage 的完成狀態(tài)如何弃舒,都允許運(yùn)行該 post 中定義的指令;
  • changed:只有當(dāng)前 Pipeline 或 stage 的完成狀態(tài)與它之前的運(yùn)行不同時(shí),才允許在該 post 部分運(yùn)行該步驟聋呢;
  • fixed:當(dāng)本次 Pipelinestage 成功苗踪,且上一次構(gòu)建是失敗或不穩(wěn)定時(shí),允許運(yùn)行該 post 中定義的指令削锰;
  • regression:當(dāng)本次 Pipeline 或 stage 的狀態(tài)為失敗通铲、不穩(wěn)定或終止,且上一次構(gòu)建的 狀態(tài)為成功時(shí)器贩,允許運(yùn)行該 post 中定義的指令颅夺;
  • failure:只有當(dāng)前 Pipeline 或 stage 的完成狀態(tài)為失敗(failure)蛹稍,才允許在 post 部分運(yùn)行該步驟吧黄,通常這時(shí)在 Web 界面中顯示為紅色
  • success:當(dāng)前狀態(tài)為成功(success),執(zhí)行 post 步驟唆姐,通常在 Web 界面中顯示為藍(lán)色 或綠色
  • unstable:當(dāng)前狀態(tài)為不穩(wěn)定(unstable)稚字,執(zhí)行 post 步驟,通常由于測(cè)試失敗或代碼 違規(guī)等造成厦酬,在 Web 界面中顯示為黃色
  • aborted:當(dāng)前狀態(tài)為終止(aborted),執(zhí)行該 post 步驟瘫想,通常由于流水線被手動(dòng)終止觸發(fā)仗阅,這時(shí)在 Web 界面中顯示為灰色;
  • unsuccessful:當(dāng)前狀態(tài)不是 success 時(shí)国夜,執(zhí)行該 post 步驟减噪;
  • cleanup:無論 pipeline 或 stage 的完成狀態(tài)如何,都允許運(yùn)行該 post 中定義的指令车吹。和 always 的區(qū)別在于筹裕,cleanup 會(huì)在其它執(zhí)行之后執(zhí)行。

示例
一般情況下 post 部分放在流水線的底部窄驹,比如本實(shí)例朝卒,無論 stage 的完成狀態(tài)如何,都會(huì)輸出一條 I will always say Hello again!信息

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  stages {
    stage('Example1') {
      steps {
        echo 'Hello World1'
      }
    }
    stage('Example2') {
      steps {
        echo 'Hello World2'
      }
    }
  }
  post {
    always {
      echo 'I will always say Hello again!'
    }
  }
}

也可以將 post 寫在 stage乐埠,下面示例表示 Example1 執(zhí)行失敗執(zhí)行 post抗斤。

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  stages {
    stage('Example1') {
      steps {
        sh 'ip a'
      }
      post {
        failure {
          echo 'I will always say Hello again!'
        }
      }
    }
  }
}

2.2.4 sepes

Steps 部分在給定的 stage 指令中執(zhí)行的一個(gè)或多個(gè)步驟,比如在 steps 定義執(zhí)行一條 shell 命令

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  stages {
    stage('Example') {
      steps {
        echo 'Hello World'
      }
    }
  }
}

或者是使用 sh 字段執(zhí)行多條指令

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  stages {
    stage('Example') {
      steps {
        sh """
           echo 'Hello World1'
           echo 'Hello World2'
        """
      }
    }
  }
}

2.3 Directives

Directives可用于一些執(zhí)行 stage 時(shí)的條件判斷或預(yù)處理一些數(shù)據(jù)丈咐,和 Sections 一致瑞眼,Directives 不是一個(gè)關(guān)鍵字或指令,而是包含了 environment棵逊、options伤疙、parameters、triggers辆影、stage徒像、tools黍特、 input、when 等配置厨姚。

2.3.1 Environment

Environment 主要用于在流水線中配置的一些環(huán)境變量衅澈,根據(jù)配置的位置決定環(huán)境變量的作用域∶剑可以定義在 pipeline 中作為全局變量今布,也可以配置在 stage 中作為該 stage 的環(huán)境變量。
該指令支持一個(gè)特殊的方法 credentials()拭抬,該方法可用于在 Jenkins 環(huán)境中通過標(biāo)識(shí)符訪問預(yù)定義的憑證部默。對(duì)于類型為 Secret Text 的憑證,credentials()可以將該 Secret 中的文本內(nèi)容賦值給環(huán)境變量造虎。對(duì)于類型為標(biāo)準(zhǔn)的賬號(hào)密碼型的憑證傅蹂,指定的環(huán)境變量為 usernamepassword育八,并且也會(huì)定義兩個(gè)額外的環(huán)境變量例衍,分別為MYVARNAME_USR和MYVARNAME_PSW

基本變量使用

//示例
pipeline {
  agent any
  environment {   //全局變量衡未,會(huì)在所有stage中生效
    NAME= 'zhangzhuo'
  }
  stages {
    stage('env1') {
      environment { //定義在stage中的變量只會(huì)在當(dāng)前stage生效氓轰,其他的stage不會(huì)生效
        HARBOR = 'https://192.168.10.15'
      }
      steps {
        sh "env"
      }
    }
    stage('env2') {
      steps {
        sh "env"
      }
    }
  }
}

使用變量引用 secret 的憑證

//這里使用k8s的kubeconfig文件示例
pipeline {
  agent any
  environment {
    KUBECONFIG = credentials('kubernetes-cluster')
  }
  stages {
    stage('env') {
      steps {
        sh "env"  //默認(rèn)情況下輸出的變量?jī)?nèi)容會(huì)被加密
      }
    }
  }
}

使用變量引用類型為標(biāo)準(zhǔn)的賬號(hào)密碼型的憑證
這里使用 HARBOR 變量進(jìn)行演示婚夫,默認(rèn)情況下賬號(hào)密碼型的憑證會(huì)自動(dòng)創(chuàng)建 3 個(gè)變量:

  • HARBOR_USR:會(huì)把憑證中 username 值賦值給這個(gè)變量
  • HARBOR_PSW:會(huì)把憑證中 password 值賦值給這個(gè)變量
  • HARBOR:默認(rèn)情況下賦值的值為usernamme:password
//這里使用k8s的kubeconfig文件示例
pipeline {
  agent any
  environment {
    HARBOR = credentials('harbor-account')
  }
  stages {
    stage('env') {
      steps {
        sh "env"
      }
    }
  }
}

2.3.2 Options

Jenkins 流水線支持很多內(nèi)置指令,比如 retry 可以對(duì)失敗的步驟進(jìn)行重復(fù)執(zhí)行 n 次署鸡,可以根據(jù)不同的指令實(shí)現(xiàn)不同的效果案糙。比較常用的指令如下:

  • buildDiscarder:保留多少個(gè)流水線的構(gòu)建記錄
  • disableConcurrentBuilds:禁止流水線并行執(zhí)行,防止并行流水線同時(shí)訪問共享資源導(dǎo)致流水線失敗靴庆。
  • disableResume:如果控制器重啟时捌,禁止流水線自動(dòng)恢復(fù)。
  • newContainerPerStage:agent 為 docker 或 dockerfile 時(shí)炉抒,每個(gè)階段將在同一個(gè)節(jié)點(diǎn)的新容器中運(yùn)行奢讨,而不是所有的階段都在同一個(gè)容器中運(yùn)行。
  • quietPeriod:流水線靜默期焰薄,也就是觸發(fā)流水線后等待一會(huì)在執(zhí)行禽笑。
  • retry:流水線失敗后重試次數(shù)。
  • timeout:設(shè)置流水線的超時(shí)時(shí)間蛤奥,超過流水線時(shí)間佳镜,job 會(huì)自動(dòng)終止。如果不加 unit 參數(shù)默認(rèn)為 1 分凡桥。
  • timestamps:為控制臺(tái)輸出時(shí)間戳蟀伸。

定義在 pipeline 中

pipeline {
  agent any
  options {
    timeout(time: 1, unit: 'HOURS')  //超時(shí)時(shí)間1小時(shí),如果不加unit參數(shù)默認(rèn)為1分
    timestamps()                     //所有輸出每行都會(huì)打印時(shí)間戳
    buildDiscarder(logRotator(numToKeepStr: '3')) //保留三個(gè)歷史構(gòu)建版本
    quietPeriod(10)  //注意手動(dòng)觸發(fā)的構(gòu)建不生效
    retry(3)    //流水線失敗后重試次數(shù)
  }
  stages {
    stage('env1') {
      steps {
        sh "env"
        sleep 2
      }
    }
    stage('env2') {
      steps {
        sh "env"
      }
    }
  }
}

定義在 stage 中
Option 除了寫在 Pipeline 頂層,還可以寫在 stage 中啊掏,但是寫在 stage 中的 option 僅支持 retry蠢络、 timeout、timestamps迟蜜,或者是和 stage 相關(guān)的聲明式選項(xiàng)刹孔,比如 skipDefaultCheckout。處于 stage 級(jí)別的 options 寫法如下

pipeline {
  agent any
  stages {
    stage('env1') {
      options {   //定義在這里這對(duì)這個(gè)stage生效
        timeout(time: 2, unit: 'SECONDS') //超時(shí)時(shí)間2秒
        timestamps()                     //所有輸出每行都會(huì)打印時(shí)間戳
        retry(3)    //流水線失敗后重試次數(shù)
      }
      steps {
        sh "env && sleep 2"
      }
    }
    stage('env2') {
      steps {
        sh "env"
      }
    }
  }
}

2.3.3 Parameters

Parameters 提供了一個(gè)用戶在觸發(fā)流水線時(shí)應(yīng)該提供的參數(shù)列表娜睛,這些用戶指定參數(shù)的值可以通過 params 對(duì)象提供給流水線的 step(步驟)髓霞。只能定義在 pipeline 頂層。

目前支持的參數(shù)類型如下:

  • string:字符串類型的參數(shù)畦戒。
  • text:文本型參數(shù)方库,一般用于定義多行文本內(nèi)容的變量。
  • booleanParam:布爾型參數(shù)障斋。
  • choice:選擇型參數(shù)纵潦,一般用于給定幾個(gè)可選的值,然后選擇其中一個(gè)進(jìn)行賦值垃环。
  • password:密碼型變量邀层,一般用于定義敏感型變量,在 Jenkins 控制臺(tái)會(huì)輸出為*遂庄。

插件 Parameters:

  • imageTag:鏡像 tag被济,需要安裝 Image Tag Parameter 插件后使用
  • gitParameter:獲取 git 倉(cāng)庫(kù)分支,需要 Git Parameter 插件后使用

示例

pipeline {
  agent any
  parameters {
    string(name: 'DEPLOY_ENV', defaultValue:  'staging', description: '1')   //執(zhí)行構(gòu)建時(shí)需要手動(dòng)配置字符串類型參數(shù)涧团,之后賦值給變量
    text(name:  'DEPLOY_TEXT', defaultValue: 'One\nTwo\nThree\n', description: '2')  //執(zhí)行構(gòu)建時(shí)需要提供文本參數(shù),之后賦值給變量
    booleanParam(name: 'DEBUG_BUILD',  defaultValue: true, description: '3')   //布爾型參數(shù)
    choice(name: 'CHOICES', choices: ['one', 'two', 'three'], description: '4')  //選擇形式列表參數(shù)
    password(name: 'PASSWORD', defaultValue: 'SECRET', description: 'A  secret password')  //密碼類型參數(shù)经磅,會(huì)進(jìn)行加密
    imageTag(name: 'DOCKER_IMAGE', description: '', image: 'kubernetes/kubectl', filter: '.*', defaultTag: '', registry: 'https://192.168.10.15', credentialId: 'harbor-account', tagOrder: 'NATURAL')   //獲取鏡像名稱與tag
    gitParameter(branch: '', branchFilter: 'origin/(.*)', defaultValue: '', description: 'Branch for build and deploy', name: 'BRANCH', quickFilterEnabled: false, selectedValue: 'NONE', sortMode: 'NONE',  tagFilter: '*', type: 'PT_BRANCH')
  }  //獲取git倉(cāng)庫(kù)分支列表泌绣,必須有g(shù)it引用
  stages {
    stage('env1') {
      steps {
        sh "env"
      }
    }
    stage('git') {
      steps {
        git branch: "$BRANCH", credentialsId: 'gitlab-key', url: 'git@192.168.10.14:root/env.git'   //使用gitParameter,必須有這個(gè)
      }
    }
  }
}

2.3.4 Triggers

Pipeline 中可以用 triggers 實(shí)現(xiàn)自動(dòng)觸發(fā)流水線執(zhí)行任務(wù)预厌,可以通過 Webhook阿迈、Cron、 pollSCM 和 upstream 等方式觸發(fā)流水線轧叽。

2.3.4.1 Cron

定時(shí)構(gòu)建假如某個(gè)流水線構(gòu)建的時(shí)間比較長(zhǎng)苗沧,或者某個(gè)流水線需要定期在某個(gè)時(shí)間段執(zhí)行構(gòu)建,可以 使用 cron 配置觸發(fā)器炭晒,比如周一到周五每隔四個(gè)小時(shí)執(zhí)行一次

注意H 的意思不是 HOURS 的意思待逞,而是 Hash 的縮寫。主要為了解決多個(gè)流水線在同一時(shí)間同時(shí)運(yùn)行帶來的系統(tǒng)負(fù)載壓力网严。

pipeline {
  agent any
  triggers {
    cron('H */4 * * 1-5')   //周一到周五每隔四個(gè)小時(shí)執(zhí)行一次
    cron('H/12 * * * *')   //每隔12分鐘執(zhí)行一次
    cron('H * * * *')   //每隔1小時(shí)執(zhí)行一次
  }
  stages {
    stage('Example') {
      steps {
        echo 'Hello World'
      }
    }
  }
}

2.3.4.2 Upstream

Upstream 可以根據(jù)上游 job 的執(zhí)行結(jié)果決定是否觸發(fā)該流水線识樱。比如當(dāng) job1 或 job2 執(zhí)行成功時(shí)觸發(fā)該流水線
目前支持的狀態(tài)有SUCCESS、UNSTABLE、FAILURE怜庸、NOT_BUILT当犯、ABORTED等。

pipeline {
  agent any
  triggers {
    upstream(upstreamProjects: 'env', threshold: hudson.model.Result.SUCCESS)  //當(dāng)env構(gòu)建成功時(shí)構(gòu)建這個(gè)流水線
  }
  stages {
    stage('Example') {
      steps {
        echo 'Hello World'
      }
    }
  }
}

2.3.5 Input

Input 字段可以實(shí)現(xiàn)在流水線中進(jìn)行交互式操作割疾,比如選擇要部署的環(huán)境嚎卫、是否繼續(xù)執(zhí)行某個(gè)階段等。

配置 Input 支持以下選項(xiàng):

  • message:必選宏榕,需要用戶進(jìn)行 input 的提示信息拓诸,比如:“是否發(fā)布到生產(chǎn)環(huán)境?”担扑;
  • id:可選恰响,input 的標(biāo)識(shí)符,默認(rèn)為 stage 的名稱涌献;
  • ok:可選胚宦,確認(rèn)按鈕的顯示信息,比如:“確定”燕垃、“允許”枢劝;
  • submitter:可選,允許提交 input 操作的用戶或組的名稱卜壕,如果為空您旁,任何登錄用戶均可提交 input;
  • parameters:提供一個(gè)參數(shù)列表供 input 使用轴捎。

假如需要配置一個(gè)提示消息為“還繼續(xù)么”鹤盒、確認(rèn)按鈕為“繼續(xù)”、提供一個(gè) PERSON 的變量的參數(shù)侦副,并且只能由登錄用戶為 alice 和 bob 提交的 input 流水線

pipeline {
  agent any
  stages {
    stage('Example') {
      input {
        message "還繼續(xù)么?"
        ok "繼續(xù)"
        submitter "alice,bob"
        parameters {
          string(name: 'PERSON', defaultValue: 'Mr Jenkins', description: 'Who should I say hello to?')
        }
      }
      steps {
        echo "Hello, ${PERSON}, nice to meet you."
      }
    }
  }
}

2.3.6 when

When 指令允許流水線根據(jù)給定的條件決定是否應(yīng)該執(zhí)行該 stage侦锯,when指令必須包含至少 一個(gè)條件。如果 when 包含多個(gè)條件秦驯,所有的子條件必須都返回 True尺碰,stage 才能執(zhí)行。
When 也可以結(jié)合 not译隘、allOf、anyOf 語法達(dá)到更靈活的條件匹配固耘。

目前比較常用的內(nèi)置條件如下:

  • branch:當(dāng)正在構(gòu)建的分支與給定的分支匹配時(shí)题篷,執(zhí)行這個(gè) stage。注意厅目,branch只適用于多分支流水線
  • changelog:匹配提交的 changeLog 決定是否構(gòu)建悼凑,例如:when { changelog '.*^\\[DEPENDENCY\\] .+$' }
  • environment:當(dāng)指定的環(huán)境變量和給定的變量匹配時(shí)偿枕,執(zhí)行這個(gè) stage,例如:when { environment name: 'DEPLOY_TO', value: 'production' }
  • equals:當(dāng)期望值和實(shí)際值相同時(shí)户辫,執(zhí)行這個(gè) stage渐夸,例如:when { equals expected: 2, actual: currentBuild.number };
  • expression:當(dāng)指定的 Groovy 表達(dá)式評(píng)估為 True渔欢,執(zhí)行這個(gè) stage墓塌,例如:when { expression { return params.DEBUG_BUILD } };
  • tag:如果 TAG_NAME 的值和給定的條件匹配奥额,執(zhí)行這個(gè) stage苫幢,例如:when { tag "release-" };
  • not:當(dāng)嵌套條件出現(xiàn)錯(cuò)誤時(shí)垫挨,執(zhí)行這個(gè) stage韩肝,必須包含一個(gè)條件,例如:when { not { branch 'master' } }九榔;
  • allOf:當(dāng)所有的嵌套條件都正確時(shí)哀峻,執(zhí)行這個(gè) stage,必須包含至少一個(gè)條件哲泊,例如:when { allOf { branch 'master'; environment name: 'DEPLOY_TO', value: 'production' } }剩蟀;
  • anyOf:當(dāng)至少有一個(gè)嵌套條件為 True 時(shí),執(zhí)行這個(gè) stage切威,例如:when { anyOf { branch 'master'; branch 'staging' } }

示例:當(dāng)分支為 main 時(shí)執(zhí)行 Example Deploy 步驟

pipeline {
  agent any
  stages {
    stage('Example Build') {
      steps {
        echo 'Hello World'
      }
    }
    stage('Example Deploy') {
      when {
        branch 'main' //多分支流水線育特,分支為才會(huì)執(zhí)行。
      }
      steps {
        echo 'Deploying'
      }
    }
  }
}

也可以同時(shí)配置多個(gè)條件先朦,比如分支是 production缰冤,而且 DEPLOY_TO 變量的值為 main 時(shí),才執(zhí)行 Example Deploy

pipeline {
  agent any
  environment {
    DEPLOY_TO = "main"
  }
  stages {
    stage('Example Deploy') {
      when {
        branch 'main'
        environment name: 'DEPLOY_TO', value: 'main'
      }
      steps {
        echo 'Deploying'
      }
    }
  }
}

也可以使用 anyOf 進(jìn)行匹配其中一個(gè)條件即可喳魏,比如分支為 main 或 DEPLOY_TO 為 main 或 master 時(shí)執(zhí)行 Deploy

pipeline {
  agent any
  stages {
    stage('Example Deploy') {
      when {
        anyOf {
          branch 'main'
          environment name: 'DEPLOY_TO', value: 'main'
          environment name: 'DEPLOY_TO', value: 'master'
        }
      }
      steps {
        echo 'Deploying'
      }
    }
  }
}

也可以使用 expression 進(jìn)行正則匹配棉浸,比如當(dāng) BRANCH_NAME 為 main 或 master,并且 DEPLOY_TO 為 master 或 main 時(shí)才會(huì)執(zhí)行 Example Deploy

pipeline {
  agent any
  stages {
    stage('Example Deploy') {
      when {
        expression { BRANCH_NAME ==~ /(main|master)/ }
        anyOf {
          environment name: 'DEPLOY_TO', value: 'main'
          environment name: 'DEPLOY_TO', value: 'master'
        }
      }
      steps {
        echo 'Deploying'
      }
    }
  }
}

默認(rèn)情況下截酷,如果定義了某個(gè) stage 的 agent,在進(jìn)入該 stage 的 agent 后乾戏,該 stage 的 when 條件才會(huì)被評(píng)估迂苛,但是可以通過一些選項(xiàng)更改此選項(xiàng)。比如在進(jìn)入 stage 的 agent 前評(píng)估 when鼓择, 可以使用 beforeAgent三幻,當(dāng) when 為 true 時(shí)才進(jìn)行該 stage

目前支持的前置條件如下:

  • beforeAgent:如果 beforeAgent 為 true,則會(huì)先評(píng)估 when 條件呐能。在 when 條件為 true 時(shí)念搬,才會(huì)進(jìn)入該 stage
  • beforeInput:如果 beforeInput 為 true抑堡,則會(huì)先評(píng)估 when 條件。在 when 條件為 true 時(shí)朗徊,才會(huì)進(jìn)入到 input 階段首妖;
  • beforeOptions:如果 beforeInput 為 true,則會(huì)先評(píng)估 when 條件爷恳。在 when 條件為 true 時(shí)有缆,才會(huì)進(jìn)入到 options 階段;
  • beforeOptions 優(yōu)先級(jí)大于beforeInput大于beforeAgent

示例

pipeline {
  agent none
  stages {
    stage('Example Build') {
      steps {
        echo 'Hello World'
      }
    }
    stage('Example Deploy') {
      when {
        beforeAgent true
        branch 'main'
      }
      steps {
        echo 'Deploying'
      }
    }
  }
}

2.4 Parallel

在聲明式流水線中可以使用 Parallel 字段温亲,即可很方便的實(shí)現(xiàn)并發(fā)構(gòu)建棚壁,比如對(duì)分支 A、B栈虚、 C 進(jìn)行并行處理

pipeline {
  agent any
  stages {
    stage('Non-Parallel Stage') {
      steps {
        echo 'This stage will be executed first.'
      }
    }
    stage('Parallel Stage') {
      failFast true         //表示其中只要有一個(gè)分支構(gòu)建執(zhí)行失敗袖外,就直接推出不等待其他分支構(gòu)建
      parallel {
        stage('Branch A') {
          steps {
            echo "On Branch A"
          }
        }
        stage('Branch B') {
          steps {
            echo "On Branch B"
          }
        }
        stage('Branch C') {
          stages {
            stage('Nested 1') {
              steps {
                echo "In stage Nested 1 within Branch C"
              }
            }
            stage('Nested 2') {
              steps {
               echo "In stage Nested 2 within Branch C"
              }
            }
          }
        }
      }
    }
  }
}

3 Jenkinsfile 的使用

上面講過流水線支持兩種語法,即聲明式腳本式魂务,這兩種語法都支持構(gòu)建持續(xù)交付流水線曼验。并且都可以用來在 Web UI 或 Jenkinsfile 中定義流水線,不過通常將 Jenkinsfile 放置于代碼倉(cāng)庫(kù)中(當(dāng)然也可以放在單獨(dú)的代碼倉(cāng)庫(kù)中進(jìn)行管理)头镊。

創(chuàng)建一個(gè) Jenkinsfile并將其放置于代碼倉(cāng)庫(kù)中蚣驼,有以下好處:

  • 方便對(duì)流水線上的代碼進(jìn)行復(fù)查/迭代
  • 對(duì)管道進(jìn)行審計(jì)跟蹤
  • 流水線真正的源代碼能夠被項(xiàng)目的多個(gè)成員查看和編輯

3.1 環(huán)境變量

3.1.1 靜態(tài)變量

Jenkins 有許多內(nèi)置變量可以直接在Jenkinsfile 中使用,可以通過JENKINS_URL/pipeline/syntax/globals#env獲取完整列表相艇。目前比較常用的環(huán)境變量如下:

  • BUILD_ID:當(dāng)前構(gòu)建的 ID颖杏,與 Jenkins 版本 1.597+中BUILD_NUMBER完全相同
  • BUILD_NUMBER:當(dāng)前構(gòu)建的 ID,和 BUILD_ID 一致
  • BUILD_TAG:用來標(biāo)識(shí)構(gòu)建的版本號(hào)坛芽,格式為:jenkins-{BUILD_NUMBER}留储, 可以對(duì)產(chǎn)物進(jìn)行命名,比如生產(chǎn)的 jar 包名字咙轩、鏡像的 TAG 等获讳;
  • BUILD_URL:本次構(gòu)建的完整 URL,比如:http://buildserver/jenkins/job/MyJobName/17/%EF%BC%9B
  • JOB_NAME:本次構(gòu)建的項(xiàng)目名稱
  • NODE_NAME:當(dāng)前構(gòu)建節(jié)點(diǎn)的名稱活喊;
  • JENKINS_URL:Jenkins 完整的 URL丐膝,需要在 SystemConfiguration 設(shè)置;
  • WORKSPACE:執(zhí)行構(gòu)建的工作目錄钾菊。

示例如果一個(gè)流水線名稱為print_env帅矗,第 2 次構(gòu)建,各個(gè)變量的值煞烫。

BUILD_ID:2
BUILD_NUMBER:2
BUILD_TAG:jenkins-print_env-2
BUILD_URL:http://192.168.10.16:8080/job/print_env/2/
JOB_NAME:print_env
NODE_NAME:built-in
JENKINS_URL:http://192.168.10.16:8080/
WORKSPACE:/bitnami/jenkins/home/workspace/print_env

上述變量會(huì)保存在一個(gè) Map 中浑此,可以使用 env.BUILD_ID 或 env.JENKINS_URL 引用某個(gè)內(nèi)置變量

pipeline {
  agent any
  stages {
    stage('print env') {
      parallel {
        stage('BUILD_ID') {
          steps {
            echo "$env.BUILD_ID"
          }
        }
        stage('BUILD_NUMBER') {
          steps {
            echo "$env.BUILD_NUMBER"
          }
        }
        stage('BUILD_TAG') {
          steps {
            echo "$env.BUILD_TAG"
          }
        }
      }
    }
  }
}

3.1.2 動(dòng)態(tài)變量

動(dòng)態(tài)變量是根據(jù)某個(gè)指令的結(jié)果進(jìn)行動(dòng)態(tài)賦值,變量的值根據(jù)指令的執(zhí)行結(jié)果而不同滞详。如下所示

  • returnStdout:將命令的執(zhí)行結(jié)果賦值給變量凛俱,比如下述的命令返回的是 clang紊馏,此時(shí) CC 的值為“clang”。
  • returnStatus:將命令的執(zhí)行狀態(tài)賦值給變量蒲犬,比如下述命令的執(zhí)行狀態(tài)為 1朱监,此時(shí) EXIT_STATUS 的值為 1。
//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  environment {
    // 使用 returnStdout
    CC = """${sh(
         returnStdout: true,
         script: 'echo -n "clang"'   //如果使用shell命令的echo賦值變量最好加-n取消換行
         )}"""
    // 使用 returnStatus
    EXIT_STATUS = """${sh(
         returnStatus: true,
         script: 'exit 1'
         )}"""
  }
  stages {
    stage('Example') {
      environment {
        DEBUG_FLAGS = '-g'
      }
      steps {
        sh 'printenv'
      }
    }
  }
}

3.2 憑證管理

Jenkins 的聲明式流水線語法有一個(gè) credentials()函數(shù)暖哨,它支持 secret text(加密文本)赌朋、username 和 password(用戶名和密碼)以及 secret file(加密文件)等。接下來看一下一些常用的憑證處理方法篇裁。

3.2.1 加密文本

本實(shí)例演示將兩個(gè) Secret 文本憑證分配給單獨(dú)的環(huán)境變量來訪問 Amazon Web 服務(wù)沛慢,需要 提前創(chuàng)建這兩個(gè)文件的 credentials(實(shí)踐的章節(jié)會(huì)有演示),Jenkinsfile 文件的內(nèi)容如下

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  environment {
    AWS_ACCESS_KEY_ID = credentials('txt1')
    AWS_SECRET_ACCESS_KEY = credentials('txt2')
  }
  stages {
    stage('Example stage 1') {
      steps {
        echo "$AWS_ACCESS_KEY_ID"
      }
    }
    stage('Example stage 2') {
      steps {
        echo "$AWS_SECRET_ACCESS_KEY"
      }
    }
  }
}

3.2.2 用戶名密碼

本示例用來演示 credentials 賬號(hào)密碼的使用达布,比如使用一個(gè)公用賬戶訪問 Bitbucket团甲、GitLab、 Harbor 等黍聂。假設(shè)已經(jīng)配置完成了用戶名密碼形式的 credentials躺苦,憑證 ID 為 harbor-account

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent any
  environment {
    BITBUCKET_COMMON_CREDS = credentials('harbor-account')
  }
  stages {
    stage('printenv') {
      steps {
        sh "env"
      }
    }
}

上述的配置會(huì)自動(dòng)生成 3 個(gè)環(huán)境變量:

  • BITBUCKET_COMMON_CREDS:包含一個(gè)以冒號(hào)分隔的用戶名和密碼,格式為 username:password
  • BITBUCKET_COMMON_CREDS_USR:僅包含用戶名的附加變量
  • BITBUCKET_COMMON_CREDS_PSW:僅包含密碼的附加變量产还。

3.2.3 加密文件

需要加密保存的文件匹厘,也可以使用 credential,比如鏈接到 Kubernetes 集群的 kubeconfig 文件等脐区。

假如已經(jīng)配置好了一個(gè) kubeconfig 文件愈诚,此時(shí)可以在 Pipeline 中引用該文件

//Jenkinsfile (Declarative Pipeline)
pipeline {
  agent {
    kubernetes {
      cloud 'kubernetes'
      slaveConnectTimeout 1200
      workspaceVolume emptyDirWorkspaceVolume()
      yaml '''
kind: Pod
metadata:
  name: jenkins-agent
spec:
  containers:
  - args: [\'$(JENKINS_SECRET)\', \'$(JENKINS_NAME)\']
    image: '192.168.10.15/kubernetes/jnlp:alpine'
    name: jnlp
    imagePullPolicy: IfNotPresent
  - command:
      - "cat"
    image: "192.168.10.15/kubernetes/kubectl:apline"
    imagePullPolicy: "IfNotPresent"
    name: "kubectl"
    tty: true
  restartPolicy: Never
'''
    }
  }
  environment {
    MY_KUBECONFIG = credentials('kubernetes-cluster')
  }
  stages {
    stage('kubectl') {
      steps {
        container(name: 'kubectl') {
          sh """
            kubectl get pod -A  --kubeconfig $MY_KUBECONFIG
          """
        }
      }
    }
  }
}

轉(zhuǎn)載于:https://mp.weixin.qq.com/s/xnIpd4bjjt9Nv7bE_hASXQ

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市牛隅,隨后出現(xiàn)的幾起案子炕柔,更是在濱河造成了極大的恐慌,老刑警劉巖媒佣,帶你破解...
    沈念sama閱讀 217,406評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件匕累,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡默伍,警方通過查閱死者的電腦和手機(jī)欢嘿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,732評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來也糊,“玉大人炼蹦,你說我怎么就攤上這事∠陨瑁” “怎么了框弛?”我有些...
    開封第一講書人閱讀 163,711評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵辛辨,是天一觀的道長(zhǎng)捕捂。 經(jīng)常有香客問我瑟枫,道長(zhǎng),這世上最難降的妖魔是什么指攒? 我笑而不...
    開封第一講書人閱讀 58,380評(píng)論 1 293
  • 正文 為了忘掉前任慷妙,我火速辦了婚禮,結(jié)果婚禮上允悦,老公的妹妹穿的比我還像新娘膝擂。我一直安慰自己,他們只是感情好隙弛,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,432評(píng)論 6 392
  • 文/花漫 我一把揭開白布架馋。 她就那樣靜靜地躺著,像睡著了一般全闷。 火紅的嫁衣襯著肌膚如雪叉寂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,301評(píng)論 1 301
  • 那天总珠,我揣著相機(jī)與錄音屏鳍,去河邊找鬼。 笑死局服,一個(gè)胖子當(dāng)著我的面吹牛钓瞭,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播淫奔,決...
    沈念sama閱讀 40,145評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼山涡,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了搏讶?” 一聲冷哼從身側(cè)響起佳鳖,我...
    開封第一講書人閱讀 39,008評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎媒惕,沒想到半個(gè)月后系吩,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,443評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妒蔚,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,649評(píng)論 3 334
  • 正文 我和宋清朗相戀三年穿挨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片肴盏。...
    茶點(diǎn)故事閱讀 39,795評(píng)論 1 347
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡科盛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出菜皂,到底是詐尸還是另有隱情贞绵,我是刑警寧澤,帶...
    沈念sama閱讀 35,501評(píng)論 5 345
  • 正文 年R本政府宣布恍飘,位于F島的核電站榨崩,受9級(jí)特大地震影響谴垫,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜母蛛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,119評(píng)論 3 328
  • 文/蒙蒙 一翩剪、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧彩郊,春花似錦前弯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,731評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至违帆,卻和暖如春剃根,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背前方。 一陣腳步聲響...
    開封第一講書人閱讀 32,865評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工狈醉, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人惠险。 一個(gè)月前我還...
    沈念sama閱讀 47,899評(píng)論 2 370
  • 正文 我出身青樓苗傅,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親班巩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子渣慕,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,724評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容