Search code examples
jenkinsgroovyjenkins-pipelinejenkins-groovy

Jenkins-pipeline Posting Failure Output to Slack


I have a Python script that I'm running in my pipeline that is forced to fail. I'm trying to send the failure output to Slack.

testing.py

import sys

print("Hello World")
sys.exit(1)

pipeline

def slackChannel = "default-ops"
def slackDetails = "${env.JOB_NAME} - (<${env.BUILD_URL}|Open>)"
def shResult() {
    script {
        sh script: 'set -e; python3 testing.py', returnStdout: true
    }
}

pipeline {
    agent any

    stages {
        stage('Execute testing.py') {
            steps {
                script{
                    echo "${shResult()}".trim()
                    if (shResult != 0) {
                        currentBuild.result = 'FAILURE'
                    }
                }
            }
        }
    }

    post {
        success {
            slackSend(color: '#00FF00',
                      channel: "${slackChannel}",
                      message: "SUCCESSFUL: " + slackDetails)
        }
        failure {
            slackSend(color: '#FF0000',
                      channel: "${slackChannel}",
                      message: "FAILED: " + slackDetails + shResult())
        }
        aborted {
            slackSend(color: '#808080',
                      channel: "${slackChannel}",
                      message: "ABORTED: " + slackDetails)

        }
    }
}

This results in the following error:

Error when executing failure post condition:
hudson.AbortException: script returned exit code 1
at org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep$Execution.handleExit(DurableTaskStep.java:659)
at org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep$Execution.check(DurableTaskStep.java:605)
at org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep$Execution.run(DurableTaskStep.java:549)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)

How do I send the output "Hello World" to Slack?


Solution

  • First of all the line message: "FAILED: " + slackDetails + shResult()) executes the script again, which is probably not what you want.

    The second thing is that returnStdout: true does not return the status code, but the stdout output. So in this case only "Hello World". Use returnStatus: true to get 0 or 1.

    Sadly you can't return both stdout and the status. One way of doing it would be to only use returnStatus: true and pipe stdout to a file.

    The pipeline would look something like this:

    def slackChannel = "default-ops"
    def slackDetails = "${env.JOB_NAME} - (<${env.BUILD_URL}|Open>)"
    def shResult() {
        script {
            sh script: 'set -e; python3 testing.py > /tmp/somefile 2>&1', returnStatus: true
        }
    }
    
    pipeline {
        agent any
    
        stages {
            stage('Execute testing.py') {
                steps {
                    script{
                        status = shResult()
                        if (status != 0) {
                            currentBuild.result = 'FAILURE'
                            errorMsg = readFile '/tmp/somefile'
                        }
                    }
                }
            }
        }
    
        post {
            success {
                slackSend(color: '#00FF00',
                          channel: "${slackChannel}",
                          message: "SUCCESSFUL: " + slackDetails)
            }
            failure {
                slackSend(color: '#FF0000',
                          channel: "${slackChannel}",
                          message: "FAILED: " + slackDetails + errorMsg
            }
            aborted {
                slackSend(color: '#808080',
                          channel: "${slackChannel}",
                          message: "ABORTED: " + slackDetails)
    
            }
        }
    }
    

    I can't test this pipeline right now but it should work.