109

I have a job that will create files, unless one of the values being fed to it matches an older value. What's the cleanest way in Jenkins to abort or exit the job, without it being FAILED? It exiting is the correct behavior so I want the build marked SUCCESS.

It'll end up in an if statement like so;

stage ('Check value') {

     if( $VALUE1 == $VALUE2 ) {
       //if they do match exit as a success, else continue with the rest of the job 
    }

}

I don't want to throw an error code unless that can somehow translate into it being marked a successful build.

7
  • 1
    Just exit 0...
    – Tensibai
    Commented Apr 13, 2017 at 15:33
  • 1
    I thought that marked the job a failure? If I'm wrong and you can show documentation, I'd be happy to accept that as an answer
    – Alex
    Commented Apr 13, 2017 at 15:35
  • Well, just bash scripts, exit 0 means success, exit non zero means failure...
    – Tensibai
    Commented Apr 13, 2017 at 15:36
  • 2
    This isn't within a bash script, this is the pipeline job itself, so Groovy. Does that change things?
    – Alex
    Commented Apr 13, 2017 at 15:36
  • In groovy I'd just try a return 0, all in all any end of the groovy code which doesn't throw an exception should do I think. I'll let someone with more background on jenkins 2 confirm or infirm
    – Tensibai
    Commented Apr 13, 2017 at 16:04

6 Answers 6

97

Please note: The following works for scripted pipelines only. For a solution for declarative pipelines see @kgriffs' answer.

---

Figured it out. Outside of any stages (otherwise this will just end the particular stage as a success) do the following;

if( $VALUE1 == $VALUE2 ) {
   currentBuild.result = 'SUCCESS'
   return
}

return will stop the stage or node you're running on which is why running it outside of a stage is important, while setting the currentBuild.result prevents it from failing.

9
  • just returning should leave the build with a grayed out status and no result... so not quite the same as a failed build.
    – drewish
    Commented Oct 28, 2017 at 18:47
  • 3
    How do you return and skip all remaining stages? Commented Nov 13, 2017 at 22:30
  • 2
    @JessBowers it's all about where you put the snippet. If you do it node-level rather than stage-level it'll finish the entire job.
    – Alex
    Commented Nov 14, 2017 at 13:52
  • 9
    Please note that it works only for scripted pipeline, not for declarative Commented Mar 28, 2018 at 11:01
  • 3
    @kagarlickij - Correct, declarative pipelines didn't exist when this answer was written!
    – Alex
    Commented Mar 28, 2018 at 12:34
26

The Executor.interrupt(Result) method is the cleanest, most direct way I could find to stop a build prematurely and mark it as a success.

script {
    currentBuild.getRawBuild().getExecutor().interrupt(Result.SUCCESS)
    sleep(1)   // Interrupt is not blocking and does not take effect immediately.
}

Pros:

  • Works in a declarative pipeline just as well as a scripted one.
  • No try/catch or exceptions to handle.
  • Marks the calling stage and any successive stages as green/passing in the UI.

Cons:

  • Requires a number of in-process script approvals, including one that is considered insecure. Approve and use with caution.
6
  • For me it doesn't work - consecutive stages are being executed.
    – Łukasz K
    Commented Oct 30, 2019 at 7:55
  • Can you put this before a stage in a declarative pipeline?
    – peetasan
    Commented Jan 16, 2020 at 16:21
  • In a declarative pipeline, script blocks are valid only inside of a stage's steps block. If you need to stop execution as described before a given stage, you will need to execute the script during a preceding stage.
    – Ben Amos
    Commented Jan 16, 2020 at 22:30
  • 2
    org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild
    – Devaroop
    Commented Feb 6, 2020 at 8:32
  • 4
    Yes, that is what I referred to in my "Cons" section.
    – Ben Amos
    Commented Feb 11, 2020 at 0:16
23

You can also use error to exit the current stage, then you don't have to consider the current stage hierarchy and similar stuff:

def autoCancelled = false

try {
  stage('checkout') {
    ...
    if (your condition) {
      autoCancelled = true
      error('Aborting the build.')
    }
  }
} catch (e) {
  if (autoCancelled) {
    currentBuild.result = 'SUCCESS'
    // return here instead of throwing error to keep the build "green"
    return
  }
  // normal error handling
  throw e
}

But this would lead to a red stage, if the error occurs within a stage.

enter image description here

It depends on your requirements, which way you want to use.

2
  • 1
    If you're going to do it this way, make a new subclass of RuntimeException to throw instead of needing to catch all exceptions and check a flag Commented Oct 15, 2018 at 16:24
  • I could not get this to work with Jenkins 2.263.3. WorkflowScript: 23: Expected a stage at the line with the try and after that: WorkflowScript: 22: No stages specified Commented Apr 26, 2021 at 18:23
13

If it is acceptable to set the build status to ABORTED instead of SUCCESS, the following snippet may be used within a pipeline stage to short-circuit the build:

steps {
    script {
        currentBuild.result = 'ABORTED'
        error("Aborting the build.")
    }
}

I tested setting the result to SUCCESS, but doing so resulted in a failed build (using Jenkins 2.235.5). It seems that ABORTED is respected by the error step, while SUCCESS is overridden.

4

I was almost able to accomplish this with declarative pipeline. This allows you to exit the before the pipeline starts based on the outcome of a shell script. I was not able to get this working within the pipeline itself (either within or between stages).

node('master'){
    env.status_code = sh(script: 'exit 0 # or 200 or other', returnStatus:true)
}
println 'status_code: ' + env.status_code
if(env.status_code == '200'){
    println 'Now is not the time to run the pipeline.'
    println 'Exiting without running subsequent stages.'
    currentBuild.result = 'SUCCESS'
    return
} else if(env.status_code == '0'){
    println 'Time to run. Let\'s go!'
} else {
    error 'Unable to check if it\'s time to run.'
}

pipeline {
  agent any
  stages {
      stage('Run only if exit status for was 0'){
          steps{
             sh 'echo hi'
          }
      }
  }
}

when directive may help if you only want to skip certain stages, not exit entirely.

https://www.jenkins.io/doc/book/pipeline/syntax/#when

1

Honestly you shouldn't need to use the exit command specifically, but there is a Conditional BuildStep Plugin which may achieve the same end result (code that doesn't run).

I haven't come up against this yet, so haven't used the plugin.

There is also conditionals as found in this prior Stack Overflow post on Jenkins: Jenkins Pipeline Conditional Step/Stage

5
  • 2
    While your answer seems to be valid (haven't checked it live since I found another workaround), I don't think "Honestly you shouldn't exit" is a good way to start it; clearly the existence of these methods means it IS sometimes necessary to exit.
    – Alex
    Commented Apr 15, 2017 at 0:18
  • What would you suggest? Moving to an ending statement? Adding the qualifier "generally"? You've provided "feedback" but it's not easy for me to tell the intent or action it, please be less terse.
    – MrMesees
    Commented Apr 16, 2017 at 19:57
  • Hang on a bit. Is it your question? If it is, TBH you wouldn't want to hear you shouldn't exit, but neither method I've suggested provide exits, they circumvent code running... Directly supporting my position.
    – MrMesees
    Commented Apr 16, 2017 at 20:15
  • 2
    Ahh I see, I think I misinterpreted your statement as "doing something to end the job is bad" instead of "you shouldn't use the literal exit command" - if so I apologize, that's my misunderstanding.
    – Alex
    Commented Apr 16, 2017 at 23:34
  • 4
    I've tried to make it clearer, no need to apologize at all, language is a fickle beast, especially on the internet :)
    – MrMesees
    Commented Apr 17, 2017 at 8:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.