J'aimerais exploiter le plugin Mailer existant de Jenkins dans un Jenkinsfile
qui définit un travail de construction de pipeline. Compte tenu du simple script d'échec suivant, j'attendrais un courrier électronique pour chaque build.
#!groovy
stage 'Test'
node {
try {
sh 'exit 1'
} finally {
step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
}
}
Le résultat de la construction 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 constater, il enregistre qu'il exécute le pipeline step
immédiatement après la défaillance, mais aucun courrier électronique n'est généré.
Les e-mails dans d'autres tâches de style libre qui exploitent le mailer
fonctionnent bien, il suffit d'appeler via des tâches de pipeline.
Cela fonctionne avec Jenkins 2.2 et mailer 1.17.
Existe-t-il un mécanisme différent selon lequel je devrais invoquer des e-mails ayant échoué à la construction? Je n'ai pas besoin de tout le surcoût de l'étape mail
, juste besoin de notifications sur les échecs et les récupérations.
Dans le pipeline a échoué sh
ne définit pas immédiatement le currentBuild.result
à FAILURE
alors que sa valeur initiale est null
. Par conséquent, les étapes de construction qui reposent sur le statut de construction, comme Mailer, pourraient fonctionner apparemment de manière incorrecte.
Vous pouvez le vérifier en ajoutant une impression de débogage:
stage 'Test'
node {
try {
sh 'exit 1'
} finally {
println currentBuild.result // this prints null
step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
}
}
Tout ce pipeline est encapsulé avec le gestionnaire d'exceptions fourni par Jenkins, c'est pourquoi Jenkins marque la construction comme ayant échoué à la fin.
Donc, si vous voulez utiliser Mailer, vous devez maintenir le statut de construction 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: '[email protected]', sendToIndividuals: true])
}
}
Si vous n'avez pas besoin de relancer l'exception, vous pouvez utiliser catchError
. Il s'agit d'un pipeline intégré qui capture toute exception dans son étendue, l'imprime dans la console et définit le statut de construction. Exemple:
stage 'Test'
node {
catchError {
sh 'exit 1'
}
step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true])
}
En plus de l'excellente réponse d'izzekil, vous souhaiterez peut-être choisir les destinataires des e-mails en fonction des auteurs. Vous pouvez utiliser email-ext pour le faire (en fonction de leurs exemples de pipeline ):
step([$class: 'Mailer',
notifyEveryUnstableBuild: true,
recipients: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
[$class: 'RequesterRecipientProvider']])])
Si vous utilisez un email récent (plus de 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 de fichier Jenkins déclaratif, vous devrez mettre checkout scm
afin que Jenkins puisse trouver les committers. Voir JENKINS-46431 .
Si vous utilisez toujours une version plus ancienne de email-ext, vous frappez JENKINS-25267 . Vous pouvez lancer votre propre email 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'
}
}
Je pense qu'une meilleure façon d'envoyer des notifications par courrier électronique dans les pipelines Jenkins est d'utiliser la section de publication d'un pipeline, comme décrit dans jenkins docs au lieu d'utiliser try catch:
pipeline {
agent any
stages {
stage('whatever') {
steps {
...
}
}
}
post {
always {
step([$class: 'Mailer',
notifyEveryUnstableBuild: true,
recipients: "[email protected]",
sendToIndividuals: true])
}
}
}
}
}