Joosep Simm
Joosep Simm

Reputation: 472

How to send notifications in Jenkins pipeline when build recovers?

I want to send notifications from my Jenkins pipeline build when the job recovers. Meaning when the current build is successful and the last build was erroneous (failed, aborted etc).

I know how to send notifications. I think my question boils down to how to check the status of the previous build, but I might be mistaken.

I have tried "currentBuild.rawBuild.getPreviousBuild()?.getResult()", but got exception "org.jenkinsci.plugins.scriptsecurity.sandbox.RejectedAccessException: Scripts not permitted to use method org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper getRawBuild". If I turn sandbox off, it should work. Would it be possible with the sandbox?

Upvotes: 16

Views: 17522

Answers (6)

Still Learning Guy
Still Learning Guy

Reputation: 111

macg33zr gave a good answer. In the meanwhile, there is an even simpler way to perform some steps in a declarative pipeline after pipeline recovery: There is a new fixed condition in the post section. The post steps in the fixed condition section are only run "if the current Pipeline’s or stage’s run is successful and the previous run failed or was unstable." (see Jenkins' declarative pipeline documentation for details).

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                echo 'Do Something that could fail the pipeline.'
            }
        }
    }
    post { 
        fixed { 
            echo 'Build is back to normal!'
        }
    }
}

If you like to send notifications, there are several Jenkins plugins, for Slack for example. The notification code for Slack would look like this.

pipeline {
    agent any
    stages {
        stage('Build') {
            steps {
                echo 'Do Something that could fail the pipeline.'
            }
        }
    }
    post { 
        fixed { 
            slackSend channel: '#your-slack-target-channel',
                  color: 'good',
                  message: "The build is back to normal. :sweat_smile: The build _${currentBuild.fullDisplayName}_ was successful again.\nGo to pipeline: ${env.BUILD_URL}"
        }
    }
}

Upvotes: 0

Ras
Ras

Reputation: 547

Attached documentation will help:

Pipeline Ref Card

Upvotes: 0

Kolky
Kolky

Reputation: 2977

I've found another working solution, which doesn't require you to manually keep track of your build result. Although, it requires use of a script element :(

pipeline {
  agent any
  post {
    success {
      script {
        if (currentBuild.getPreviousBuild() && 
            currentBuild.getPreviousBuild().getResult().toString() != "SUCCESS") {
          echo 'Build is back to normal!'
        }
      }
    }
  }
}

Upvotes: 24

Jonas Masalskis
Jonas Masalskis

Reputation: 1256

Alternatively, you could move your script logic outside of the pipeline (ideally - to Jenkins shared pipeline library to be re-usable & keep the pipeline clean) so you wouldn't need the script block:

def sendNotification(buildStatus) {
  if (buildStatus != 'SUCCESS') {
    // Do nothing - only interested when status becomes GREEN
    return
  }

  mattermostSend "${env.JOB_NAME} has recovered! (<${env.BUILD_URL}|See the build>)"
}

pipeline {
  ...

  post {
    changed {
      sendNotification(currentBuild.currentResult)
    }
  }
}

Upvotes: 3

Alex
Alex

Reputation: 2649

similar to answer by @Kolky, this would be the snippet for "Scripted pipeline", where you use " node{ stage1... stage2... etc }":

    stage('Email') {
        if (currentBuild.getPreviousBuild().getResult().toString() != "SUCCESS") {
            echo 'Build is back to normal!'
            stage('Send build recovered email') {
                mail body: 'My build back to successful',
//                    from: '', replyTo: '',
                        subject: 'My build back to successful',
                        to: '[email protected]'
            }

        }
    }

Upvotes: 4

macg33zr
macg33zr

Reputation: 1805

Interesting question. You can do it in Jenkins declarative pipeline using the 'changed' part of a post{} section. But you will need to set currentBuild.result to SUCCESS or FAILURE in the job and check it in the post section. There does not seem to be an easy way to get the current build status (fail, success etc) as far as Jenkins is concerned without tracking it in your pipeline - unless I have missed something subtle. Here is an example, you would send the notification in the changed section where it checks for SUCCESS:

pipeline {
    agent any

    parameters {
        string(name: 'FAIL',     defaultValue: 'false', description: 'Whether to fail')
    }

    stages {
        stage('Test') {

            steps {

                script {

                    if(params.FAIL == 'true') {
                        echo "This build will fail"
                        currentBuild.result = 'FAILURE'
                        error("Build has failed")
                    }
                    else {
                        echo "This build is a success"
                        currentBuild.result = 'SUCCESS'
                    }

                }
            }
        }
    }

    post {
        always  {
            echo "Build completed. currentBuild.result = ${currentBuild.result}"
        }

        changed {
            echo 'Build result changed'

            script {
                if(currentBuild.result == 'SUCCESS') {
                    echo 'Build has changed to SUCCESS status'
                }
            }
        }

        failure {
            echo 'Build failed'
        }

        success {
            echo 'Build was a success'
        }
        unstable {
            echo 'Build has gone unstable'
        }
    }
}

--Bill

Upvotes: 12

Related Questions