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

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

问题描述

我的管道设置如下.

我需要让它在遵守以下条件的情况下工作.帮我定义何时使用块和其他代码以及在哪些阶段使用?

  1. 如果 A 失败,则不执行其他阶段,作业运行标记为失败.
  2. 如果任何 B 阶段失败,则不应调用相应的 C 阶段.
  3. 阶段 D 应在 C1 或 C2 已执行时执行,无论其执行是否失败.
  4. 此外,如果任何阶段失败,则整个作业运行状态应为失败.

我尝试了什么&观察到?根据上述定义的条件,1 和 2 可以按预期工作,但在我的以下尝试中,3 和 4 没有.

在 C1 和 C2 中,我添加了 catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') 指的是

  1. 适用于 B1 阶段和B2、首先在你的Jenkinsfile的顶部初始化一个空的map stageResultMap = [:] 来捕获每个阶段的结果.现在,对于每个 Bn 阶段,使用 try-catch 块,以便在成功时唯一的键值对 stageResultsMap.ddBnSucceed = 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 将执行.

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

当然,没有失败的绿色构建.

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天全站免登陆