10

I have 4 groovy scripts (2 are dsl.groovy scripts):

JobConfig.groovy:

class JobConfig {
    final name

    JobConfig(map) {
        name = map['name']
    }
}

topLevel.groovy:

import JobConfig.*

def doSmthWithJobConfig(final JobConfig config) {
    println(config.name);
}

sublevel1.dsl.groovy:

GroovyShell shell = new GroovyShell()
def topLevelScript = shell.parse(new File("topLevel.groovy"))

def jobConfigs = [
    new JobConfig(name: 'JenkinsTestDSLs'),
    new JobConfig(name: 'JenkinsTestDSLs2')
]

jobConfigs.each {
    topLevelScript.doSmthWithJobConfig(it);
}

sublevel2.dsl.groovy:

GroovyShell shell = new GroovyShell()
def topLevelScript = shell.parse(new File("topLevel.groovy"))

def jobConfigs = [
    new JobConfig(name: 'JenkinsTestDSLs3'),
    new JobConfig(name: 'JenkinsTestDSLs4')
]

jobConfigs.each {
    topLevelScript.doSmthWithJobConfig(it);
}

Now if locally I do:

groovyc JobConfig.groovy

,I get no issues with running the scripts locally.

But on jenkins even if I provide the JobConfig.class at the same place where these scripts are, I can't get it running. I read here that I don't need to do any compiling as long as JobConfig.groovy is on the CLASSPATH. How do I do that with jenkins? Or is there another solution?

Community
  • 1
  • 1
despot
  • 7,167
  • 9
  • 44
  • 63

2 Answers2

3

If you don't want to compile the groovy class(es) and then add the compiled classes to the classpath, you can make use of classes within groovy scripts like this:

Given a groovy class

class GroovyClass {
    def GroovyClass(someParameter) {}

    def aMethod() {}
}

you can use the class in groovy script like this

import hudson.model.*
import java.io.File;
import jenkins.model.Jenkins;

def jenkinsRootDir = build.getEnvVars()["JENKINS_HOME"];
def parent = getClass().getClassLoader()
def loader = new GroovyClassLoader(parent)

def someParameterValue = "abc"

def groovyClass = loader.parseClass(new File(jenkinsRootDir + "/userContent/GroovyScripts/GroovyClass.groovy")).newInstance(someParameterValue)

groovyClass.aMethod()
TheEllis
  • 1,666
  • 11
  • 18
  • Can this be used in a Jenkins Pipeline groovy script as well? I get `an exception which occurred: in field locals in field capture in field def in field closures in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@ac028aa Caused: java.io.NotSerializableException: org.jenkinsci.plugins.workflow.cps.CpsGroovyShell$CleanGroovyClassLoader` on the line which gets the class loader `def parent = getClass().getClassLoader()` – raluru Jun 06 '17 at 13:56
  • @TheEllis project running on slave gives an error file not found exception even the file is in workspace on master it works fine , what can be the issue ? – jayant singh Sep 24 '17 at 10:14
  • i used def Job = loader.parseClass(new hudson.FilePath(Jenkins.getInstance().getComputer(build.getEnvVars()['NODE_NAME']).getChannel(),build.getEnvVars()["WORKSPACE"] + "/groovy_modules/GroovyHelper.groovy")).newInstance() but error came that hudson.FilePath can not be used in hudson.FilePath – jayant singh Sep 24 '17 at 10:18
  • 2
    @jayantsingh Try using `loader.parseClass(readFile 'PATH_TO_FILE')` instead. readFile is a Jenkins utility step made to handle files on slaves as well. – andrzej.szmukala Nov 09 '17 at 12:59
0

What I would do is following, instead of trying to make it all work manually, I would create maven project or gradle one and organize your groovy files within resulted project. When configure maven or gradle to run it. Once maven or gradle runs it without any issues, you can give it to jenkins.

Jenkins takes maven projects for sure and for gradle you will have to check, however one thing for sure, is maven runs you groovy project locally it will run without any issues under Jenkins as well.

Please try, let me know.

MeIr
  • 7,236
  • 6
  • 47
  • 80