Search code examples
groovycicd

Groovy setting variables to be access in multiple files


I am a newer Groovy users and not at all Java more C. So I may be thinking about this problem incorrectly.

I have multiple groovy files that hold functions needed by my main groovy Jenkins script. I am wanting to pass the array of strings I use when I detect errors in my build.

I tried with setting my array of strings as global and tried using fields but I got errors on the field declares and when globals set in main.groovy file the helper.groovy file did not know what the arrays were. Here is what I tried.

// Required to check for changes to input decks
import java.text.SimpleDateFormat
import java.util.Calendar
import hudson.tasks.Mailer
import hudson.model.User
import groovy.transform.Field   //used to try to pass error messages

// This is the default project template
def call(body) {
  // evaluate the body block, and collect configuration into the object
  def pipelineParams = [:]
  body.resolveStrategy = Closure.DELEGATE_FIRST
  body.delegate = pipelineParams
  body()

  //unknown number of strings in the array so make as a list so not defined
 //@field - I commented these @field's out as they caused errors
   List<String> errorMessages = new ArrayList<>()
 //@field
   List<String> warningMessages = new ArrayList<>()
 //@field
   List<String> verboseMessages = new ArrayList<>()

In the help function I have :

#!usr/bin/env groovy
import java.text.SimpleDateFormat
import groovy.time.TimeCategory
import java.io.File
import groovy.transform.Field

def checkMultiModule(String folder, String pathToFolder, List<String> buildModules) {
  //...bunch of code here to make sure all modules required for that folder are found....

//...gets to my checking to see if modules were not found
 // Remove the test from the folder if a module is missing
        if (!allModulesFound) {
            testFile.delete()
            @field warningMessages +="Warning: Module " + testName + "requires " + requiredModules + ". So the modules test were not tested"
        }
        print "Multi-module ${testName} requires ${requiredModules} found = ${allModulesFound}"
        
    }

Besides doing the field wrong I am wondering if field is the correct way to pass the array.


Solution

  • You can't declare "field" variables inside a function. call(body) {...} is a function.

    I have concern that it's a good idea to declare "field" variables in "vars" kind of script. call(body) {...} looks like "vars" script...

    To have lists of errors, warnings, and verbose - is a strange approach.


    Ideally you just need success / not success for a job and this could be managed by exceptions. "Warning" and "Verbose" messages could be just printed out to log.

    throw new Exception('Message here') will terminate your job as any other exceptions.


    If you still want to collect some information - just declare variable in your main jenkins flow before calling any help functions and then pass it into every function you need:

    // just an example - not able to test it
    
    // global part
    script{
        CONTEXT = [
            messages: [
                errors: [],
                warnings: [],
                debug: []
            ]
        ]
    }
    // function
    def myFunc(context) {
        context.messages.errors << "Hello"
        context.messages.warnings << "World"
    }
    // pipeline
    node {
        stage('Hello') {
            myFunc(CONTEXT)
            echo CONTEXT.messages
        }
    }