声明式管道中基于前一阶段结果的条件执行 [英] Conditional execution based on result of previous stage in declarative pipeline

查看:66
本文介绍了声明式管道中基于前一阶段结果的条件执行的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的管道设置如下.

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

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

我尝试过什么&观察到了吗?根据上面定义的条件,我的以下尝试使1和2可以正常工作,但3和4却无法正常工作.

在C1和C2中,我添加了 catchError(buildResult:'SUCCESS',stageResult:'FAILURE'),引用了

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

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

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

My pipeline setup is as follows.

I need to get it working with adherence to following conditions. Help me defining when blocks and other code to be used and in which stages?

  1. If A fails, no other stage is executed and job run is marked failed.
  2. If any of the B stage fails, then corresponding C stage should not be invoked.
  3. Stage D should get executed when either C1 or C2 have been executed regardless of failure in their execution.
  4. Also, if any of the stages have been failed, then the over all job run status should be fail.

What have I tried & observed? From above conditions defined, 1 and 2 are working as expected but not 3 and 4 with my following attempt.

In C1 and C2, I added catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') referring to Continue Jenkins pipeline past failed stage.

But what I have observed is -

  1. D executes if C1 or C2 fails, but over all job run is marked Success. Expected is failure as one of the C steps have failed. But due to catch it gets success status.
  2. When any of the B stages fail, their corresponding C also doesn't execute (expected) but it doesn't trigger D either. As I need D to be triggered because some other C has been executed.

解决方案

This is what you need:

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. For stages C1 & C2, use catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') to mark both the stage and build results as FAILURE but continue pipeline execution.

  1. For stages B1 & B2, first initialize an empty map stageResultMap = [:] at the top of your Jenkinsfile to capture the results of each stage. Now, for every Bn stage, use a try-catch block so that on success a unique key-value pair stageResultsMap.didBnSucceed = true is added to the map, and on exception the stage result is set to UNSTABLE, build result to FAILURE, and stageResultsMap.didBnSucceed = false. We use the method unstable here because none of the other two methods catchError or warnError let us add to the map. Then, in the corresponding Cn stage, evaluate the map and execute only if Bn did succeed. Also, if both B1 and B2 fail, i.e., both C1 and C2 do not execute, D wouldn't execute either because when {expression {return stageResultMap.any {it.value}}} will evaluate to false. But D will execute if either C1 or C2 executed regardless of failures.

In both the above scenarios, the overall build status will be marked as FAILURE if any of the stages fail.

Of course, a green build on no failures.

这篇关于声明式管道中基于前一阶段结果的条件执行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆