How to know the 'changed' state of a Pipeline Model Definition based build?

40 views
Skip to first unread message

Tim Downey

unread,
Dec 7, 2016, 4:17:19 PM12/7/16
to Jenkins Users
Hi all,

Has anyone come to a satisfactory way to know the build status during pipeline model definition in terms of things like emailing on build state changes?  Nominally, we only want to email folks on failures and on build state changes, but I want the email to be able to say why the build state has changed.

With pipeline model definition, we can catch these events.  The problem is that we don't know why we received a changed {} state.  Here's a simple mvn build...

pipeline {
    agent label:'docker'

    stages {
        stage('maven-build') {
            steps {
                sh 'mvn clean install'
            }
        }
    }

    post {
        always {
            archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true                
            step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*.xml'])
        }

        changed {
            sendEmail(config, 'CHANGED')
        }

        failure {
            sendEmail(config, 'FAILURE')
        }
    }    
}

Inside of this, I want to email on 'changed', but I really want the email to say whether or not I changed from SUCCESS to FAILURE or from FAILURE to SUCCESS.  I can't figure out how to do this.  Both ${currentBuild.result} and ${currentBuild.rawBuild.result} are unset.  Is there some way to know what the state change was from?  Right now, I can email, but the email won't know whether or not the current state is pass or fail.

Thanks for any help.  I'm assuming that it's me since this seems like a lot of work for something that is a pretty default case.

Tim

Tim Downey

unread,
Dec 8, 2016, 9:36:56 AM12/8/16
to Jenkins Users
Ok....answering my own question in case others are facing this.  For a pretty typical use case, this shouldn't be this hard.  I'm still hoping that someone is able to point out something simple that I missing so that I can avoid jumping through these hoops.

Here's what I've got working for sending emails on only those builds that are FAILURE or those that are transitioning from FAILURE -> SUCCESS.  One other ugly bit is that if you're using the emailext plugin, most of the templates will normally use currentBuild.result.  That is never set during pipeline, so you'll either need to set it yourself, or change your templates to use something else.  I'm setting it here, but it's probably wiser to change the templates to avoid confusion.

#!/usr/bin/env groovy
def config = [emailRecipients: 'email@com', attachLog: false]

def buildStateHasChanged = false;

pipeline {
    agent label:'docker'

    stages {
        stage('maven-build') {
            steps {
                sh 'mvn clean install'
            }
        }
    }

    post {
        always {
            archiveArtifacts artifacts: '**/target/*.jar', fingerprint: true                
            step([$class: 'JUnitResultArchiver', testResults: '**/target/surefire-reports/TEST-*.xml'])
        }

        success {
            script {
                if (buildStateHasChanged == true) {
                    echo "Emailing for success because build state has changed..."
                    sendEmail(config, 'SUCCESS')
                }
            }
        }
        changed {
            echo "Build state has changed..."
            script {
                buildStateHasChanged = true
            }
        }

        failure {
            sendEmail(config, 'FAILURE')
        }
    }    
}

def sendEmail(config, status) {
    // We need to do this because the template uses it and it won't be set properly in pipeline
    currentBuild.result = status

    def subject = config.subject ? config.subject : "${env.JOB_NAME} - Build #${env.BUILD_NUMBER} - ${status}!"
    def content = '${SCRIPT,template="groovy-html-tim.template"}'
    def attachLog = config.attachLog != null ? config.attachLog : (status != "SUCCESS")

    def to = []
    to << emailextrecipients([[$class: 'RequesterRecipientProvider']])

    if (config.emailRecipients != null) {
        to << config.emailRecipients
    }

    if (status != "SUCCESS") {
        to << emailextrecipients([[$class: 'CulpritsRecipientProvider']])
    }

    to = to.join(',')

    emailext(body: content, mimeType:'text/html',
        replyTo: '$DEFAULT_REPLYTO',
        subject: subject,
        to: to,
        attachLog: attachLog)
}



Reply all
Reply to author
Forward
0 new messages