今天來介紹在 Jenkinsfile 中 if else 的變形 - when。 使用 when 有助於我們在 Jenkins UI 閱讀時更加容易。
這邊我們以昨天的例子作為範例
pipeline{
    agent any
    parameters {
        choice(name: 'env', choices: ['staging', 'uat', 'prod'])
    }
    stages{
        stage("Deploy process"){
            steps{
                script{
                    if (params.env == "staging"){
                        // do staging processing
                        echo "deploy to test env"
                    } else if (params.env == "uat"){
                        // do uat processing
                        echo "deploy to poc uat"
                    } else if (params.env == "prod"){
                        // do production processing
                        echo "deploy to prod env"
                    }
                }
            }
        }
    }
}

看似沒什麼問題,但是從 Ocean blue UI 來看,需要點開 stage(Deploy process) 的 log 才能清楚知道我們是在做哪一個環境的部署,故較難閱讀。接下來讓我們試著用 when 來寫同一個 pipeline 看看會有什麼不同吧~
pipeline{
    agent any
    parameters {
        choice(name: 'env', choices: ['staging', 'uat', 'prod'])
    }
    stages{
        stage("Deploy"){
            parallel{
                stage("staging env"){
                    when {
                        expression { params.env == "staging" } 
                    }
                    steps{
                        // do staging processing
                        echo "deploy to staging env"
                    }
                }
                stage("UAT uat"){
                    when {
                        expression { params.env == "uat" } 
                    }
                    steps{
                        // do uat processing
                        echo "deploy to uat env"
                    }
                }
                stage("Prod env"){
                    when {
                        expression { params.env == "prod" } 
                    }
                    steps{
                        // do prod processing
                        echo "deploy to prod env"
                    }
                }
            }
        }
    }
}

當沒有滿足 when 的條件時,則當下的 stage 直接判為 skip,因此我們可以搭配 parallel 實現更簡易閱讀的 pipeline。
而在 when 的區塊內大致有以下常見的判斷式:
environment: 搭配在初始 pipeline 時宣告的環境變數,做為判斷依據。pipeline{
    agent any
    environment { 
        env = 'staging'
    }    
    stages{
        stage("the stage that will be executed"){
            when{
                environment name: 'env', value: 'staging'
            }
            steps{
                echo "processing"
            }
        }
        
        stage("the stage that will not be executed"){
            when{
                environment name: 'env', value: 'uat'
            }
            steps{
                echo "processing"
            }
        }
    }
}
expression:pipeline{
    agent any
    parameters {
        string(name: 'env', default='staging')
    }
    stages{
        stage("the stage that will be executed"){
            when {
                expression { params.env == "staging" } 
            }
            steps{
                echo "processing"
            }
        }
        
        stage("the stage that will not be executed"){
            when {
                expression { params.env == "not exist" } 
            }
            steps{
                echo "processing"
            }
        }
    }
}
branch: 主要使用在 multibranch pipeline,用以判斷目前 branch 下是否要執行特定行為,例如:當 branch 為 main 時,會去 build docker latest image ......// branch == day14
pipeline{
    agent any
    stages{
        stage("the stage that will be executed"){
            when {
                branch 'day14'
            }
            steps{
                echo "processing"
            }
        }
        
        stage("the stage that will not be executed"){
            when {
                branch 'notExists'
            }
            steps{
                echo "processing"
            }
        }
    }
}
not: 作為反敘述使用,當 not 中的內容為假時,則敘述成立,stage 開始執行。建議不要在 pipeline 中加入過多的反敘述條件假設,會造成閱讀困難。
// branch == day14
pipeline{
    agent any
    stages{
        stage("the stage that will be executed"){
            when {
                not { branch 'notExists' }
            }
            steps{
                echo "processing"
            }
        }
        
        stage("the stage that will not be executed"){
            when {
                not { branch 'day14' }
            }
            steps{
                echo "processing"
            }
        }
    }
}
allOf: 當在 allOf 內的條件皆成立,,則敘述成立,stage 開始執行。// branch == day14
pipeline{
    agent any
    parameters {
        string(name: 'env', default='staging')
    }
    stages{
        stage("the stage that will be executed"){
            when {
                allOf{
                    branch 'day14'
                    expression { params.env == "staging" }
                }
            }
            steps{
                echo "processing"
            }
        }
        
        stage("the stage that will not be executed"){
            when {
                allOf{
                    branch 'day14'
                    expression { params.env == "not exists" }
                }
            }
            steps{
                echo "processing"
            }
        }
    }
}
anyOf: 當在 anyOf 內的條件任一一個成立,,則敘述成立,stage 開始執行。// branch == day14
pipeline{
    agent any
    parameters {
        string(name: 'env', default='staging')
    }
    stages{
        stage("the stage that will be executed"){
            when {
                anyOf{
                    branch 'day14'
                    expression { params.env == "staging" }
                }
            }
            steps{
                echo "processing"
            }
        }
        
        stage("the stage that will not be executed"){
            when {
                anyOf{
                    branch 'notExist'
                    expression { params.env == "not exists" }
                }
            }
            steps{
                echo "processing"
            }
        }
    }
}
今天做了很多相似的例子可能會需要花點時間來品評其中的差異,但是非常推薦大家用 when 來優化自己的 pipeline。
https://michakutz.medium.com/conditionals-in-a-declarative-pipeline-jenkinsfile-d1a4a44e93bb
https://www.jenkins.io/doc/book/pipeline/syntax/#when