1

I have a Jenkinsfile with some properties, for example

trace = false

userNotifications = [
    build_master :                 [name : 'name',
                                    email : 'email',
                                    slackid: 'slack id',
                                    slackchannel: 'slack channel']
]
env.aProperty = "aValue"
node('COMPILE')
{
...
}

I want to parse the above Jenkinsfile inside groovy code in order to access some of the property values.

When I use GroovyShell like this

        Binding binding = new Binding()
        GroovyShell shell = new GroovyShell(binding)
        Object groovyDsl = shell.evaluate(clean)

I get this error

groovy.lang.MissingMethodException: No signature of method: Script1.node() is applicable for argument types: (String, Script1$_run_closure1) values: [COMPILE, Script1$_run_closure1@7d804e7]

I might be able to get around the particular error with some Groovy meta-programming, however, I am unsure if this is the right direction. My question is what is the best way to parse a Jenkinsfile in Groovy code? This is Groovy DSL at the end of the day and I would expect it to be more straightforward.

2 Answers 2

3

Here is how I eventually did what I wanted:

import org.codehaus.groovy.control.CompilerConfiguration

class JenkinsfileParser {
    static void main(String[] args) {
        LinkedHashMap vars = JenkinsfileParser.parse('Jenkinsfile' as File)
        println vars.toString()
    }

    static LinkedHashMap parse(File jenkinsfile) {
        CompilerConfiguration config = new CompilerConfiguration()
        config.scriptBaseClass = JenkinsfileBaseClass.class.name
        Binding binding = new Binding()
        GroovyShell shell = new GroovyShell(this.class.classLoader, binding, config)
        String clean = jenkinsfile.text.replace('import hudson.model.*', '')
                .replace('import hudson.EnvVars', '')
        Script script = shell.parse(clean)
        script.run()
        return binding.variables
    }

    static abstract class JenkinsfileBaseClass extends Script {
        LinkedHashMap<String, Closure> nodeClosures = new LinkedHashMap<>()
        LinkedHashMap env = new LinkedHashMap()
        CurrentBuild currentBuild = new CurrentBuild()
        LinkedHashMap parallelClosures = new LinkedHashMap<>()

        void node(String name, Closure closure) {
            nodeClosures.put(name, closure)
        }

        void parallel(LinkedHashMap closures) {
            parallelClosures.putAll(closures)
        }

        class CurrentBuild {
            List<String> expectedResults = new ArrayList<>()

            boolean resultIsBetterOrEqualTo(String expected) {
                expectedResults << expected
                return true
            }
        }
    }
}

The JenkinsfileBaseClass is specific to my Jenkinsfile and would need adaptation for a different Jenkinsfile.

Relevant documentation can be found here: https://groovy-lang.org/integrating.html

I tried using the implementation group: 'org.jenkins-ci.main', name: 'jenkins-core', version: '2.9' package from the maven repository http://repo.jenkins-ci.org/public/, however, there doesn't seem to be anything in there useful for my case.

Let me know if there's a better or more elegant way of doing it.

Sign up to request clarification or add additional context in comments.

Comments

0

DSLs are context specific and can't be run out of context.

you could try

  • Script Console under Manage Jenkins.

1 Comment

Sorry for not clarifying this earlier, but I do not use Jenkins. All I want to do is simply extract some properties from a Jenkinsfile from within a standalone Groovy script.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.