Search code examples
bashjenkinscppcheck

Bash: Store return value in variable and throw error later


I'm currently setting up cppcheck on our jenkins. I'd like to make the build stage "red" in case of any detected errors and publish the cppcheck results. However when cppcheck fails no results are published. I'd like to make Cppcheck fail AND publish the results.

I have tried the following 1) "normal" approach

sh """
cppcheck -j 16--project=myProject.sln --enable=all --inconclusive --xml --xml-version=2 --output-file="cppcheckresults.xml"
"""
//publish the cppcheck results...

=>results are published but stage will never turn red since cppcheck will not return a fail

2) append --error-exitcode=-1

sh """
cppcheck -j 16--project=myProject.sln --enable=all --inconclusive --xml --xml-version=2 --output-file="cppcheckresults.xml" --error-exitcode=-1
"""
//publish the cppcheck results...

=>cppcheck will fail properly in case of errors but results are not published since pipeline is aborted within sh step in case of error

3) "collect" the cppcheck error

def cppcheckReturn = 1
sh """
cppcheck -j 16--project=myProject.sln --enable=all --inconclusive --xml --xml-version=2 --output-file="cppcheckresults.xml" --error-exitcode=-1
cppcheckReturn=\$?
"""
//publish the cppcheck results...
//How to throw error in case of failure afterwards?

=> "collecting" the result does not work. Cppcheck will still fail and abort the pipeline without publishing the results

Is something like this even possible in bash?

How to reproduce: Create a new project (for ex. a VS solution) in your main generate some dummy failures like

int main()
{
  int* pFoo = malloc(sizeof(int)*10);
  pFoo[20] = 12345;
  return 0;
}

run cpp check with commands listed above

thx for your help guys :)


Solution

  • Groovy is not bash. Processes can't modify each other memory. When you set a variable in groovy, and another variable in bash, these are diffent things in memory of two different programs.

    Use the usual ways if interprocess communication, the simplest is a file. Write the exit status to a file in bash and read the content of that file read in groovy. From memory its readFile groovy jenkins function.

    But anyway, just set the groovy variable to the exit status of a command, using sh returnStatus option, see https://www.jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script . Something along:

    def cppcheckReturn = sh(
       script: "cppcheck",
       returnStatus: true
    )
    

    Additionally, as i really dispise jenkins and groovy, I would recommend writing a shell script that runs cppcheck, publishes result, abd then exits with cppcheck exit status. Instead of doing it in groovy, a shell script can be tested locally. Then from jenkins I would only sh "./thatscript.sh".