如何继续使用Jenkins声明性管道语法中的失败阶段

时间:2017-07-10 21:09:22

标签: jenkins jenkins-pipeline jenkins-declarative-pipeline

我想在Jenkins声明性管道语法中定义多个阶段,这些阶段可以继续通过其中任何一个失败。我找不到任何真正重复的问题,因为它们都假设或允许脚本语法。

pipeline {
    agent any
    stages {
        stage('stage 1') {
            steps {
                echo "I need to run every time"
            }
        }
        stage('stage 2') {
            steps {
                echo "I need to run every time, even if stage 1 fails"
            }
        }
        stage('stage 3') {
            steps {
                echo "Bonus points if the solution is robust enough to allow me to continue *or* be halted based on previous stage status"
            }
        }
    }
}

为了澄清,我没有在脚本语法中寻找如何做到这一点。我试图了解这种流控制是否实际上是在声明性语法中支持和形式化的。为此,我将尝试准确定义我正在寻找的内容:

必需

  • 没有尝试/捕获。我不想进入脚本模式,或者#34; wrap"我在另一个共享库或脚本块中的声明性管道。
  • 没有post step恶作剧。我想要真正的多个阶段,而不是一个包含我所有其他逻辑的post always步骤的阶段

可选

  • 失败的阶段应被视为失败;我不希望失败的舞台显示为绿色,因为它是"跳过"或者"继续"。
  • 任何失败阶段的构建应标记为红色(或黄色,或任何非绿色)。

相关但不充分

4 个答案:

答案 0 :(得分:3)

我可能遗漏了一些东西,但声明性的,固定的管道的想法是提供对大多数简单用例的报道。 当你需要自以为是的没有涉及的东西时,你必须求助于脚本管道,这只是指“声明性管道”的“要求”:现在不会发生。

至于你的其他“要求”,它们没有多大意义,因为整个想法是将低级丑陋包含在共享库中,为用户提供如下构造:

    mylib.failable_stages({
      stages {
        stage('stage 1') {
          steps {
            echo "I need to run every time"
          }
        }
        stage('stage 2') {
          steps {
            echo "I need to run every time, even if stage 1 fails"
          }
        }
        stage('stage 3') {
          steps {
            echo "Bonus points if the solution is robust enough to allow me to continue *or* be halted based on previous stage status"
          }
        }
      }
    })

当然,你必须找到或实现这样的mylib类,failable_stages将获得一个闭包,并将其包装在各种管道/样板代码中。

希望这有用。

答案 1 :(得分:1)

现在可以:

pipeline {
    agent any
    stages {
        stage('1') {
            steps {
                sh 'exit 0'
            }
        }
        stage('2') {
            steps {
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    sh "exit 1"
                }
            }
        }
        stage('3') {
            steps {
                sh 'exit 0'
            }
        }
    }
}

在上面的示例中,所有阶段都将执行,管道将成功,但是阶段2将显示为失败:

Pipeline Example

您可能已经猜到了,可以随意选择buildResultstageResult,以防不稳定或其他原因。您甚至可以使构建失败并继续执行管道。

只需确保您的Jenkins是最新的,因为这是一个相当新的功能。

编辑:这是此答案的初衷。对于其他一些问题,这也是正确的答案,这就是为什么我也在此处发布此答案的原因。这是解决多个类似问题的正确方法。我已经针对他们的具体问题量身定制了其他答案,以使其清楚。我只是复制答案以节省时间。这并不意味着它不是一个正确的答案。

答案 2 :(得分:0)

我认为这取决于工作彼此之间的依赖程度。从您的示例得出,我认为

  • 阶段1 独立于所有其他阶段,因为它是第一个
  • 阶段2 与所有其他阶段均独立,因为阶段1 可能会立即失败,并且仍然需要运行阶段2
  • 阶段3 取决于阶段1 阶段2
  • 的结果

因此对应的管道可能是

pipeline {
    stages {
        stage('Independent tasks') {
            parallel {
                stage('stage 1') {
                    steps {
                        sh 'exit 1' // failure
                    }
                }
                stage('stage 2') {
                    steps {
                        echo 'Happens even so stage 1 fails'
                        sh 'exit 0' // success
                    }
                }
            }
            post {  // 'stage 3'
                failure {
                    echo "... at least one failed"
                }
                success {
                    echo "Success!"
                }
            }
        }
        stage ('stage 4') {
            steps {
                echo 'Happens only if all previous succeed'
            }
        }
    }
}

阶段1 阶段2 将始终运行,阶段3 对它们的成功/失败进行反应。


其他思想:此概念仅在管道的“末端”起作用。如果您需要在中间某个地方并且必须继续进行构建,则可以将其移至自己的工作中并使用build job插件。

pipeline {
    stages {
    stage('Start own job for stage 1, 2, 3') {
        steps {
            build job: 'stageOneTwoThree', propagate: false, wait: true
        }
    }
    stage ('stage 4') {
        steps {
            echo 'Happens always, because "propagate: false"'
        }
    }
}

答案 3 :(得分:0)

我使用post实现了它。我的要求是无论构建状态如何,都发送松弛通知。

@Library('instanceGroups')
import x.z.y.jenkins.libraries.SlackNotifier

def slackHelper = new x.z.y.jenkins.libraries.SlackNotifier(env)
final String projectName = "pomeranian"
final String featureBranchPattern = "f_"

pipeline {
    agent any
    options { disableConcurrentBuilds() }

    stages {
        stage('clean') {
            steps {
                script {
                    try {
                        echo 'Current Branch...' + env.BRANCH_NAME
                        sh 'rm -rf /var/lib/jenkins/.gradle/caches'
                        sh './gradlew clean'
                    } catch (e) {
                        currentBuild.result = 'FAILURE'
                        slackHelper.buildGenericJobFailureNotificationMessage()
                        throw e
                    }
                }
            }
        }

        stage('compile') {
            steps {
                script {
                    try {
                        sh "./gradlew compileJava"
                    } catch (e) {
                        currentBuild.result = 'FAILURE'
                        slackHelper.getCompilationFailureSlackNotificationMessage()
                        throw e
                    }
                }
            }
        }

        stage('test') {
            steps {
                script {
                    try {
                        sh "./gradlew test"
                    } finally {
                        junit 'build/test-results/test/*.xml'

                        slackHelper.getTestStatuses(currentBuild)
                        slackHelper.buildUnitTestSlackNotificationMessage()
                    }
                }
            }
        }

        stage('publish 2 nexus') {
            steps {
                script {
                  // some code
                }
            }
        }

        stage('git tagging') {
            steps {
                script {
                    // some more code...
            }
        }
    }


    post {
        always {
            script {
                slackHelper.finalBuildStatusMessage(currentBuild)
                slackSend(channel: '#ci-cd', attachments: slackHelper.getFinalSlackMessage())
            }
        }
    }
}