I have pipeline runs 3 stages. success, fail, success. Yes I want the pipeline continue to run even one stage fails.
This screenshot looks right.
My problem is, the last stage green2 is successful but the post action went to failure block instead of success. Here is output

green success
red failure
green2 failure

My goal is catch every stage status and send to slack. With catchError(), if the stage fail I cannot assign a global variable to indicates that stage failed.
Thank you in advance for your help!
enter image description here

pipeline {
    stages {    
        stage("green"){            
            steps{
                catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
                    sh 'exit 0'
                }               
            }
            post{
                success {
                    echo 'green success'
                }
                failure{
                    echo 'green fail'
                }               
            }
        }       
        stage("red"){
           
            steps{
                catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
                    sh 'exit 1'
                }
            }
            post{
                success {
                    echo 'red success'
                }
                failure{
                    echo 'red failure'
                }           
            }
        }
        
        stage("green2"){
            steps{
                catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
                    sh 'exit 0'
                }
            }
            post{
                success {
                    echo 'green2 success'
                }
                failure{
                    echo 'green2 failure'
                }
            }
        }
    }
}

Jenkins 2.401.3

2

There are 2 best solutions below

1
Iterokun On BEST ANSWER

A slight variation of the @m-b 's answer, accumulating stage results in a map

def stageResults = [:]
pipeline {
  agent any
  stages {
    stage("green"){
      steps{
        script { stageResults[STAGE_NAME] = 'failure' }
        catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
          sh 'exit 0'
          script { stageResults[STAGE_NAME] = 'success' }
        }
      }
    }
    stage("red"){
      steps{
        script { stageResults[STAGE_NAME] = 'failure' }
        catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
          sh 'exit 1'
          script { stageResults[STAGE_NAME] = 'success' }
        }
      }
    }
    stage("green2"){
      steps{
        script { stageResults[STAGE_NAME] = 'failure' }
        catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
          sh 'exit 0'
          script { stageResults[STAGE_NAME] = 'success' }
        }
      }
    }
  }
  post{
    always {
      echo "Stage results: ${stageResults}"
    }
  }
}
2
M B On

If you want to send the status of each stage regardless of what it is, you could completely remove both success and failure post stages and replace them with an always block. Then, in the always block you could have an if condition where you send the correct Slack message. Drawing from this answer, your pipeline would look like this:

def boolean test_results = false

...
stage("red"){
    steps{
        catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
            sh 'exit 1'
            script { test_results = true }
        }
    }
    post{
        always {
            if( test_results == true ) {
                echo 'red success'
            } else {
                echo 'red failure'
            }
            test_results = false
        }        
    }
}

stage("green2"){
    steps{
        catchError(buildResult: 'FAILURE', stageResult: 'FAILURE') {
            sh 'exit 0'
            script { test_results = true }
        }
    }
    always {
        if( test_results == true ) {
            echo 'green2 success'
        } else {
            echo 'green2 failure'
        }   
        test_results = false
    }   
}

You can move the if condition out into a function to reduce code duplication.