32

In my Jenkins pipelines I generally use post declarative function to send me an email incase the pipeline has failed.

A simple syntax of the post function is as under:

post {
    failure {
        mail to: 'team@example.com',
             subject: "Failed Pipeline: ${currentBuild.fullDisplayName}",
             body: "Something is wrong with ${env.BUILD_URL}"
    }
}

In the above email, I also want to mention which stage (lets say the pipeline has 5 to 6 stages) of the pipeline has failed. How can I do that? Any help is much appreciated.

An extension to the above requirement will be to provide the user with the actual error log (of the stage that has failed) also as a part of the failure notification email.

Idea is, when a user receives a failure notification from jenkins, he should know which stage of the pipeline has failed along with the error log.

Thanks in advance.

Yash
  • 2,944
  • 7
  • 25
  • 43
  • An alternative is to use "post" at the stage level – vmartin Apr 18 '19 at 17:30
  • Does this answer your question? [Determine Failed Stage in Jenkins Declarative Pipeline](https://stackoverflow.com/questions/43439093/determine-failed-stage-in-jenkins-declarative-pipeline). This question has a more comprehensive set of answers. – zett42 May 16 '20 at 13:28

1 Answers1

30

There is a variable called env.STAGE_NAME which you can use. However, in your case you will probably need to store the stage name in a different variable, because when you get the env.STAGE_NAME in a post stage the result will be Declarative: Post Actions. Instead, you will need to store the stage name in a variable in all stages. So once a stage fails - Jenkins will not continue with the next stages and therefore you will have the "failed" stage name.

Here's an example:

def FAILED_STAGE

pipeline {
    agent { label "master" }
    stages {
        stage("Stage 1") {
            steps {
                script {
                    FAILED_STAGE=env.STAGE_NAME
                    echo "stage 1"
                }
            }
        }
        stage("Stage 2") {
            steps {
                script {
                    FAILED_STAGE=env.STAGE_NAME
                    echo "stage 2"
                    error "failed for some reason."
                }
            }
        }
        stage("Stage 3") {
            steps {
                script {
                    FAILED_STAGE=env.STAGE_NAME
                    echo "stage 3"
                }
            }
        }
    }
    post {
        failure {
            echo "Failed stage name: ${FAILED_STAGE}"
        }
    }
}

There might be a better way to do it, but I haven't found it so far.

Regarding the logs - As of JENKINS-40526 you could possibly use the API and get the log file from there, but I am not sure you can get the parameters you need from within the pipeline. The other solution would be to use emailext and email the entire build log file:

emailext attachLog: true, body: '', compressLog: true, subject: 'Build failed.', to: 'somebody@somewhere.com'

tftd
  • 16,203
  • 11
  • 62
  • 106
  • Thanks @tftd for your response. I will try the solution suggested by you and share the feedback. – Yash May 18 '18 at 16:40
  • Hi @tftd, I'm using `Jenkins ver. 2.41` and in this version, the env variable `STAGE_NAME` is not available. Shall I switch to any specific version of Jenkins for using this env var or there is any other way out? – Yash May 18 '18 at 19:20
  • This has been fixed in [JENKINS-44456](https://issues.jenkins-ci.org/browse/JENKINS-44456) which was released as part of [Pipeline Stage Step Plugin](https://wiki.jenkins.io/display/JENKINS/Pipeline+Stage+Step+Plugin) version 2.3. Check if you can upgrade to that version of the plugin and you should be able to use the env variable. – tftd May 18 '18 at 19:36
  • 1
    Thanks @tftd, after installing the stage step plugin v2.3, I'm able to use `STAGE_NAME` environment variable. – Yash May 21 '18 at 07:42
  • 1
    seems like that `script` tag is needed in order to alter a `def` https://stackoverflow.com/a/39846733/1572848 . you only have it used on step 2 in your example – William Reed Jun 12 '19 at 20:51
  • 1
    @WilliamReed Yeah, that's correct - I've updated the answer. Thanks! :) – tftd Jun 13 '19 at 14:39
  • I'm able to echo FAILED_STAGE during the run, but the post-stage doesn't recognize it. I used this syntax: post { failure { emailext body: 'Failed stage name: ${FAILED_STAGE} }} – arielma Dec 03 '19 at 10:35
  • Have you defined the variable before the pipeline as in the example? – tftd Dec 03 '19 at 11:19
  • Yes I did. maybe something with the apostrophe – arielma Dec 03 '19 at 11:31
  • 1
    Try using double quotes `"` instead of single ones `'` – tftd Dec 03 '19 at 11:54
  • 2
    Looks good. However, this may return incorrect stage names when you use parallel stages – Kutzi May 12 '22 at 13:08
  • @Kutzi Yes, the example above is for sequential stage builds. What I tend to do for parallel builds is to approach the issue at a higher level. So for example I have stages like `Checkout`, `Build`, `Test` where `Build` and `Test` have parallel inner stages (i.e. `jdk8`, `jdk11`, etc). When the inner stages fail they will also fail the outer ones (i.e. `Build`). In the failure report you can just mention the `Build` or `Test` (not `jdk8` or `jdk11` because there isn't an easy way to fetch that info) – tftd May 13 '22 at 11:28