94

In Jenkins scripted pipeline we are able to create methods and can call them.

Is it possible also in the Jenkins declarative pipeline? And how?

Guy Avraham
  • 3,482
  • 3
  • 38
  • 50
vinesh vini
  • 1,041
  • 1
  • 7
  • 4

4 Answers4

105

Newer versions of the declarative pipelines support this, while this was not possible before (~mid 2017). You can just declare functions as you'd expect it from a groovy script:

pipeline {
    agent any
    stages {
        stage('Test') {
            steps {
                whateverFunction()
            }
        }
    }
}

void whateverFunction() {
    sh 'ls /'
}
StephenKing
  • 36,187
  • 11
  • 83
  • 112
  • 2
    I was able to get this to work, however it removes the ability to edit the pipeline in the Blue Ocean GUI editor. Do you know of a way around that? I do most of the editing in the Jenkinsfile directly via text editor, but it is nice to be able to stub things out quickly in the UI. I got around that by commenting out the function temporarily. – Damon Mar 18 '18 at 21:03
  • 1
    I'm trying to define a function that defines a stage but this doesn't seem to work (syntax error expected 'stage'). Do they only support running functions defining steps? – Will Brode Jun 01 '18 at 00:16
  • 3
    This is really cool. However, where is this documented? I fail to find any resource describing this ability. I only find documentation how to import external, shared groovy libraries. I only find this SO answer for embedding them in the Jenkinsfile itself, which is really useful. Jenkins issue tracker with proposals received wontfix status, e.g.: https://issues.jenkins-ci.org/browse/JENKINS-41396 – gertvdijk Aug 14 '18 at 10:09
  • @WillBrode i am also interested in having functions to define/configure an entire stage. It is my understanding that the declarative pipeline parser simply doesn't allow those type of syntax flexibility: https://issues.jenkins-ci.org/browse/JENKINS-49135 Have you had any success with this? – carlos Jan 16 '20 at 16:58
  • @carlos I asked that question and there are some answers here: https://stackoverflow.com/questions/50634592/can-i-use-a-closure-to-define-a-stage-in-a-jenkins-declarative-pipeline – Will Brode Jan 16 '20 at 17:37
  • Such method is not usable in a `post` block even though documentation [here](https://docs.cloudbees.com/docs/admin-resources/latest/pipeline-syntax-reference-guide/declarative-pipeline#post-example) says we can use steps. – Eric Salemi Sep 10 '21 at 13:33
  • @EricSalemi you have to wrap the call in `script { }` I guess. – StephenKing Sep 13 '21 at 21:42
31

You can create a groovy function like this and save it in your git which should be configured as managed library (Configure it in jenkins too):

/path/to/repo-shared-library/vars/sayHello.groovy:

Content:

def call(String name = 'human') {
    echo "Hello, ${name}."
}

You can just call this method in your pipeline using:

@Library('name-of-shared-library')_
pipeline {
    agent any
    stages {
        stage('test') {
            steps {
                sayHello 'Joe'
            }
        }
    }
}

Output:

[Pipeline] echo
Hello, Joe.

You can reuse existing functions which you keep in your library.

lvthillo
  • 28,263
  • 13
  • 94
  • 127
  • 1
    I can't seem to find the answer to "Step does not take a single required parameter - use named parameters instead", I am getting this error exactly at the method call – Benjamin Vison Jan 08 '19 at 19:26
  • what if you want to have multiple functions in a groovy? or is it recommended to have one groovy per function? – ealeon Oct 15 '20 at 16:21
  • @ealeon you can have multiple functions in the shared library and call them from inside your pipeline – lvthillo Oct 23 '20 at 11:02
23

You can also have separate groovy files with all your functions (just to keep things structured and clean), which you can load to file with pipeline:

JenkinsFile.groovy

Map modules = [:]
pipeline {
    agent any
    stages {
        stage('test') {
            steps {
                script{
                    modules.first = load "first.groovy"
                    modules.first.test1()
                    modules.first.test2()
                }
            }
        }
    }
}

first.groovy

def test1(){
    //add code for this method
}
def test2(){
    //add code for this method
}
return this
awefsome
  • 1,431
  • 1
  • 13
  • 11
  • 1
    Can you explain the `return this` statement? Why is that necessary? – YoavKlein Oct 26 '20 at 16:11
  • 1
    This could also be made more clear by defining exactly where each file is saved, relative to one another. – macetw Dec 01 '20 at 16:05
  • 1
    https://www.jenkins.io/doc/pipeline/steps/workflow-cps/ i guess load "first.groovy" will execute the groovy script, and "return this" will return reference to the script it self which contains the methods otherwise you won't get the reference to the methods. – Veaceslav Serghienco Jan 10 '21 at 16:45
23

This worked for me.It can be view with Blue Ocean GUI but when I edit using Blue Ocean GUI it removes methods "def showMavenVersion(String a)".

pipeline {
agent any
stages {
    stage('build') {
        agent any
        steps {
            script {
                showMavenVersion('mvn version')
            }
        }
    }
}

}

def showMavenVersion(String a) {
        bat 'mvn -v'
        echo a
}
Mukesh M
  • 2,242
  • 6
  • 28
  • 41