Jenkins Pipeline + Slack

Para el desarrollo de Get-On usamos varias herramientas muy copadas, pero estamos enamorados especialmente de dos: Jenkins y Slack.

Hace un tiempo hicimos el upgrade a la versión 2.x de Jenkins y empezamos a usar el pipeline y su famoso Jenkinsfile . Hasta ahí, todo iba perfecto, hasta que caímos en la cuenta que cuando un build fallaba, no nos avisaba en nuestro canal de Slack. Ni tampoco nos avisaba cuando arreglábamos el problema.

Y no había nadie a quien culpar, solo que nuestro Jenkinsfile era muy básico.

Notificar algo por Slack desde el Jenkinsfile es algo realmente fácil. Lo que no es tan fácil es que te avise solamente si cambió el estado del build (se rompió o se volvió a arreglar, o fallaron los tests que no venían fallando, etc). Y eso es lo que queríamos lograr.

Creamos un archivo slack.groovy que luego vamos a cargar y a consumir desde el Jenkinsfile. La única magia, es que en el mustNotify pregunta si hay algún cambio entre el  build actual y el resultado del anterior.

slack.groovy

def getLastBuildStatus() {
    return currentBuild.rawBuild.getPreviousBuild()?.getResult().toString()
}

def notifyToSlack(String buildStatus = 'STARTED') {
    buildStatus =  buildStatus ?: 'SUCCESS'
    if (mustNotify(buildStatus)) {
        def color = getColorByStatus(buildStatus)
        slackSend(message: "${env.JOB_NAME} - #${env.BUILD_NUMBER} - ${buildStatus}",
                channel: "#your-channel", color: color, token: "yourToken")
        return
    }
    echo "No debe notificar por Slack"
}

def getColorByStatus(String buildStatus = 'STARTED') {
    if (buildStatus == 'STARTED') {
        //amarillo
        colorCode = '#FFFF00'
    } else if (buildStatus == 'SUCCESS') {
        //verde
        colorCode = '#00FF00'
    } else {
        //rojo
        colorCode = '#FF0000'
    }
    return colorCode;
}

def mustNotify(String buildStatus) {
    def lastBuildStatus = getLastBuildStatus()
    return !buildStatus.equals(lastBuildStatus)
}

return this

Y en el Jenkinsfile directamente lo consumimos de esta manera

Jenkinsfile

#!groovy

stage 'build and tests'

def project
def slack

node {
    def workspace = pwd()
    slack   = load "${workspace}@script/slack.groovy"
    project = load "${workspace}@script/project.groovy"

    try {
        //get things done
    } catch (e) {
        currentBuild.result = "FAILED"
        throw e
    } finally {
        slack.notifyToSlack(currentBuild.result)
    }
}

Y ya con eso solamente, logramos el anhelado deseo de obtener notificaciones solamente cuando el estado cambia. También podés verlo en este Gist.

Vale mencionar que este fragmento de código nos sirvió mucho también.

PD: perdón por los magic strings

[starbox]