将Jenkins管道阶段显示为失败而不会使整个作业失败

时间:2016-04-25 22:36:33

标签: jenkins groovy jenkins-workflow jenkins-pipeline

这是我正在玩的代码

node {
    stage 'build'
    echo 'build'

    stage 'tests'
    echo 'tests'

    stage 'end-to-end-tests'
    def e2e = build job:'end-to-end-tests', propagate: false
    result = e2e.result
    if (result.equals("SUCCESS")) {
        stage 'deploy'
        build 'deploy'
    } else {
        ?????? I want to just fail this stage
    }
}

我有什么方法可以标记“端到端测试”和#39;在没有失败整个工作的情况下失败的阶段?传播虚假只是总是将舞台标记为真实,这不是我想要的,但是传播真实标志着失败的工作,我也不想要。

7 个答案:

答案 0 :(得分:21)

Stage现在占用一个块,所以将这个阶段包装在try-catch中。舞台内的Try-catch使它成功。

前面提到的新功能将更加强大。与此同时:

try {
   stage('end-to-end-tests') {
     node {      
       def e2e = build job:'end-to-end-tests', propagate: false
       result = e2e.result
       if (result.equals("SUCCESS")) {
       } else {
          sh "exit 1" // this fails the stage
       }
     }
   }
} catch (e) {
   result = "FAIL" // make sure other exceptions are recorded as failure too
}

stage('deploy') {
   if (result.equals("SUCCESS")) {
      build 'deploy'
   } else {
      echo "Cannot deploy without successful build" // it is important to have a deploy stage even here for the current visualization
   }
}

答案 1 :(得分:13)

听起来像JENKINS-26522。目前,您可以做的最好的事情是设置总体结果:

if (result.equals("SUCCESS")) {
    stage 'deploy'
    build 'deploy'
} else {
    currentBuild.result = e2e.result
    // but continue
}

答案 2 :(得分:10)

我最近尝试使用vaza的答案 Show a Jenkins pipeline stage as failed without failing the whole job作为模板,用于编写一个函数,该函数在类似于作业名称的自己的阶段中执行作​​业。令人惊讶的是它有效,但也许一些时髦的专家看看它:)

以下是其中一个作业被中止的情况: enter image description here

def BuildJob(projectName) {
    try {
       stage(projectName) {
         node {      
           def e2e = build job:projectName, propagate: false
           result = e2e.result
           if (result.equals("SUCCESS")) {
           } else {
              error 'FAIL' //sh "exit 1" // this fails the stage
           }
         }
       }
    } catch (e) {
        currentBuild.result = 'UNSTABLE'
        result = "FAIL" // make sure other exceptions are recorded as failure too
    }
}

node {
    BuildJob('job1')
    BuildJob('job2')
}

答案 3 :(得分:2)

您可以添加一个显式的失败任务,例如“sh”在阶段中不存在命令“”。

if (result.equals("SUCCESS")) {
   stage 'deploy'
   build 'deploy'
} else {
   try {
       sh "not exist command"
   }catch(e) {
   }
}

答案 4 :(得分:1)

解决步骤

  • 您必须在阶段中发出错误以将其标记为错误
  • let currentDateResult = currentDformatter.date(from: currentDformatter.string(from: currentDate)) 的范围之外,处理异常并选择构建状态
  • 这使此处的一些用户(包括我自己@ user3768904,@ Sviatlana)具有所需的效果

成功,但步骤示例失败

stage

enter image description here

由于失败而失败步骤示例

node("node-name") {
  try {
    stage("Process") {
      error("This will fail")
    }
  } catch(Exception error) {
    currentBuild.result = 'SUCCESS'
    return
  }
  stage("Skipped") {
     // This stage will never run
  }
}

enter image description here

答案 5 :(得分: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是最新的,因为这是一个相当新的功能。

答案 6 :(得分:1)

为了在下游作业失败时显示失败阶段的成功构建, AND 支持用户能够取消构建(包括所有后续阶段),我必须使用各种解决方案的组合,特别是何时 try / catch throw catchError()

env.GLOBAL_BUILD_ABORTED = false        // Set if the user aborts the build

pipeline {
    agent any

    stages {
        stage('First Stage') {
            when { expression { env.GLOBAL_BUILD_ABORTED.toBoolean() == false } }

            steps {
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    myLocalBuildMethod('Stage #1, build #1')
                    myLocalBuildMethod('Stage #1, build #2')
                }
            }
        }

        stage('Second Stage') {
            when { expression { env.GLOBAL_BUILD_ABORTED.toBoolean() == false } }

            steps {
                catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
                    myLocalBuildMethod('Stage #2, build #1')
                    myLocalBuildMethod('Stage #2, build #2')
                    myLocalBuildMethod('Stage #2, build #3')
                }
            }
        }
    }
}

def myLocalBuildMethod(myString) {
    /* Dummy method to show User Aborts vs Build Failures */

    echo "My Local Build Method: " + myString

    try {
        build (
            job: "Dummy_Downstream_Job"
        )

    } catch (e) {
        /* Build Aborted by user - Stop All Test Executions */
        if (e.getMessage().contains("was cancelled") || e.getMessage().contains("ABORTED")) {

            env.GLOBAL_BUILD_ABORTED = true
        }
        /* Throw the execiption to be caught by catchError() to mark the stage failed. */
        throw (e)
    }

    // Do other stuff...
}