withMaven UNSTABLE 构建结果未保留在 Jenkins 声明性管道中

withMaven UNSTABLE build result is not preserved in Jenkins declarative pipeline

当 Maven 构建步骤因测试失败而退出时,我想将构建结果设置为 UNSTABLE。 我正在使用 withMaven 构建步骤,它提供对 Maven 测试结果的特殊处理: 如果测试失败,它会在步骤失败之前将构建结果设置为 UNSTABLE

这在使用脚本管道时非常有效。 但是,在声明性管道的情况下,构建结果设置为 FAILURE.

以下代码示例说明了这一点。

编辑:请注意,示例工作不需要 try/catch 和 post 块。它们的存在只是为了在调用 withMaven.

之后可以立即检查 currentBuild.result 的值

声明式

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                withMaven() {
                    sh 'mvn clean verify' // -> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
                }
            }

            post {
                always {
                    echo "CurrentResult: $currentBuild.currentResult" // -> FAILURE
                    echo "Result: $currentBuild.result"               // -> FAILURE
                                                                      // overall build result -> FAILURE
                }
            }
        }
    }
}

脚本化

node() {
    stage('Build') {
        try {
            withMaven() {
                sh 'mvn clean verify'  // -> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
            }
        } catch (e) {
            echo "CurrentResult: $currentBuild.currentResult" // -> UNSTABLE
            echo "Result: $currentBuild.result"               // -> UNSTABLE
                                                              // overall build result -> UNSTABLE
        }
    }
}

如何在声明性管道中保留 Maven 构建步骤中 UNSTABLE 的构建结果?

使用的版本:Jenkins 2.204.1、Pipeline Maven Integration Plugin 3.8.2、Maven 3.6.3(安装在构建代理上)、AdoptOpenJDK 1.8。0_222.

您的管道之间的区别在于您在脚本管道上使用了 try/catch。我会做的是以下

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                script {
                    try {
                        withMaven() {
                            sh 'mvn clean verify' // -> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
                        }
                    } catch (e) {
                        echo "CurrentResult: $currentBuild.currentResult" // -> UNSTABLE
                        echo "Result: $currentBuild.result"               // -> UNSTABLE
                    }
                }
            }

            post {
                always {
                    echo "CurrentResult: $currentBuild.currentResult" // -> UNSTABLE
                    echo "Result: $currentBuild.result"               // -> UNSTABLE
                                                                      // overall build result -> UNSTABLE
                }
            }
        }
    }
}

正如 fredericrous 所指出的,区别在于捕获的异常。 如果 Jenkinsfile 中没有捕获异常,那么结果将设置为 FAILED.

我不是专家,但我想出了一个纯声明式的方法来解决这个问题,以换取更混乱的 Jenkinsfile。

pipeline {
    agent any

    stages {
        stage('Build') {
            steps {
                catchError(buildResult: null, catchInterruptions: false) {
                    withMaven() {
                        sh 'mvn clean verify' // -> Tests run: 1, Failures: 1, Errors: 0, Skipped: 0
                    }
                }
            }

            post {
                always {
                    echo "CurrentResult: $currentBuild.currentResult" // -> UNSTABLE
                    echo "Result: $currentBuild.result"               // -> UNSTABLE
                }
            }
        }

        stage('Deploy') {
            when {
                expression {
                    currentBuild.result == "SUCCESS"
                }
            }
            steps {
                echo 'Deploy'
            }
        }
    }
}

说明

catchError(buildResult: null, catchInterruptions: false)

buildResult: null 等同于 buildResult: 'SUCCESS',阻止 catchError 将 buildResult 设置为 FAILURE,无论之前的值如何。

catchInterruptions: false 告诉 catchError 不要捕获或重新抛出某些类型的用于中断管道执行流程的异常。

捕获异常的“缺点”是执行当前和所有后续 stages。 要跳过有关结果的阶段,可以将 when 声明添加到阶段。

从舞台上看是这样的