Jenkins 管道:分阶段运行所有步骤,即使第一个步骤失败

时间:2021-07-01 22:29:45

标签: jenkins jenkins-pipeline

我想在一个阶段中执行一系列步骤,即使第一个步骤失败。我希望阶段结果失败并且构建被中止,但只有 所有步骤都运行后。例如,

pipeline {
    agent any
    stages {
        stage('Run Test') {
            steps {
                sh "echo running unit-tests"
                sh "echo running linting && false"  // failure
                sh "echo generating report"  // This should still run (It currently doesn't)
                publishCoverage adapters: [coberturaAdapter("coverage.xml")]  // This should still run (It currently doesn't)
                junit 'unit-test.xml'  // This should still run (It currently doesn't)
            }
        }
        stage('Deploy') {
            steps {
                echo "deploying"  // This should NOT run
            }
        }
    }
}

结果应该是构建失败,其中“运行测试”阶段失败而“部署”阶段未运行。这可能吗?

附言

要求与Continue Jenkins pipeline past failed stage中的行为相同。我想运行失败后的步骤,而不是之后的任何阶段。我尝试用 catchError (buildResult: 'FAILURE', stageResult: 'FAILURE') 将每个测试步骤括起来,但“部署”阶段仍在运行。

编辑:

我无法将所有步骤合并为一个大 sh 步骤并捕获其返回码,因为有些步骤不是 shell 命令,而是像 junitpublishCoverage 这样的 jenkins 步骤。

4 个答案:

答案 0 :(得分:0)

理论上你应该能够使用 sh "<command>||true" 它会忽略命令上的错误并继续。但是,Jenkins 不会失败,因为它会忽略错误。

如果您不希望 Jenkins 忽略错误并希望它在阶段结束时停止,您可以执行以下操作:sh "<command>||$error=true" 然后根据 $error 变量使构建失败. (sh "$error" 可能就足够了,但我不确定,最后可能需要一个 if 语句。)它只会设置为 true 如果 command 失败。

答案 1 :(得分:0)

具有非零退出代码的脚本将始终导致 jenkins 步骤失败。您可以将 returnStatus 用作 true,以便 jenkins 不会失败该步骤。
此外,考虑到您的用例,您可以使用 post always 执行,以便始终执行这些步骤。

请参阅以下参考示例:

stage('Run Test') {
            steps {
                def unit_test_result= sh returnStatus: true, script: 'echo "running unit-tests"'
                def lint_result= sh returnStatus: true, script: 'echo "running linting"'       
                if (unit_test_result!=0 || lint_result!=0 ) {
                   // If the unit_test_result or lint_result status is not 0 then mark this stage as unstable to continue ahead 
                   // and all later stages will be executed 
                   unstable ('Testing failed')
                   // You can also mark as failed as below and it will not conintue other stages:
                   // error ('Testing failed')
                   }
                
            }
           post {
                always {
                   // This block would always be executed inspite of failure
                    sh "echo generating report"
                publishCoverage adapters: [coberturaAdapter("coverage.xml")]
                junit 'unit-test.xml' 
                       }
                }
        }

答案 2 :(得分:0)

另一种选择是将构建步骤包装在 try-catch 块中!如果出现异常,即构建的返回代码不是 0,您可以捕获它,将构建标记为不稳定,然后管道的其余部分继续。

这是一个例子` 管道{

agent {
    node {
        label 'linux'
    }
}

options {
    timestamps()
    disableConcurrentBuilds()
    buildDiscarder(logRotator(numToKeepStr: '3'))
}

tools {
    maven 'Maven 3.6.3'
    jdk 'jdk11'
}

stages {

    stage('CleanWS') {
        steps {
            cleanWs()
        }
    }

  

    stage('Build') {
        steps {
            withMaven(options: [artifactsPublisher(disabled: true)]) {
                sh "export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn -f pom.xml clean install -DskipTests -Pregression-test  -Dmaven.javadoc.skip=true"
            }
        }
    }

    stage('Test') {
        steps {
            script {
                try {
                    withMaven(options: [artifactsPublisher(disabled: true)]) {
                        sh "export MAVEN_OPTS=\"-Xmx2048m\" && export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn -B verify   -Dmaven.source.skip=true -Dmaven.javadoc.skip=true"
                    }

                } catch (exc) {
                    currentBuild.result = 'UNSTABLE'
                }
            }
        }
        post {
            always {
                script {
                    junit "**/surefire-reports/*.xml"
                }
            }
        }
    }

    stage('Sonar Analyse') {
        steps {
            script {
                withMaven(options: [artifactsPublisher(disabled: true)]) {
                    withSonarQubeEnv("SonarQube") {
                        sh "export MAVEN_OPTS=\"-Xmx2048m\" && export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn sonar:sonar"
                    }
                }
            }
        }
    }

    stage('Deploy to Nexus') {
        steps {
            sh "export NLS_LANG=GERMAN_GERMANY.WE8ISO8859P1 && mvn -f pom.xml -B clean deploy -DdeployAtEnd=true -DskipTests"
        }
    }

}

post {
    failure {
        script {
            emailext(
                    body: "Please go to ${env.BUILD_URL}/console for more details.",
                    to: emailextrecipients([developers(), requestor()]),
                    subject: "Nightly-Build-Pipeline Status is ${currentBuild.result}. ${env.BUILD_URL}"
            )
        }
    }
    unstable {
        script {
            emailext(
                    body: "Please go to ${env.BUILD_URL}/console for more details.",
                    to: emailextrecipients([developers(), requestor()]),
                    subject: "Nightly-Build-Pipeline Build Status is ${currentBuild.result}. ${env.BUILD_URL}"
            )
        }
    }
}

}`

答案 3 :(得分:0)

我找到了一种获得我想要的行为的有点笨拙的方法。其他答案对我不起作用,要么是因为它们需要所有步骤都是 Generics 步骤,要么它们不会阻止 sh 阶段运行。我使用 deploy 来设置构建和暂存结果。但是为了防止下一个阶段运行,如果阶段失败,我需要显式调用 catchError

error