2016-05-11 22 views
26

Vorrei sfruttare il plug-in esistente Mailer da Jenkins all'interno di uno Jenkinsfile che definisce un processo di generazione della pipeline. Dato il seguente semplice script di errore, mi aspetterei un'e-mail su ogni build.Utilizzare Mailer di Jenkins all'interno del flusso di lavoro della pipeline

#!groovy 

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

L'uscita dalla build è:

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 

Come si può vedere, lo fa record che esegue la pipeline step subito dopo il fallimento, ma nessun email ottenere generato.

Le e-mail in altri lavori in stile libero che sfruttano lo mailer funzionano correttamente, stanno solo invocando tramite lavori di pipeline.

Questo è in esecuzione con Jenkins 2.2 e mailer 1.17.

C'è un meccanismo diverso con cui dovrei invocare email di build non riuscite? Non ho bisogno di tutto il sovraccarico del passaggio mail, ho solo bisogno di notifiche su guasti e ripristini.

+0

E 'questo helful? http://stackoverflow.com/questions/36948606/jenkins-notifying-error-by-sending-mail-in-pipeline-former-known-as-workflow –

+0

Molto vicino a quello che stavo cercando di fare, ma si riferisce più a l'uso del plugin di posta dopo un errore. Il pezzo mancante è dettagliato nella risposta di seguito in come lo stato viene impostato durante il processo di pipeline, che è richiesto per i plug-in che utilizzano uno stato di build non in sospeso. – rkeilty

risposta

53

In tubazioni fallito sh non imposta immediatamente il currentBuild.result di FAILURE mentre il suo valore iniziale è null. Quindi costruisci passaggi che si basano sullo stato di build come Mailer potrebbe funzionare apparentemente errato.

È possibile controllare con l'aggiunta di una stampa di debug:

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

Questa intero oleodotto è avvolto con gestore di eccezioni fornito da Jenkins è per questo che Jenkins segna il build fallito in alla fine.

Quindi, se si desidera utilizzare Mailer è necessario mantenere correttamente lo stato di compilazione. Per esempio:

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]) 
    } 
} 

Se non c'è bisogno di rigenerare l'eccezione è possibile utilizzare catchError. È un built-in Pipeline che cattura qualsiasi eccezione nel suo ambito, lo stampa in console e imposta lo stato della build. Esempio:

stage 'Test' 
node { 
    catchError { 
     sh 'exit 1' 
    } 
    step([$class: 'Mailer', notifyEveryUnstableBuild: true, recipients: '[email protected]', sendToIndividuals: true]) 
} 
+0

Questa è una risposta fantastica e dettagliata, e mi ha riportato sulla giusta strada. Grazie per questo! – rkeilty

+0

Come posso assicurarmi che una build di successo dopo una build fallita (o instabile) inneschi una nuova e-mail? – asmaier

+0

@asmaier Il plug-in AFAIK Mailer non fornisce questa funzionalità. Puoi copiarlo con groovy (controlla lo stato precedente della build) o dare un'occhiata a [Plug-in Email Ext] (https://wiki.jenkins-ci.org/display/JENKINS/Email-ext+plugin). – izzekil

22

Oltre a izzekil di risposta eccellente, si potrebbe desiderare di scegliere i destinatari di posta elettronica in base commettere gli autori. È possibile utilizzare email-ext per fare questo (basata su their pipeline examples):

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

Se stai usando una recente email-ext (2.50+), è possibile utilizzare che nella vostra pipeline:

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

Se non stai utilizzando un Jenkinsfile dichiarativo, dovrai inserire checkout scm in modo che Jenkins possa trovare i committer. Vedi JENKINS-46431.

Se si è ancora in una versione precedente di email-ext, verrà visualizzato JENKINS-25267.Si potrebbe rotolare il proprio e-mail 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' 
    } 
} 
+0

Ottima risposta supplementare! Grazie – technophobia

+0

Come si dovrebbe eseguire il debug di Jenkinsfile? Per esempio in quale ambito 'emailext' è disponibile? – Raffaele

+2

L'argomento Mailer "sendToIndividuals: true' non dovrebbe già inviare un'e-mail agli autori di commit? –

7

Credo che un modo migliore per inviare notifiche di posta elettronica a Jenkins gasdotti è quello di utilizzare la sezione di post di una condotta come descritto nel jenkins docs invece di utilizzare try cattura:

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

Ho provato la tua tecnica, ma questo non invia notifiche "Ritorno alla normalità". –

+0

come impostare 'currentBuild.result' nella sezione post.always? – prat0318

+0

@ prat0318 penso che 'currentBuild.result' sia corretto a questo punto in quanto è un'azione post. Puoi solo leggere il risultato. – Andi

Problemi correlati