Как разобрать Jenkinsfile из Groovy кода - PullRequest
0 голосов
/ 17 июня 2020

У меня есть файл Jenkins с некоторыми свойствами, например

trace = false

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

Я хочу проанализировать указанный выше файл Jenkins внутри groovy кода, чтобы получить доступ к некоторым значениям свойств.

Когда я использую GroovyShell следующим образом

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

, я получаю эту ошибку

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

Я могу обойти конкретную ошибку с помощью некоторого Groovy метапрограммирования, однако я Я не уверен, что это правильное направление. Мой вопрос в том, как лучше всего разобрать файл Jenkins в коде Groovy? В конце концов, это Groovy DSL, и я ожидал бы, что он будет более простым.

Ответы [ 2 ]

0 голосов
/ 17 июня 2020

Вот как я в конечном итоге сделал то, что хотел:

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
            }
        }
    }
}

JenkinsfileBaseClass указан c в моем Jenkinsfile и потребует адаптации для другого Jenkinsfile.

Соответствующее документацию можно найти здесь: https://groovy-lang.org/integrating.html

Я пробовал использовать пакет implementation group: 'org.jenkins-ci.main', name: 'jenkins-core', version: '2.9' из репозитория maven http://repo.jenkins-ci.org/public/, однако, похоже, там нет ничего полезного для моего случая.

Дайте мне знать, есть ли лучший или более элегантный способ сделать это.

0 голосов
/ 17 июня 2020

DSL определяются контекстом c и не могут быть запущены вне контекста.

вы можете попробовать

  • Script Console в разделе «Управление Jenkins».
...