Search code examples
jenkinsgroovyjenkins-pipelinejenkins-groovyjenkins-job-dsl

Return value from bat function in Groovy DSL Pipeline in Jenkins


Background

I have a written a Groovy DSL declarative pipeline script in Jenkins. The script is executes on a slave agent which runs on Windows Server 2012. On this agent machine there is a command line executable called kitchen. I execute the kitchen program using Groovy's bat() method, and I pipe in a parameter that is passed into the pipeline when it's built.

The script is simple and does the following in a series of two stages

  1. Takes in an AWARD_YEAR parameter
  2. Checkout a project from SVN
  3. Executes the kitchen program through a bat() function

I am using Jenkins 2.235.3

Issue

The kitchen executable returns an exit code in the range from 0 - 9. When the exit code is anything other than 0 this indicates the executable has failed. However, as it stands currently the pipeline execution always succeeds regardless of the exit code. To fix this, I need to store the exit code in a variable and then check its value.

However, when I attempt to store the result into a variable I get the error shown below.

Code and Error

Below is the code that causes the error

pipeline {
    agent { label 'pentaho-test' }


    parameters {
        string(name: 'AWARD_YEAR', defaultValue: "${Calendar.getInstance().get(Calendar.YEAR)}", description: 'Award Year Parameter')
    }
    
    stages {
        stage('Checkout') {
            steps {
                checkout changelog: false, poll: false, scm: [
                        $class: 'SubversionSCM', 
                        additionalCredentials: [], 
                        excludedCommitMessages: '', 
                        excludedRegions: '', 
                        excludedRevprop: '', 
                        excludedUsers: '', 
                        filterChangelog: false, 
                        ignoreDirPropChanges: false, 
                        includedRegions: '', 
                        locations: [[cancelProcessOnExternalsFail: true, 
                            credentialsId: 'hudson', 
                            depthOption: 'infinity', 
                            ignoreExternalsOption: true, 
                            local: '.', 
                            remote: 'https://svn.int.domain.edu/project/trunk']], 
                        quietOperation: true, 
                        workspaceUpdater: [$class: 'UpdateUpdater']
                ]
            }
        }
        stage('Run Kitchen') {       
            steps {
                def result = bat( label: '', returnStdout: true, script: 'kitchen -args %AWARD_YEAR%'  )
                
                echo result     
            }

        }

    }

}

Below is the error shown in the Jenkins Console

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 35: Expected a step @ line 35, column 5.
                result = bat( label: '', returnStdout: true, script: 'kitchen -args %AWARD_YEAR%'  )
       ^

1 error

    at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
    at org.codehaus.groovy.control.CompilationUnit.applyToPrimaryClassNodes(CompilationUnit.java:1085)
    at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:603)
    at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
    at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
    at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
    at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
    at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
    at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
    at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:142)
    at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:127)
    at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:561)
    at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:522)
    at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:337)
    at hudson.model.ResourceController.execute(ResourceController.java:97)
    at hudson.model.Executor.run(Executor.java:428)
Finished: FAILURE

When I modify the step as follows the script executes without error, but the exit code is not stored and therefore even when the binary executable fails the pipeline shows as if it succeeds.

steps {
     result = bat label: '', returnStdout: true, script: 'kitchen -args %AWARD_YEAR%'  
}

Post Script

There are two other StackOverflow questions that ask this specific question, but the solution causes the error I am recieving.


Solution

  • If you want to capture the result from the sh step and assign it to a variable, you need to do it in the script block.

    Change

    stage('Run Kitchen') {       
        steps {
            def result = bat( label: '', returnStdout: true, script: 'kitchen -args %AWARD_YEAR%'  )
                    
            echo result     
        }
    }
    

    to

    stage('Run Kitchen') {       
        steps {
            script {
                def result = bat( label: '', returnStdout: true, script: 'kitchen -args %AWARD_YEAR%'  )
                    
                echo result     
            }
        }
     }
    

    and you should fix the problem you see at the moment.