为什么在尝试从常规管道作业启动多分支构建作业时出现异常?

Why am I getting an exception when attempting to kickoff a multibranch build job from a regular pipeline job?

我正在做的事情类似于 接受的回复。我有一个常规的管道作业,它试图启动一个多分支管道作业,用于一个已经被扫描和注册的特定分支。

代码如下:

 rc = build job: mb_job_name, 
       wait: true

其中 mb_job_name 包含下游作业的名称加上分支名称。

奇怪的是下游作业实际上启动并运行良好。我看到预期的:

Scheduling project: playground-sandbox » Chris » test-jenkins-mb » dv_main_117_chris2

输出。问题是,在我启动下游作业的常规管道作业中,就在构建作业调用和预期的 Scheduling... 输出之后,它会抛出如下异常:

an exception which occurred:
    in field com.cloudbees.groovy.cps.impl.BlockScopeEnv.locals
    in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@28280b21
    in field com.cloudbees.groovy.cps.impl.ProxyEnv.parent
    in object com.cloudbees.groovy.cps.impl.BlockScopeEnv@48fc924d
    in field com.cloudbees.groovy.cps.impl.CallEnv.caller
    in object com.cloudbees.groovy.cps.impl.FunctionCallEnv@3b112c7a
    in field com.cloudbees.groovy.cps.Continuable.e
    in object org.jenkinsci.plugins.workflow.cps.SandboxContinuable@a5e88d8
    in field org.jenkinsci.plugins.workflow.cps.CpsThread.program
    in object org.jenkinsci.plugins.workflow.cps.CpsThread@6faa034a
    in field org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.threads
    in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@d6a022e
    in object org.jenkinsci.plugins.workflow.cps.CpsThreadGroup@d6a022e
Caused: java.io.NotSerializableException: groovy.json.internal.LazyMap
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:926)
    at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
    at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
    at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
    at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
    at java.util.HashMap.internalWriteEntries(HashMap.java:1793)
    at java.util.HashMap.writeObject(HashMap.java:1363)
    at sun.reflect.GeneratedMethodAccessor124.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.jboss.marshalling.reflect.JDKSpecific$SerMethods.callWriteObject(JDKSpecific.java:156)
    at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:191)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1028)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1019)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1019)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1019)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
    at org.jboss.marshalling.river.BlockMarshaller.doWriteObject(BlockMarshaller.java:65)
    at org.jboss.marshalling.river.BlockMarshaller.writeObject(BlockMarshaller.java:56)
    at org.jboss.marshalling.MarshallerObjectOutputStream.writeObjectOverride(MarshallerObjectOutputStream.java:50)
    at org.jboss.marshalling.river.RiverObjectOutputStream.writeObjectOverride(RiverObjectOutputStream.java:179)
    at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:344)
    at java.util.concurrent.ConcurrentSkipListMap.writeObject(ConcurrentSkipListMap.java:1437)
    at sun.reflect.GeneratedMethodAccessor146.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.jboss.marshalling.reflect.JDKSpecific$SerMethods.callWriteObject(JDKSpecific.java:156)
    at org.jboss.marshalling.reflect.SerializableClass.callWriteObject(SerializableClass.java:191)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1028)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteFields(RiverMarshaller.java:1082)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteSerializableObject(RiverMarshaller.java:1040)
    at org.jboss.marshalling.river.RiverMarshaller.doWriteObject(RiverMarshaller.java:920)
    at org.jboss.marshalling.AbstractObjectOutput.writeObject(AbstractObjectOutput.java:58)
    at org.jboss.marshalling.AbstractMarshaller.writeObject(AbstractMarshaller.java:111)
    at org.jenkinsci.plugins.workflow.support.pickles.serialization.RiverWriter.lambda$writeObject[=12=](RiverWriter.java:144)
    at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.GroovySandbox.runInSandbox(GroovySandbox.java:237)
    at org.jenkinsci.plugins.workflow.support.pickles.serialization.RiverWriter.writeObject(RiverWriter.java:143)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:553)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgram(CpsThreadGroup.java:530)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.saveProgramIfPossible(CpsThreadGroup.java:517)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:441)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access0(CpsThreadGroup.java:96)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.call(CpsThreadGroup.java:312)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.call(CpsThreadGroup.java:276)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService.call(CpsVmExecutorService.java:67)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at hudson.remoting.SingleLaneExecutorService.run(SingleLaneExecutorService.java:136)
    at jenkins.util.ContextResettingExecutorService.run(ContextResettingExecutorService.java:28)
    at jenkins.security.ImpersonatingExecutorService.run(ImpersonatingExecutorService.java:59)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
Finished: FAILURE

在一般意义上,我理解这意味着我有 code/variables Jenkins 无法序列化,但我不清楚它是什么。

我尝试将我的代码更改为更简单的形式:

build mb_job_name

我也尝试用带有作业名称的字符串文字替换 mb_job_name 变量,但没有任何改进。

更新

看起来这与我在构建调用之前有以下代码这一事实有关:

def jsonSlurper = new JsonSlurper()
def pl = jsonSlurper.parseText(payload)
def repo_name = pl.repository.name

如果我删除 def jsonSlurper = new JsonSlurper() 那么我就不会再得到异常。不幸的是,我需要解析一些 JSON 所以我有点需要创建对象。可能需要以某种方式使用@NonCPS 注释。

Jenkins 中的多分支作业文件夹结构与常规作业不同,要从远程作业触发它,您必须指定 'JOBNAME/BRANCHNAME'。 可能是你弄错了格式,因此它是错误的。看看我下面的例子。

node {
    stage('call multibranch pipeline') {
        def res = build job:'test0/main'
    }
}

在我的示例中,test0 - 是多分支作业名称,main 是分支。我没有使用 wait: true 因为 wait 默认值在 build DSL

中是 True

输出

如果您想在管道代码中使用 JsonSlurper,请改用 JsonSlurperClassic。不同之处在于第二个生成 LinkedHashMap,一个可序列化的对象。第一个生成不可序列化的 LazyMap

在管道代码中有不同的方法来解析JSON,您可以查看此博客post以获取更多信息-https://e.printstacktrace.blog/how-to-catch-curl-response-in-jenkins-pipeline/#using-groovy-json-jsonslurperclassic-to-parse-the-response

正如您所说,您需要使用@NonCPS 来告诉Jenkins CPS 它处于无法序列化程序状态的状态。这是通过将不可序列化的代码移动到函数中来完成的:

@NonCPS
def parseRepositoryName(payload) {
    def jsonSlurper = new JsonSlurper()
    def pl = jsonSlurper.parseText(payload)
    return pl.repository.name
}

将此添加到代码末尾,并将旧的 json 解析代码替换为对新函数的函数调用:

def repo_name = parseRepositoryName(payload)