Utiliser Jenkins 'Mailer' à l'intérieur du pipeline de flux de travail

j'aimerais tirer parti de l'existant Mailer plugin Jenkins dans un Jenkinsfile qui définit un pipeline de travail. Étant donné le script d'échec simple suivant, je m'attendrais à un email sur chaque construction.

#!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.

Emails dans d'autres travaux de style libre qui l'effet de levier de l' mailer bon travail, c'est juste invoquer via des travaux de pipeline.

ceci fonctionne avec Jenkins 2.2 et mailer 1.17.

y a-t-il un autre mécanisme par lequel je devrais invoquer les e-mails de compilation échoués? 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.

28
demandé sur rkeilty 2016-05-11 20:06:11

3 réponses

Dans le Pipeline a échoué sh ne pas régler immédiatement la currentBuild.resultFAILURE alors que sa valeur initiale est null. Par conséquent, les étapes de construction qui dépendent du statut de construction comme Mailer peuvent fonctionner de façon apparemment incorrecte.

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 du pipeline est emballé avec un manipulateur d'exception fourni par Jenkins c'est pourquoi Jenkins marque L'échec de la construction à 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. Il s'agit d'un Pipeline intégré qui saisit toute exception dans sa portée, l'imprime dans la console et définit l'état de construction. Exemple:

stage 'Test'
node {
    catchError {
        sh 'exit 1'
    } 
    step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: 'me@me.com', sendToIndividuals: true])
}
57
répondu izzekil 2016-12-05 14:12:23

en plus de l'excellente réponse d'izzekil, vous pouvez choisir des destinataires de courriel basés sur les auteurs de commit. Vous pouvez utiliser e-mail-ext pour ce faire (basé sur leurs exemples de pipeline):

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'utilisez pas un Jenkinsfile déclaratif, vous devrez mettre checkout scm pour que Jenkins puisse trouver les committers. Voir JENKINS-46431.

si vous êtes toujours sur une ancienne version de email-ext, vous frapperez 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'
    }
}
23
répondu Wilfred Hughes 2017-08-24 17:19:23

je pense qu'une meilleure façon d'envoyer des notifications de courrier dans jenkins pipelines est d'utiliser la section de courrier d'un pipeline comme décrit dans le jenkins docs 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])
        }
      }
    }
  }
}
10
répondu Andi 2017-05-19 08:56:43