37 votes

Utiliser Jenkins 'Mailer' dans le workflow du pipeline

J'aimerais profit de l' Expéditeur plugin Jenkins dans un Jenkinsfile qui définit un pipeline de travail. Compte tenu de l'suivantes simple erreur de script je m'attends à un e-mail à chaque génération.

#!groovy

stage 'Test'
node {
    try {
        sh 'exit 1'
    } finally {
        step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: 'me@me.com', sendToIndividuals: true])
    }
}

La sortie de la compilation est:

Started by user xxxxx
[Pipeline] stage (Test)
Entering stage Test
Proceeding
[Pipeline] node
Running on master in /var/lib/jenkins/jobs/rpk-test/workspace
[Pipeline] {
[Pipeline] sh
[workspace] Running shell script
+ exit 1
[Pipeline] step
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
ERROR: script returned exit code 1
Finished: FAILURE

Comme vous pouvez le voir, il n'enregistrer qu'il effectue le pipeline step immédiatement après l'échec, mais pas de courriels se produit.

E-mails dans d'autres free-style emplois qui tirent parti de la mailer beau travail, tout en invoquant via des travaux de canalisation.

C'est en cours d'exécution avec Jenkins 2.2 et mailer 1.17.

Est-il un autre mécanisme par lequel je devrais être en invoquant échec lors de la construction des e-mails? Je n'ai pas besoin de tous les frais généraux de l' mail étape, il faut juste les notifications sur les échecs et les recouvrements.

64voto

izzekil Points 156

Dans le Pipeline a échoué sh n'est pas immédiatement l' currentBuild.result de FAILURE alors que sa valeur initiale est null. Donc créer des étapes qui dépendent de l'état de création comme Mailer pourrait fonctionner apparemment incorrect.

Vous pouvez le vérifier par l'ajout d'un débogage d'impression:

stage 'Test'
node {
    try {
        sh 'exit 1'
    } finally {
        println currentBuild.result  // this prints null
        step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: 'me@me.com', sendToIndividuals: true])
    }
}

L'ensemble de ce pipeline est enveloppé avec le gestionnaire d'exceptions prévues par Jenkins, c'est pourquoi Jenkins marque le construire comme ayant échoué à la fin.

Donc, si vous voulez utiliser Mailer vous avez besoin pour maintenir l'état de création correctement. Par exemple:

stage 'Test'
node {
    try {
        sh 'exit 1'
        currentBuild.result = 'SUCCESS'
    } catch (any) {
        currentBuild.result = 'FAILURE'
        throw any //rethrow exception to prevent the build from proceeding
    } finally {
        step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: 'me@me.com', sendToIndividuals: true])
    }
}

Si vous n'avez pas besoin de renvoyer l'exception que vous pouvez utiliser catchError. C'est un Pipeline intégré dans lequel les captures aucune exception à l'intérieur de son champ d'application, il imprime dans la console et des jeux de l'état de création. Exemple:

stage 'Test'
node {
    catchError {
        sh 'exit 1'
    } 
    step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: 'me@me.com', sendToIndividuals: true])
}

30voto

Wilfred Hughes Points 3507

En plus de izzekil excellente réponse, vous pouvez choisir les destinataires de courrier électronique basé sur la validation des auteurs. Vous pouvez utiliser e-mail-ext pour ce faire (basé sur leur pipeline exemples):

step([$class: 'Mailer',
      notifyEveryUnstableBuild: true,
      recipients: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
                                      [$class: 'RequesterRecipientProvider']])])

Si vous utilisez un récent e-mail-ext (2.50+), vous pouvez l'utiliser dans votre pipeline:

emailext(body: '${DEFAULT_CONTENT}', mimeType: 'text/html',
         replyTo: '$DEFAULT_REPLYTO', subject: '${DEFAULT_SUBJECT}',
         to: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
                                 [$class: 'RequesterRecipientProvider']]))

Si vous n'êtes pas à l'aide d'un déclaratif Jenkinsfile, vous aurez besoin de mettre l' checkout scm donc Jenkins pouvez trouver les développeurs. Voir JENKINS-46431.

Si vous êtes encore sur une ancienne version de e-mail-ext, vous serez frappé de JENKINS-25267. Vous pourriez rouler votre propre e-mail en HTML:

def emailNotification() {
    def to = emailextrecipients([[$class: 'CulpritsRecipientProvider'],
                                 [$class: 'DevelopersRecipientProvider'],
                                 [$class: 'RequesterRecipientProvider']])
    String currentResult = currentBuild.result
    String previousResult = currentBuild.getPreviousBuild().result

    def causes = currentBuild.rawBuild.getCauses()
    // E.g. 'started by user', 'triggered by scm change'
    def cause = null
    if (!causes.isEmpty()) {
        cause = causes[0].getShortDescription()
    }

    // Ensure we don't keep a list of causes, or we get
    // "java.io.NotSerializableException: hudson.model.Cause$UserIdCause"
    // see http://stackoverflow.com/a/37897833/509706
    causes = null

    String subject = "$env.JOB_NAME $env.BUILD_NUMBER: $currentResult"

    String body = """
<p>Build $env.BUILD_NUMBER ran on $env.NODE_NAME and terminated with $currentResult.
</p>

<p>Build trigger: $cause</p>

<p>See: <a href="$env.BUILD_URL">$env.BUILD_URL</a></p>

"""

    String log = currentBuild.rawBuild.getLog(40).join('\n')
    if (currentBuild != 'SUCCESS') {
        body = body + """
<h2>Last lines of output</h2>
<pre>$log</pre>
"""
    }

    if (to != null && !to.isEmpty()) {
        // Email on any failures, and on first success.
        if (currentResult != 'SUCCESS' || currentResult != previousResult) {
            mail to: to, subject: subject, body: body, mimeType: "text/html"
        }
        echo 'Sent email notification'
    }
}

16voto

Andi Points 353

Je pense qu'une meilleure façon d'envoyer des notifications par courrier électronique dans les pipelines jenkins consiste à utiliser la section post d'un pipeline comme décrit dans les documents jenkins au lieu d'utiliser try catch:

 pipeline {
  agent any
    stages {
      stage('whatever') {
        steps {
          ...
        }
      }
    }
    post {
        always {
          step([$class: 'Mailer',
            notifyEveryUnstableBuild: true,
            recipients: "example@example.com",
            sendToIndividuals: true])
        }
      }
    }
  }
}
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X