我有一个管道作业,该管道作业运行以下groovy脚本,但是一旦jenkins看到带有sh命令的行,就会引发以下异常。即使使用@NonCPS注释了该方法,我似乎也无法摆脱这种异常。 我想念什么?
node {
stage('Kill Long Running jobs') {
try {
def longRunningJobs = getLongRunningJobs()
if (longRunningJobs.size() > 0) {
def metricData = killAndGetMetricData(longRunningJobs)
if (metricData.size() > 0) {
def payload = metricData.join('\n')
sh("curl -X POST ${ENDPOINT} --data-binary ${payload}")
}
} else {
echo 'No long running jobs'
}
} catch (err) {
throw err
}
}
}
@NonCPS
def getLongRunningJobs() {
def timeInMillis = 24*3600*1000
def rightNow = Calendar.getInstance()
return Jenkins.instance.getAllItems(Job.class).findAll { Job job ->
job.isBuilding()
}.collect { Job job ->
//find all matching items and return a list but if null then return an empty list
job.builds.findAll { Run run ->
run.isBuilding() && ((rightNow.getTimeInMillis() - run.getStartTimeInMillis()) > timeInMillis)
} ?: []
}.sum()
}
错误:
an exception which occurred:
in field com.cloudbees.groovy.cps.impl.BlockScopeEnv.locals
in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@5dc513b2
in field com.cloudbees.groovy.cps.impl.ProxyEnv.parent
in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@788991c6
in field com.cloudbees.groovy.cps.impl.ProxyEnv.parent
in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@76c7fb80
in field com.cloudbees.groovy.cps.impl.CallEnv.caller
in object com.cloudbees.groovy.cps.impl.FunctionCallEnv@41b11dd6
in field com.cloudbees.groovy.cps.impl.ProxyEnv.parent
in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@4a0dec81
in field com.cloudbees.groovy.cps.impl.ProxyEnv.parent
in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@21e5f4ba
in field com.cloudbees.groovy.cps.impl.ProxyEnv.parent
in object com.cloudbees.groovy.cps.impl.TryBlockEnv@69fbc75f
in field com.cloudbees.groovy.cps.impl.ProxyEnv.parent
in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@430907d9
in field com.cloudbees.groovy.cps.impl.CallEnv.caller
in object com.cloudbees.groovy.cps.impl.FunctionCallEnv@779bb867
in field com.cloudbees.groovy.cps.Continuable.e
in object org.jenkinsci.plugins.workflow.cps.SandboxContinuable@e363a3
in field org.jenkinsci.plugins.workflow.cps.CpsThread.program
in object org.jenkinsci.plugins.workflow.cps.CpsThread@29a42aee
in field org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.threads
in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@23c20513
in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@23c20513
Caused: java.io.NotSerializableException: org.jenkinsci.plugins.workflow.job.WorkflowRun
at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:926)
答案 0 :(得分:0)
您真的不应该将沉重的内部Jenkins对象(例如“工作”)泄漏到管道的CPS部分中。由于Jenkins的管道作业类型需要能够随时挂起和恢复管道,因此管道中的所有对象都需要可序列化-大多数内部Jenkins对象在设计时就没有考虑到这一点。
如果您真的需要在管道中使用Jenkins内部对象,请将所有内容包装到@NonCPS
方法中。根据经验:在管道CPS代码中只能使用“简单”对象,例如String或List。对于上面的代码,我建议:
getLongRunningJobs()
的字符串列表(工作名称?),然后修改killAndGetMetricData()
以获取字符串列表有关更多技术细节,请参见https://www.jenkins.io/blog/2017/02/01/pipeline-scalability-best-practice/