显示 Jenkins 的输油管道阶段失败了,而不是整个工作都失败了

这是我玩的代码

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

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

130974 次浏览

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

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

您可以在 stage 中添加一个显式的失败任务,比如“ sh“ not alive command”。

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

现在阶段需要一个块,所以包装阶段在尝试捕捉。尝试捕捉内的阶段使它成功。

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

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

我最近试图使用瓦扎的回答 将 Jenkins 流水线阶段显示为失败,但不要将整个作业 作为模板来编写一个函数,该函数在名为作业名称的自己的阶段中执行作业。令人惊讶的是,它确实起作用了,但也许一些时髦的专家会看一看:)

下面是其中一个作业被中止时的情况: 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')
}

解决步骤

  • 您必须在某个阶段中发出一个错误,以将其标记为错误
  • 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
}
}

enter image description here

由于失败而中止步骤示例

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

enter image description here

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

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 是最新的,因为这是一个相当新的功能。

为了显示一个成功的构建与失败的阶段,当下游作业失败时,支持用户能够取消构建(包括所有后续阶段) ,我必须使用各种解决方案的组合,特别是 什么时候尝试/接住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...
}

可以在 else 语句中使用以下代码:

catchError(buildResult: 'SUCCESS', stageResult: 'FAILURE') {
error "some err msg"
}

这可以是一个通用模式,显示如何使用内置函数使用漂亮的消息定制阶段结果,并将子作业的结果传播到阶段结果。如果一个子作业不成功,那么整个构建就会显得不稳定,这只是这个例子的一个实现选择。

def run_sub_job() {
def jobBuild = build(job: 'foo', wait: true, propagate: false)
def result = jobBuild.getResult()
def msg = 'sub-job: ' + result
if ('SUCCESS' == result) {
println(msg)
} else if ('UNSTABLE' == result) {
unstable(msg) // will also set buildResult to UNSTABLE
} else { // anything else (FAILURE, ABORTED ...) is considered an error
catchError(
buildResult: 'UNSTABLE',
stageResult: result // propagate sub-job result
) {
error(msg)
}
}
}