25

I'm trying to replicate the equivalent of a conditional stage in Jenkins pipeline using a try / catch around a preceding stage, which then sets a success variable, which is used to trigger the conditional stage.

It appears that a try catch block is the way to go, setting a success var to SUCCESS or FAILED, which is used as part of a when statement later (as part of the conditional stage).

The code I am using is as follows:

pipeline {
    agent any
    stages {
        try{
            stage("Run unit tests"){
                steps{
                    sh  '''
                        # Run unit tests without capturing stdout or logs, generates cobetura reports
                        cd ./python
                        nosetests3 --with-xcoverage --nocapture --with-xunit --nologcapture --cover-package=application
                        cd ..
                    '''
                    currentBuild.result = 'SUCCESS'
                }
            }
        } catch(Exception e) {
            // Do something with the exception 
            currentBuild.result = 'SUCCESS'
        }

        stage ('Speak') {
            when {
                expression { currentBuild.result == 'SUCCESS' }
            }
            steps{
                echo "Hello, CONDITIONAL"
            }
        }
    }
}

The latest syntax error I am receiving is as follows:

org.codehaus.groovy.control.MultipleCompilationErrorsException: startup 
failed:
WorkflowScript: 4: Expected a stage @ line 4, column 9.
       try{

I've also tried lots of variations.

Am I taking the wrong approach here? This seems like a fairly common requirement.

Thanks.

Xerphiel
  • 1,053
  • 2
  • 12
  • 23
  • 4
    you are using a declarative pipeline, this does not allow to execute Groovy code such as `try`/`catch`. – StephenKing Apr 08 '17 at 12:13
  • I'm using declarative - and a non messy way of having a stage that will always run as cleanup is a basic requirement of the "pipeline" concept. Is there a cleaner way? If I have 10 stages this creates 9 places I need to add a bit more code, which feels wrong. –  Apr 04 '19 at 08:21
  • If you are using a declarative pipeline, it does allow to execute Groovy code such as try/catch, as long as you wrap it in a `script` clause (which turns this clause into a scripted pipeline, so StephenKing was technically right, but at the same time wrong in the wider sense of lack of any possibility, because clearly we have a good workaround here). – mirekphd Dec 16 '19 at 08:44

1 Answers1

36

This might solve your problem depending on what you are going for. Stages are only run when the preceding stages succeed, so if you actually have two stages like in your example, and if you want the second to only run when the first succeeds, you want to ensure that the first stage fails appropriately when tests fail. Catching will prevent the (desirable) failure. Finally will preserve the failure, and can also still be used to grab your test results.

So here, the second stage will only run when the tests pass, and the test results will be recorded regardless:

pipeline {
  agent any
  stages {
    stage("Run unit tests"){
      steps {
        script {
          try {
            sh  '''
              # Run unit tests without capturing stdout or logs, generates cobetura reports
              cd ./python
              nosetests3 --with-xcoverage --nocapture --with-xunit --nologcapture --cover-package=application
              cd ..
              '''
          } finally {
            junit 'nosetests.xml'
          }
        }
      }
    }
    stage ('Speak') {
      steps{
        echo "Hello, CONDITIONAL"
      }
    }
  }
}

Note that I'm actually using try in a declarative pipeline, but like StephenKing says, you can't just use try directly (you have to wrap arbitrary groovy code in the script step).

Community
  • 1
  • 1
burnettk
  • 13,557
  • 4
  • 51
  • 52