6

I have a pipeline with multiple steps, for example:

stage 'dev - compile'
node('master') {
  //do something
}

stage 'test- compile'
node('master') {
    //do something
}

stage 'prod- compile'
node('master') {
    //do something
}

I want to send a email if something goes wrong in the job, how can I send an email no matter where the error got triggered, something like:

try {
 /** 
  all the code above
  **/
 } catch(Exception e) { 
     mail the error
 } 
Daniel Hernández
  • 4,078
  • 6
  • 27
  • 38
  • Possible duplicate of [Use Jenkins 'Mailer' inside pipeline workflow](http://stackoverflow.com/questions/37169100/use-jenkins-mailer-inside-pipeline-workflow) – Wilfred Hughes Sep 14 '16 at 21:15

3 Answers3

8

I think it is a better way to use the jenkins build in post section instead of using try catch:

pipeline {
  agent any
    stages {
      stage('whatever') {
        steps {
          ...
        }
      }
    }
    post {
        always {
          step([$class: 'Mailer',
            notifyEveryUnstableBuild: true,
            recipients: "example@example.com",
            sendToIndividuals: true])
        }
      }
    }
  }
}
Andi
  • 1,172
  • 1
  • 11
  • 16
  • 1
    Good catch! I wish I understood why the Mailer plugin isn't exposed more nicely in the declarative pipeline instead of the lower-level `mail()` which requires much more assembly. Probably 95% of the users are happy with the emails generated by the Mailer plugin... – Yeroc Jul 27 '17 at 22:39
5

What I did to include useful information in my mail about the failure:

try {
    stage 'checkout cvs'
    node('master') {
        /** CODE **/
    }

    stage 'compile'
    node('master') {
        /** CODE **/
    }

    stage 'test unit'
    node('master') {
        /** CODE **/
    }   

    stage 'package'
    node('master') {
        /** CODE **/
    }

    stage 'nexus publish'
    node('master') {
        /** CODE **/
    }

    stage 'Deploy to App Server'
    node('master') {
        /** CODE **/            
    }

} catch(e) {
    String error = "${e}";
    // Make the string with job info, example:
    // ${env.JOB_NAME}
    // ${env.BUILD_NUMBER} 
    // ${env.BUILD_URL}
    // and other variables in the code
    mail bcc: '',
         cc: '',
         charset: 'UTF-8',
         from: '',
         mimeType: 'text/html',
         replyTo: '',
         subject: "ERROR CI: Project name -> ${env.JOB_NAME}",
         to: "${mails_to_notify}",
         body: "<b>${pivote}</b><br>\n\nMensaje de error: ${error}\n\n<br>Projecto: ${env.JOB_NAME} <br>Build Number: ${env.BUILD_NUMBER} <br> URL de build: ${env.BUILD_URL}";
    error "${error}"
}
Marco Roy
  • 4,004
  • 7
  • 34
  • 50
Daniel Hernández
  • 4,078
  • 6
  • 27
  • 38
3

Well, your idea is absolutely correct, you just need to move mail after the catch block or use finally. Examples (in pseudocode):

try {
    //code
    email = 'success'
} catch(Exception e) { 
    // error handler: logging
    email = 'failure'
}
send email

Or the same approach using the catchError pipeline built-in:

result = 'failure'
catchError { // this catches all exceptions and set the build result
    //code
    result = 'success' // we will reach this point only if no exception was thrown
}
send result 

Or using finally:

try {
    //code
} finally { 
    send email
}
izzekil
  • 5,781
  • 2
  • 36
  • 38
  • I think if I use the finally I will send always the email, I just want to notify when the buils it's broken. Also, I tried catchError { echo 'ERROR MY FRIEND'; } and I put some wrong IP in GIT and I did not get my echo 'ERROR MY FRIEND' – Daniel Hernández Apr 29 '16 at 23:41
  • I might misunderstand your question. If you want to send email only when an error occured, you initial code snippet fits perfectly. As for `catchError` it doesn't block any logging. – izzekil Apr 29 '16 at 23:46
  • I will try my code , I didn't to be honest, I just thought that wasn't work – Daniel Hernández Apr 29 '16 at 23:48
  • I also edited the `catchError` example so that it can maintain the build result. – izzekil Apr 29 '16 at 23:49
  • I don't think the original code snippet will work, unless you put everything into that try {...} catch block. I'm also wondering whether there is a solution like job failure listener/hook. – fayndee Aug 11 '16 at 09:41