Abort current build from pipeline in Jenkins

后端 未结 7 1358
时光说笑
时光说笑 2020-12-02 13:06

I have a Jenkins pipeline which has multiple stages, for example:

node(\"nodename\") {
  stage(\"Checkout\") {
    git ....
  }
  stage(\"Check Preconditions         


        
相关标签:
7条回答
  • 2020-12-02 13:19

    After some testing I came up with the following solution:

    def autoCancelled = false
    
    try {
      stage('checkout') {
        ...
        if (your condition) {
          autoCancelled = true
          error('Aborting the build to prevent a loop.')
        }
      }
    } catch (e) {
      if (autoCancelled) {
        currentBuild.result = 'ABORTED'
        echo('Skipping mail notification')
        // return here instead of throwing error to keep the build "green"
        return
      }
      // normal error handling
      throw e
    }
    

    This will result into following stage view:

    failed stage

    If you don't like the failed stage, you have to use return. But be aware you have to skip each stage or wrapper.

    def autoCancelled = false
    
    try {
      stage('checkout') {
        ...
        if (your condition) {
          autoCancelled = true
          return
        }
      }
      if (autoCancelled) {
        error('Aborting the build to prevent a loop.')
        // return would be also possible but you have to be sure to quit all stages and wrapper properly
        // return
      }
    } catch (e) {
      if (autoCancelled) {
        currentBuild.result = 'ABORTED'
        echo('Skipping mail notification')
        // return here instead of throwing error to keep the build "green"
        return
      }
      // normal error handling
      throw e
    }
    

    The result:

    custom error as indicator

    You can also use a custom message instead of a local variable:

    final autoCancelledError = 'autoCancelled'
    
    try {
      stage('checkout') {
        ...
        if (your condition) {
          echo('Aborting the build to prevent a loop.')
          error(autoCancelledError)
        }
      }
    } catch (e) {
      if (e.message == autoCancelledError) {
        currentBuild.result = 'ABORTED'
        echo('Skipping mail notification')
        // return here instead of throwing error to keep the build "green"
        return
      }
      // normal error handling
      throw e
    }
    
    0 讨论(0)
  • 2020-12-02 13:26

    You can go to the script console of Jenkins and run the following to abort a hung / any Jenkins job build/run:

    Jenkins .instance.getItemByFullName("JobName")
            .getBuildByNumber(JobNumber)
            .finish(hudson.model.Result.ABORTED, new java.io.IOException("Aborting build"));
    
    0 讨论(0)
  • 2020-12-02 13:32

    Following this documentation from Jenkins, you should be able to generate an error to stop the build and set the build result like this:

    currentBuild.result = 'ABORTED'

    Hope that helps.

    0 讨论(0)
  • 2020-12-02 13:35

    Inspired by all the answers I have put all the stuff together into one Scripted Pipeline. Keep in mind this is not a Declarative Pipeline.

    To get this example working you will need:

    • QuickFIX form this answer Jenkins CI Pipeline Scripts not permitted to use method groovy.lang.GroovyObject
    • discord notifier plugin - https://plugins.jenkins.io/discord-notifier/
    • Discord channel webhook url filled in the code

    The idea I had was to abort the pipeline if it is "replayed" vs started by "run button"(in branches tab of Jenskins BlueOcean):

    def isBuildAReplay() {
      // https://stackoverflow.com/questions/51555910/how-to-know-inside-jenkinsfile-script-that-current-build-is-an-replay/52302879#52302879
      def replyClassName = "org.jenkinsci.plugins.workflow.cps.replay.ReplayCause"
      currentBuild.rawBuild.getCauses().any{ cause -> cause.toString().contains(replyClassName) }
    }
    
    node { 
            try {
                    stage('check replay') {
                        if (isBuildAReplay()) {
                            currentBuild.result = 'ABORTED'
                            error 'Biuld REPLAYED going to EXIT (please use RUN button)'
                        } else {
                            echo 'NOT replay'
                        }
                    }
                    stage('simple stage') {
                        echo 'hello from simple stage'
                    }
                    stage('error stage') {
                        //error 'hello from simple error'
                    }
                    stage('unstable stage') {
                        unstable 'hello from simple unstable'
                    }
                    stage('Notify sucess') {
                        //Handle SUCCESS|UNSTABLE
                        discordSend(description: "${currentBuild.currentResult}: Job ${env.JOB_NAME} \nBuild: ${env.BUILD_NUMBER} \nMore info at: \n${env.BUILD_URL}", footer: 'No-Code', unstable: true, link: env.BUILD_URL, result: "${currentBuild.currentResult}", title: "${JOB_NAME} << CLICK", webhookURL: 'https://discordapp.com/api/webhooks/')
    
                    }
    
            } catch (e) {
                    echo 'This will run only if failed'
    
                    if(currentBuild.result == 'ABORTED'){
                        //Handle ABORTED
                        discordSend(description: "${currentBuild.currentResult}: Job ${env.JOB_NAME} \nBuild: ${env.BUILD_NUMBER} \nMore info at: \n${env.BUILD_URL}\n\nERROR.toString():\n"+e.toString()+"\nERROR.printStackTrace():\n"+e.printStackTrace()+" ", footer: 'No-Code', unstable: true, link: env.BUILD_URL, result: "ABORTED", title: "${JOB_NAME} << CLICK", webhookURL: 'https://discordapp.com/api/webhooks/')
                        throw e
                    }else{
                        //Handle FAILURE
                        discordSend(description: "${currentBuild.currentResult}: Job ${env.JOB_NAME} \nBuild: ${env.BUILD_NUMBER} \nMore info at: \n${env.BUILD_URL}\n\nERROR.toString():\n"+e.toString()+"\nERROR.printStackTrace():\n"+e.printStackTrace()+" ", footer: 'No-Code', link: env.BUILD_URL, result: "FAILURE", title: "${JOB_NAME} << CLICK", webhookURL: 'https://discordapp.com/api/webhooks/')
                        throw e
                    }
            } finally {
                    echo 'I will always say Hello again!'
    
            }
    }
    

    Main trick was the order of lines to achive abort state:

    currentBuild.result = 'ABORTED'
    error 'Biuld REPLAYED going to EXIT (please use RUN button)'
    

    First set the state then throw an exception.

    In the catch block both work:

    currentBuild.result
    currentBuild.currentResult
    
    0 讨论(0)
  • 2020-12-02 13:37

    The thing that we use is:

    try {
     input 'Do you want to abort?'
    } catch (Exception err) {
     currentBuild.result = 'ABORTED';
     return;
    }
    

    The "return" at the end makes sure that no further code is executed.

    0 讨论(0)
  • 2020-12-02 13:42

    You can mark the build as ABORTED, and then use the error step to cause the build to stop:

    if (!continueBuild) {
        currentBuild.result = 'ABORTED'
        error('Stopping early…')
    }
    

    In the Stage View, this will show that the build stopped at this stage, but the build overall will be marked as aborted, rather than failed (see the grey icon for build #9):

    0 讨论(0)
提交回复
热议问题