Jenkinsfile 變數使用示範

筆者最近在寫 Jenkinsfile ,Jenkinsfile 有區分 Declarative Pipeline (宣告式) 和稍微進階一點的 Scripted Pipeline (腳本/指令式)。筆者一開始是使用指令式,不過寫到後面在寫成功和失敗的通知(post)時才發現指令式只能用 try catch 的方式慢慢作錯誤處理,非常麻煩。 而宣告式只要一個 post 區塊,裡面放 success, fixed, failure 等區塊就好了,簡單很多。 於是就從指令式跳槽到宣告式的 Jenkinsfile,為了怕以後忘記怎麼寫又要重新研究,於是就寫在這篇作紀錄。

宣告式 Declarative Pipeline:
    
pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                echo 'Building..'
            }
        }
    }
}
    

腳本/指令式 Scripted Pipeline
    
node {
	stage('Checkout'){
	    echo 'Checkout'
	    checkout scm
	}
}
    

最容易分辨的方式應該就是宣告式 Declarative Pipeline 需要有 pipeline 關鍵字開頭

宣告式 Declarative Pipeline 變數使用示範
    
pipeline {
    agent any
    
    environment {
        DOCKER_IMAGE = "ruyut_image"
        DOCKER_IMAGE_VERSION = "1.0.0"
    }
    
    stages {
    
        stage('Get commit details') {
            steps {
                script {
                    env.GIT_COMMIT_MSG = sh (script: 'git log -1 --pretty=%B ${GIT_COMMIT}', returnStdout: true).trim()
                    env.GIT_AUTHOR = sh (script: 'git log -1 --pretty=%cn ${GIT_COMMIT}', returnStdout: true).trim()
                }
                
                echo "commit 訊息: ${GIT_COMMIT_MSG}"
                echo "commit 使用者: ${GIT_AUTHOR}"
            }
        }
        
        stage('Check')
        {
            steps {
                echo 'Check'
                sh 'docker --version'
                
                echo 'DOCKER_IMAGE: ' + DOCKER_IMAGE
                echo 'DOCKER_IMAGE_VERSION: ' + DOCKER_IMAGE_VERSION
                
                echo ''
                
                echo 'DOCKER_IMAGE: ' + env.DOCKER_IMAGE
                echo 'DOCKER_IMAGE_VERSION: ' + env.DOCKER_IMAGE_VERSION
            }
        }
}
    

腳本/指令式 Scripted Pipeline 變數使用示範
    
node{
    withEnv(
        [
            "DOCKER_IMAGE=ruyut_image",
            "DOCKER_IMAGE_VERSION=1.0.0"
        ]){
    
        stage('Checkout'){
            echo 'Checkout'
            checkout scm
        }
        
        stage('Get commit details') {
            env.GIT_COMMIT_MSG = sh (script: 'git log -1 --pretty=%B ${GIT_COMMIT}', returnStdout: true).trim()
            env.GIT_AUTHOR = sh (script: 'git log -1 --pretty=%cn ${GIT_COMMIT}', returnStdout: true).trim()
            
            echo "commit 訊息: ${GIT_COMMIT_MSG}"
            echo "commit 使用者: ${GIT_AUTHOR}"
        }
        
        stage('Check')
        {
            echo 'DOCKER_IMAGE: ' + DOCKER_IMAGE
            echo 'DOCKER_IMAGE_VERSION: ' + DOCKER_IMAGE_VERSION
            
            echo ''
            
            echo 'DOCKER_IMAGE: ' + env.DOCKER_IMAGE
            echo 'DOCKER_IMAGE_VERSION: ' + env.DOCKER_IMAGE_VERSION
        }

    }
}
    

筆者在測試中 DOCKER_IMAGE 和 env.DOCKER_IMAGE 這兩種方式都能正常讀取到,如果要在字串中直接使用的話可以用 ${} 的方式。

另外筆者在測試中發現如果一個 stage 中有多個 steps 會拋出下面的錯誤訊息
    
Started by GitHub push by ruyut
Obtained Jenkinsfile from git git@github.com:ruyut/ruyut.git
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 12: Multiple occurrences of the steps section @ line 12, column 9.
           stage('Get commit details') {
           ^

WorkflowScript: 12: Duplicate parallel branch name: "default" @ line 12, column 9.
           stage('Get commit details') {
           ^

2 errors

	at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:309)
	at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1107)
	at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:624)
	at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:602)
	at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:579)
	at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:323)
	at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:293)
	at groovy.lang.GroovyShell.parseClass(GroovyShell.java:677)
	at groovy.lang.GroovyShell.parse(GroovyShell.java:689)
	at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:142)
	at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:127)
	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:561)
	at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:513)
	at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:335)
	at hudson.model.ResourceController.execute(ResourceController.java:107)
	at hudson.model.Executor.run(Executor.java:449)
Finished: FAILURE
    

所以一個 stage 中只能有一個 steps

參考資料:
Using a Jenkinsfile

留言