Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I use a Closure to define a stage in a Jenkins Declarative Pipeline?

I'm trying to do something like this:

def makeStage = {
  stage('a') {
    steps {
      echo 'Hello World'
    }
  }
} 
pipeline {
  agent none
  stages {
    makeStage()
  }
}

But it gives me this exception:

WorkflowScript: 11: Expected a stage @ line 11, column 5.
   makeStage()
   ^

Is it possible to define a stage as a external closure and if so - how?

like image 476
Will Brode Avatar asked Jun 01 '18 00:06

Will Brode


People also ask

What block can be used to control if a stage runs in a declarative pipeline?

The top-level of the Pipeline must be a block, specifically: pipeline { } No semicolons as statement separators. Each statement has to be on its own line. Blocks must only consist of declarative sections, declarative directives, declarative steps, or assignment statements.

How does Jenkins pipeline define stages?

Jenkins Pipeline can be defined by a text file called JenkinsFile. You can implement pipeline as code using JenkinsFile, and this can be defined by using a DSL (Domain Specific Language). With the help of JenkinsFile, you can write the steps required for running a Jenkins Pipeline.

What is closure in Jenkins pipeline?

The Groovy documentation explains that, “A closure in Groovy is an open, anonymous, block of code that can take arguments, return a value and be assigned to a variable. A closure may reference variables declared in its surrounding scope.”

How do I run a specific stage in Jenkins pipeline?

The variables checkoutCode , runSonarScan , deployNexusArtifact can be set as environment variables statically or dynamically. environment { checkoutCode = true runSonarScan = true deployNexusArtifact = true } stage('Gitlab code Checkout') { when { expression { "${checkoutCode}" == 'true' } } ... }


1 Answers

You can't define stages outside the declarative pipeline. The main purpose of declarative pipeline is to provide simplified and opinionated syntax so you can focus on what should be done (by using some of the available steps) and not how to do it.

If you are interested in more flexible way of implementing pipeline, you may choose Scripted Pipeline approach which is not that strict if it comes to the syntax - it's only limited by Groovy and CPS execution module.

Working (scripted) pipeline from your example would look like this:

#!groovy

def makeStage = {
  stage('a') {
    echo 'Hello World'
  }
} 

node {
    makeStage()
}

Attention: There is no steps method inside stage in a scripted pipeline. If you leave it there you will get

java.lang.NoSuchMethodError: No such DSL method 'steps' found among 
    steps [archive, bat, build, catchError, checkout, deleteDir, dir, 
    dockerFingerprintFrom, ...

Scripts in declarative pipeline

Declarative pipeline defines a script step that allows you to put a block of scripted pipeline. However it still does not allow you to define stage dynamically or/and extract stage definition to a function or closure. script step gets executed inside the stage so you can't control inside this block if stage is executed or not. In some cases however this step might be very useful if you want to do something more complex than just calling pre-defined step of a declarative pipeline.

like image 197
Szymon Stepniak Avatar answered Oct 16 '22 00:10

Szymon Stepniak