我有一个Jenkins管道,触发多个构建作业在一个单一的项目。每个构建作业都有不同的参数,这些参数在作业期间动态生成。还有一个字符串参数,作业应该在哪个从属服务器上运行。该列表是一个多行字符串,被n分割。
这是我得到的:
def projectName = "${PROJECT_NAME}"
def slaveList = "${SLAVE_LIST}".split("n")
def gradleTasks = "${GRADLE_TASKS}"
def slaveClosure = { slaveNum ->
build job: projectName, parameters: [
[$class: 'LabelParameterValue', name: 'slaveAol', label: slaveList[slaveNum]],
[$class: 'StringParameterValue', name: 'gradleTasks', value: gradleTasks]
]
}
def parallelSlaveMap = [:]
for (int i = 0; i < slaveList.size(); i++) {
parallelSlaveMap.put("slave${i}", slaveClosure(i))
}
parallel(parallelSlaveMap)
但这给了我以下错误:
java.lang.IllegalArgumentException: Expected a closure or failFast but found slave0=org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper@5caff0a8
at org.jenkinsci.plugins.workflow.cps.steps.ParallelStep$DescriptorImpl.newInstance(ParallelStep.java:202)
at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:134)
at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:113)
at groovy.lang.GroovyObject$invokeMethod.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:151)
at org.kohsuke.groovy.sandbox.GroovyInterceptor.onMethodCall(GroovyInterceptor.java:21)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:115)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onMethodCall(SandboxInterceptor.java:103)
at org.kohsuke.groovy.sandbox.impl.Checker$1.call(Checker.java:149)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedCall(Checker.java:146)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.methodCall(SandboxInvoker.java:15)
at WorkflowScript.run(WorkflowScript:44)
作为参考,脚本中的第44行是"parallel"行。
我做错了什么?我不确定是否有一种更简单的方法来基于slave的参数列表动态创建并行构建作业。
对slaveClosure(i)
的调用初始化了一个对象并将其分配给映射,这是jenkins没有预料到的。如果要使用这种模式,可能需要在闭包周围使用外部函数,该函数返回闭包而不求值。相反,我使用以下方法来生成并行作业。在每次迭代中存储索引值非常重要,因为闭包是在运行时求值的。
def projectName = "${PROJECT_NAME}"
def slaveList = "${SLAVE_LIST}".split("n")
def slaveMap = [:]
def gradleTasks = "${GRADLE_TASKS}"
for (int i = 0; i < slaveList.size(); i++) {
def index = i
slaveMap['slave' + index] = {build job: projectName, parameters: [
[$class: 'LabelParameterValue', name: 'slaveAol', label: slaveList[index]],
[$class: 'StringParameterValue', name: 'gradleTasks', value: gradleTasks]
]
}
}
parallel slaveMap