liori
liori

Reputation: 42387

Jenkinsfile, send email when failure or improvement

I would like to send an email in the following situations:

So far I know I can write a post section with a failure condition, like:

pipeline {
    […]
    post {
        failure {
            emailext(
                to: '[email protected]',  // testing
                subject: "Status: ${currentBuild.result?:'SUCCESS'} - Job \'${env.JOB_NAME}:${env.BUILD_NUMBER}\'",
                body: """
                    <p>EXECUTED: Job <b>\'${env.JOB_NAME}:${env.BUILD_NUMBER}\'</b></p>
                    <p>View console output at "<a href="${env.BUILD_URL}"> ${env.JOB_NAME}:${env.BUILD_NUMBER}</a>"</p>"""
            )
        }
    }
}

and this handles the first part. But none of the other conditions available in the post section seem to match my intents: the only conditions that consider the past are changed, fixed and regression, but the first is too generic, fixed requires the run to be successful (and I also want unstable), and regression obviously goes in the wrong direction.

How can I do that?

Upvotes: 0

Views: 1006

Answers (2)

liori
liori

Reputation: 42387

A full solution I coded based on @Simon Martineau's answer, reading Groovy's tutorial, an answer on devops.SE, an answer on SO and documentation on currentBuild is as follows:

post {
    always {
        script {
            // see https://stackoverflow.com/a/59739297/42610 for details
            if (currentBuild.currentResult == 'ABORTED') {
                return
            }

            def previousBuild = currentBuild.previousBuild
            while(previousBuild != null && previousBuild.result == 'ABORTED') {
                echo "Skipping over an aborted build ${previousBuild.fullDisplayName}"
                previousBuild = previousBuild.previousBuild;
            }
            def isFailure = currentBuild.currentResult == 'FAILURE'
            def wasFailure = previousBuild.result == 'FAILURE'
            echo "Is: ${currentBuild.currentResult} (${isFailure})"
            echo "Was: ${previousBuild.result} (${wasFailure})"

            def status = null
            if (isFailure && !wasFailure) {
                status = 'New failure'
            } else if (isFailure) {
                status = 'Still failure'
            } else if (wasFailure) {
                status = 'Failure fixed'
            }

            if (status != null) {
                emailext(
                    to: '[email protected]',
                    subject: "${status}: Job \'${env.JOB_NAME}:${env.BUILD_NUMBER}\'",
                    body: """
                        <p>EXECUTED: Job <b>\'${env.JOB_NAME}:${env.BUILD_NUMBER}\'</b></p>
                        <p>Status: <b>${status}</b> (currently: ${currentBuild.currentResult}, previously: ${previousBuild.result})</p>
                        <p>View console output at "<a href="${env.BUILD_URL}">${env.JOB_NAME}:${env.BUILD_NUMBER}</a>"</p>"""
                )
            }
        }
    }
}

Upvotes: 1

Simon Martineau
Simon Martineau

Reputation: 31

I think you would need to switch from declarative pipeline to scripted pipeline to do what you want.

Interesting reference: Jenkins scripted pipeline or declarative pipeline

Don't forget that you don't need to switch the whole file. You can have a script block in a declarative pipeline.

See example 35 there: https://jenkins.io/doc/book/pipeline/syntax/

Upvotes: 1

Related Questions