75

这是我正在玩的代码

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
    }
}

我有什么方法可以将“端到端测试”阶段标记为失败,而不会使整个工作失败?Propagate false 总是将阶段标记为 true,这不是我想要的,但 Propagate true 将工作标记为失败,我也不想要。

4

7 回答 7

55

这现在是可能的,即使使用声明性管道:

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 将显示为失败:

管道示例

正如您可能已经猜到的那样,您可以自由选择buildResultand stageResult,以防您希望它不稳定或其他任何东西。您甚至可以使构建失败并继续执行管道。

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

于 2019-07-10T16:45:22.900 回答
25

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
   }
}
于 2017-02-09T21:59:42.333 回答
14

听起来像JENKINS-26522。目前你能做的最好的就是设置一个整体结果:

if (result.equals("SUCCESS")) {
    stage 'deploy'
    build 'deploy'
} else {
    currentBuild.result = e2e.result
    // but continue
}
于 2016-04-26T18:53:43.140 回答
13

我最近尝试使用 vaza 的答案 Show a Jenkins pipeline stage as failed 而没有失败整个作业作为模板来编写一个函数,该函数在一个名为作业名称的自己的阶段执行作业。令人惊讶的是它起作用了,但也许一些 groovy 专家看看它:)

以下是其中一项作业被中止时的样子: 在此处输入图像描述

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')
}
于 2017-12-13T13:39:27.550 回答
4

为了在下游作业失败时显示带有失败阶段的成功构建并支持用户能够取消构建(包括所有后续阶段),我不得不使用各种解决方案的组合,特别是whentry/catchthrowcatchError()

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...
}
于 2020-11-25T18:39:30.813 回答
3

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

if (result.equals("SUCCESS")) {
   stage 'deploy'
   build 'deploy'
} else {
   try {
       sh "not exist command"
   }catch(e) {
   }
}
于 2016-06-16T08:25:59.210 回答
3

解决步骤

  • 您必须在阶段发出错误以将其标记为错误
  • 在 的范围之外stage,处理异常并选择构建状态
  • 这使得这里的几个用户想要的效果,包括我自己,@user3768904,@Sviatlana

失败步骤示例成功

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

在此处输入图像描述

因失败而中止步骤示例

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

在此处输入图像描述

于 2019-04-15T07:21:51.203 回答