Search code examples
groovyjenkins-pipelinejenkins-declarative-pipeline

Jenkins pipeline: how to access custom globals from groovy scripts in vars dir?


I am able to declare a class instance as global like this :

gitUtils = new GitUtils()

pipeline {
  ...
  echo "hello: " + gitUtils.doSomething()
}

But if the pipeline calls a function defined as groovy script in "vars" directory, gitUtils is not visible anymore

def call() {
  def something = gitUtils.doSomething()
}

I also tryed to use @Field but it changes nothing. Note that all the pipeline is defined in the shared library (project jenkinsfile just calls a function from this shared library).

How to access gitUtils from groovy scripts in /vars in this example ?

I know we could pass the instance as parameter of function declared in /vars but more you have functions using you utilitary class, more it is ugly. Would you imagine to pass 'echo' or 'sh' function as parameter ? No, here is the same.

I know we could not use at all classes defined in src and define groovy script with multiple public methods. Here we could imagine create in /vars a gitutils.groovy with many public method. But this would imply to use 'script' closure in the pipeline to choose which method we want, like this:

script {
  gitutils.doSomething()
}

I dont want this. I would pref to create a single function per groovy script in /vars. Thus, we can call them directly in steps, like this:

 steps {
    myGroovyScriptFunction()
 }

But by doing such, the number of function increase and functions are not organized correctly. That is why the idea is to create "big step function" in /vars which use inside more generic functions, from instances of classes (even static in the better case). So, instead of creating a new instance in each groovy script, I would like a global instance.

Context: declarative pipeline, openshift jenkins, slave with dynamic pod template


Solution

  • It's not possible because of JENKINS-42360.

    The best way to use global steps without a script block is in my opinion to define an instance of GitUtils and use it directly in the global steps. If you need the pipeline step context you can pass it to the constructor:

    # vars/myStep.groovy
    
    import my.packagename.GitUtils
    
    def call() {
        GitUtils gitUtils = new GitUtils(steps) 
        ...
    } 
    

    then you can use the steps with inside GitUtils as described here. Remember to define GitUtils to implement Serializable as per documentation.