Show a Jenkins pipeline stage as failed without failing the whole job

对着背影说爱祢 提交于 2019-11-27 12:01:37

Stage takes a block now, so wrap the stage in try-catch. Try-catch inside the stage makes it succeed.

The new feature mentioned earlier will be more powerful. In the meantime:

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

Sounds like JENKINS-26522. Currently the best you can do is set an overall result:

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

I recently tried to use vaza's answer Show a Jenkins pipeline stage as failed without failing the whole job as template for writing a function that excutes a job in an own stage named like the job name. Surprisingly it worked, but maybe some groovy experts have a look at it :)

Here is how it looks like if one of the jobs is aborted:

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

You could add a explicit fail task, such as 'sh "not exist command"' in the stage.

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

Solution steps

  • You must emit an error in a stage to mark it as an error
  • Outside the scope of the stage, handle the exception and choose the build status
  • This makes the effect desired by a couple of users here, including myself, @user3768904, @Sviatlana

Success with failed Step Example

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

Aborted with failure Step Example

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

This is now possible, even with declarative pipelines:

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

In the example above, all stages will execute, the pipeline will be successful, but stage 2 will show as failed:

As you might have guessed, you can freely choose the buildResult and stageResult, in case you want it to be unstable or anything else. You can even fail the build and continue the execution of the pipeline.

Just make sure your Jenkins is up to date, since this is a fairly new feature.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!