Как создать расширяемую базовую работу в Jenkins Job DSL? - PullRequest
1 голос
/ 03 июля 2019

Я пытаюсь создать базовую работу, чтобы уменьшить дублирование между нашими работами. Я сделал следующее, но это не работает:

def baseJob(Map m, Closure c = {}) {
    type = m.type ?: 'dev'
    pipelineJob("prefix-${m.name}") {
        parameters {
            stringParam('ONE', 'one', 'Description one')
        }
        c()
    }
}

baseJob(type: 'release', name: 'test') {
    parameters { // <-- Fails here
        stringParam('TWO', 'two', 'Description two')
    }
}

Я получаю следующую ошибку:

ОШИБКА: (сценарий, строка 12) Нет подписи метода: script.parameters () применима для типов аргументов: (script $ _run_closure1 $ _closure4) значения: [script $ _run_closure1 $ _closure4 @ 18b249b3]

Следующее работает как ожидалось:

def baseJob(Map m, Closure c = {}) {
    type = m.type ?: 'dev'
    pipelineJob("prefix-${m.name}") {
        parameters {
            stringParam('ONE', 'one', 'Description one')
        }
        parameters { // <-- This is fine
            stringParam('TWO', 'two', 'Description two')
        }
        c()
    }
}

baseJob(type: 'release', name: 'test')

Так что проблема не в том, что я звоню parameters несколько раз. Кажется, проблема в том, что я звоню parameters изнутри.

Я бы хотел верить, что есть способ выполнить замыкание, чтобы parameters вызывался правильно. Однако я подозреваю, что мне придется узнать больше о Groovy и Jenkins Job DSL, прежде чем я смогу это понять. Поэтому я надеюсь, что есть кто-то, кто знает, как это сделать.

Если у вас есть альтернативное решение для выполнения расширяемой базовой работы, это тоже правильный ответ.

Ответы [ 2 ]

1 голос
/ 03 июля 2019

Вам просто нужно установить делегат замыкания, который вы вызываете, делегату замыкания, в котором вы находитесь:

def baseJob(Map m, Closure c = {}) {
    type = m.type ?: 'dev'
    pipelineJob("prefix-${m.name}") {
        parameters {
            stringParam('ONE', 'one', 'Description one')
        }
        c.delegate = delegate // <-- Just add this line
        c()
    }
}

baseJob(type: 'release', name: 'test') {
    parameters {
        stringParam('TWO', 'two', 'Description two')
    }
}

delegate содержит делегата текущего выполняющегося закрытия.

1 голос
/ 03 июля 2019

Ответ: Метод parameters не реализован в вашем скрипте. Фактически он был реализован внутри конвейера. Класс делегата Closure .

Этот код может помочь вам понять, что там происходит ...

class Test {
    void printMe()
    {
        println "I am in test"
    }    
}

void test(Closure cl)
{
    Test t = new Test()
    cl.delegate = t
    cl()
}

def callMe = { printMe()}
test { 
    printMe() // This will run
    callMe() // This will fail
}

В вашем случае: pipeline (String arg, Closure pipeLineClosure)

pipeLineClousure был реализован внутри класса X , где можно найти метод parameters.как показано ниже кода,

class X
{
  ...
  parameters (Closure cl)
}

Таким образом, возможная реализация может быть:

class Custom{
    String val1
    String val2
    String val3
}

def baseJob(Map m, List<Custom> l) {
    type = m.type ?: 'dev'
    pipelineJob("prefix-${m.name}") {
        l.each{v->
            parameters {
                stringParam(v.val1, v.val2, v.val3)
            }
        }
    }
}

List l = []
l.add new Custom(val1: 'ONE', val2: 'one', val3: 'description')
// can be add more values
baseJob(type: 'release', name: 'test', l)

НАДЕЖДА, ЭТО ПОМОГАЕТ

...