jenkinsjenkins-pipelinejenkins-groovyjenkins-shared-libraries

The 'error' in the Jenkinsfile, does not get executed


I have a jenkinsfile, which calls a shared library. For eg: Jenkinsfile-

@Library('test-shared-library') _
testAndPack{
    //container = ''

    PIPELINE = [
                ["type": "python",
                "name": "Dummy",
                "stage": "Run python",
                "folder": "build",
                "script": "python3 HelloWorld.py",
                
                ],
                ["type": "Pack",
                "name": "DummyCombination",
                "stage":"Pack To Zip",
                "script": "echo packing to zip",
                "artefacts": "*.zip"
                ],
            ]
    triggerGenerateCodePipeline = true
}

The testAndPack.groovy looks like this:

def call(body) {
    // Confuration from the argument
    def config = [:]
    body.resolveStrategy = Closure.DELEGATE_FIRST
    body.delegate = config
    body()
    try{
        for (val in config.PIPELINE){
                    
                   if (val.type == "python"){
                        run_python(val)
                    }else if (val.type == "Pack"){
                       perform_packing(val)
                    }
                }

    }
    catch(Exception e) {
         BUILD_STATUS ="FAILURE"
    }
}

def run_python(val){
   stage(val.name) {
     node {
        checkout scm
      BUILD_STATUS = sh ( script: "ls && cd ${val.folder} && ${val.script}",
                          returnStatus: true
                        ) == 0
      echo "${BUILD_STATUS}"
  if (BUILD_STATUS) {
          echo "${val.name} was build correctly "
      } else {    
         error "#### build_step ${val.name} failed ####"//Even here it doesn't print when failure
      }
    }
   }
}

def perform_packing(val){
   stage(val.name) {
      node {
      def BUILD_STATUS = sh (returnStatus: true, script: "ls && zip -r build.zip build")==0
       echo "${BUILD_STATUS}"   
      if (BUILD_STATUS) {
          echo "${STAGE_NAME} was build correctly "
      } else {    
          echo "before error"
          error "There is a failure" //Does not print
          echo "after error"
          //throw new Exception("Something went wrong!")
      }
    }
   }
}

Currently, the zip tool isnot present in the node. So I expect an error to be thrown and build to fail. However, the response is the following Jenkins Response.

Am I missing something here? The error construct seems to work on a simple pipeline though.(Just eliminating the scenario if its based on a plugin)


Solution

  • So I expect an error to be thrown and build to fail.

    This is currently half true: an error is being thrown, but the build is not failing. The error is being explicitly caught by the invoking code higher on the stack:

    try { ... }
    catch(Exception e) {
      BUILD_STATUS = "FAILURE"
    }
    

    To additionally mark the build as a failure you would need to modify the result member of the currentBuild object to be assigned the string value of FAILURE:

    if (BUILD_STATUS) {
      echo "${val.name} was build correctly "
    } else {    
      error "#### build_step ${val.name} failed ####"//Even here it doesn't print when failure
      currentBuild.result = 'FAILURE'
    }
    

    alternatively to conform to your current style:

    try { ... }
    catch(Exception e) {
      currentBuild.result = 'FAILURE'
    }
    

    but this alternate implementation of course also prevents the error message from flushing to the stderr descriptor, and so you would need to explicitly log it beforehand if you want to view it in the Jenkins Pipeline logs.