Reputation: 42574
I'm trying to create a base job, to reduce the duplication between our jobs. I did the following, but it's not working:
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')
}
}
I get the following error:
ERROR: (script, line 12) No signature of method: script.parameters() is applicable for argument types: (script$_run_closure1$_closure4) values: [script$_run_closure1$_closure4@18b249b3]
The following works as expected:
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')
So the problem isn't that I call parameters
multiple times. The problem seems to be that I call parameters
from inside a closure.
I'd like to believe that there is a way to execute the closure, so that parameters
is called correctly. However, I suspect that I will have to learn a lot more about Groovy and Jenkins Job DSL, before I am able to figure it out. So I'm hoping that there is someone that knows how to do it.
If you have an alternative solution to accomplishing an extendable base job, that's a valid answer as well.
Upvotes: 4
Views: 654
Reputation: 42574
You just need to set the delegate of the closure that you're calling to the delegate of the closure that you are in:
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
contains the delegate of the currently executing closure.
Upvotes: 3
Reputation: 1621
Answer : The method
parameters
is not implemented inside your script. It was actually implemented inside the pipeline Closure delegate class.
This code may help you to understand what's happening there....
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
}
In Your case :
pipeline (String arg, Closure pipeLineClosure)
pipeLineClousure had been implemented inside a class X where the parameters
method can be Found. like shown below code,
class X
{
...
parameters (Closure cl)
}
So the possible implementation could be :
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)
HOPE IT HELPS
Upvotes: 3