声明式管道中基于前一阶段结果的条件执行

时间:2019-09-07 05:21:19

标签: jenkins-pipeline jenkins-declarative-pipeline

我的管道设置如下。 enter image description here

我需要使其遵循以下条件才能正常工作。帮助我定义何时使用块和其他代码以及在哪个阶段使用?

  1. 如果A失败,则不执行其他任何步骤,并且作业运行被标记为失败。
  2. 如果任何B阶段失败,则不应调用相应的C阶段。
  3. 无论执行C1或C2是否失败,都应执行阶段D。
  4. 此外,如果任何一个阶段都失败了,那么整个作业运行状态都将失败。

我尝试并观察了什么? 根据上面定义的条件,我的以下尝试使1和2可以正常工作,但3和4不能正常工作。

在C1和C2中,我添加了catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE')指的是Continue Jenkins pipeline past failed stage

但是我观察到的是-

    如果C1或C2失败,则执行
  1. D,但总体上将作业标记为“成功”。由于C步骤之一已失败,因此预期会失败。但是由于捕获,它获得了成功状态。
  2. 当B个阶段中的任何一个失败时,它们相应的C也不会执行(预期),但也不会触发D。因为需要执行其他一些C,所以我需要触发D。

1 个答案:

答案 0 :(得分:1)

这就是您需要的:

stageResultMap = [:]

pipeline {
    agent any
    stages {
        stage('A') {
            steps {
                println("This is stage: ${STAGE_NAME}")
            }
        }
        stage('BC') {
            parallel {
                stage ('1'){
                    stages {
                        stage('B1') {
                            steps {
                                script {
                                    // Catch exceptions, set the stage result as unstable,
                                    // build result as failure, and the variable didB1Succeed to false
                                    try {                                        
                                        sh "exit 1"
                                        stageResultMap.didB1Succeed = true
                                    }
                                    catch (Exception e) {
                                        unstable("${STAGE_NAME} failed!")
                                        currentBuild.result = 'FAILURE'
                                        stageResultMap.didB1Succeed = false                                        
                                    }
                                }
                            }
                        }
                        stage('C1') {
                            // Execute only if B1 succeeded
                            when {
                                expression {
                                    return stageResultMap.find{ it.key == "didB1Succeed" }?.value
                                }
                            }
                            steps {
                                // Mark the stage and build results as failure on error but continue pipeline execution
                                catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
                                    sh "echo Hello"
                                }
                            }
                        }
                    } 
                }
                stage ('2'){
                    stages {
                        stage('B2') {
                            steps {
                                script {
                                    // Catch exceptions, set the stage result as unstable,
                                    // build result as failure, and the variable didB2Succeed to false
                                    try {
                                        sh "echo Hello"
                                        stageResultMap.didB2Succeed = true
                                    }
                                    catch (Exception e) {
                                        unstable("${STAGE_NAME} failed!")
                                        currentBuild.result = 'FAILURE'
                                        stageResultMap.didB2Succeed = false                                        
                                    }
                                }
                            }
                        }
                        stage('C2') {
                            // Execute only if B2 succeeded
                            when {
                                expression {
                                    return stageResultMap.find{ it.key == "didB2Succeed" }?.value
                                }
                            }
                            steps {
                                // Mark the stage and build results as failure on error but continue pipeline execution
                                catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
                                    sh "echo Hello"
                                }
                            }
                        }
                    } 
                }
            }
        }
        stage('D') {
            // Execute only when C1 or C2 have executed, that is B1 or B2 have succeeded
            when {
                expression {
                    return stageResultMap.any {it.value}
                }
            }
            steps {
                println("This is stage: ${STAGE_NAME}")
            }
        }
    }
}
  1. 对于阶段C1和C2,使用catchError(buildResult: 'FAILURE', stageResult: 'FAILURE')标记该阶段,并将构建结果标记为FAILURE,但继续执行管道。

enter image description here enter image description here

  1. 对于阶段B1和B2,首先在Jenkinsfile顶部初始化一个空映射stageResultMap = [:],以捕获每个阶段的结果。现在,对于每个Bn阶段,请使用try-catch块,以便在成功时将唯一的键值对stageResultsMap.didBnSucceed = true添加到映射,并且在例外情况下,阶段结果设置为UNSTABLE ,将结果构建为FAILURE,然后stageResultsMap.didBnSucceed = false。我们在这里使用方法unstable,因为其他两个方法catchErrorwarnError都不让我们添加到地图中。然后,在相应的Cn阶段,评估映射并仅在Bn成功的情况下执行。另外,如果B1和B2均失​​败,即C1和C2均未执行,则D也将不会执行,因为when {expression {return stageResultMap.any {it.value}}}的值为false。但是,无论执行C1还是C2,无论失败如何,D都会执行。

enter image description here enter image description here

在上述两种情况下,如果任何一个阶段失败,则总体构建状态将标记为“失败”。

当然,没有失败的绿色基础。

enter image description here