jenkinsci / templating-engine-plugin

create tool-agnostic, templated pipelines to be shared by multiple teams
https://jenkinsci.github.io/templating-engine-plugin/latest/
Apache License 2.0
171 stars 58 forks source link

[Bug]: Failed to serialize hudson.model.Actionable#Actions for class org.jenkinsci.plugins.workflow.job.WorkflowRun #241

Closed ux123 closed 3 years ago

ux123 commented 3 years ago

Jenkins Version

Jenkins 2.235.1

JTE Version

2.2.2

Bug Description

When trying to write to currentBuild.description in the pipeline template, the build fails with the error Failed to serialize hudson.model.Actionable#Actions for class org.jenkinsci.plugins.workflow.job.WorkflowRun. Doing the same in an initialize library doesn't result in a failure. Also, before moving any of the pipeline code into JTE libraries, we were able to write to the currentBuild variable successfully in the Jenkinsfile.

Relevant log output

hudson.remoting.ProxyException: hudson.AbortException: java.lang.RuntimeException: Failed to serialize hudson.model.Actionable#actions for class org.jenkinsci.plugins.workflow.job.WorkflowRun
    at org.jenkinsci.plugins.workflow.steps.ErrorStep$Execution.run(ErrorStep.java:63)
    at org.jenkinsci.plugins.workflow.steps.ErrorStep$Execution.run(ErrorStep.java:50)
    at org.jenkinsci.plugins.workflow.steps.SynchronousStepExecution.start(SynchronousStepExecution.java:38)
    at org.jenkinsci.plugins.workflow.cps.DSL.invokeStep(DSL.java:319)
    at org.jenkinsci.plugins.workflow.cps.DSL.invokeMethod(DSL.java:193)
    at org.jenkinsci.plugins.workflow.cps.CpsScript.invokeMethod(CpsScript.java:122)
    at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:48)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
    at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.methodCall(DefaultInvoker.java:20)
    at WorkflowScript.call(WorkflowScript:5)
    at org.boozallen.plugins.jte.init.primitives.injectors.StepWrapperCPS.invoke(script16347498880811562650911.groovy:67)
    at org.boozallen.plugins.jte.init.primitives.injectors.StepWrapperCPS.call(script16347498880811562650911.groovy:41)
    at WorkflowScript.run(WorkflowScript:111)
    at ___cps.transform___(Native Method)
    at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:86)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:113)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:83)
    at sun.reflect.GeneratedMethodAccessor143.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:89)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:113)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixName(FunctionCallBlock.java:78)
    at sun.reflect.GeneratedMethodAccessor148.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
Caused: hudson.remoting.ProxyException: org.codehaus.groovy.runtime.InvokerInvocationException: hudson.AbortException: java.lang.RuntimeException: Failed to serialize hudson.model.Actionable#actions for class org.jenkinsci.plugins.workflow.job.WorkflowRun
    at org.boozallen.plugins.jte.init.primitives.injectors.StepWrapperCPS.invoke(script16347498880811562650911.groovy:69)
    at org.boozallen.plugins.jte.init.primitives.injectors.StepWrapperCPS.call(script16347498880811562650911.groovy:41)
    at WorkflowScript.run(WorkflowScript:111)
    at ___cps.transform___(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at org.codehaus.groovy.reflection.CachedConstructor.invoke(CachedConstructor.java:83)
    at org.codehaus.groovy.runtime.callsite.ConstructorSite$ConstructorSiteNoUnwrapNoCoerce.callConstructor(ConstructorSite.java:105)
    at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallConstructor(CallSiteArray.java:60)
    at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callConstructor(AbstractCallSite.java:235)
    at com.cloudbees.groovy.cps.sandbox.DefaultInvoker.constructorCall(DefaultInvoker.java:25)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:97)
    at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:83)
    at sun.reflect.GeneratedMethodAccessor143.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
    at com.cloudbees.groovy.cps.impl.LocalVariableBlock$LocalVariable.get(LocalVariableBlock.java:39)
    at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
    at com.cloudbees.groovy.cps.impl.LocalVariableBlock.evalLValue(LocalVariableBlock.java:28)
    at com.cloudbees.groovy.cps.LValueBlock$BlockImpl.eval(LValueBlock.java:55)
    at com.cloudbees.groovy.cps.LValueBlock.eval(LValueBlock.java:16)
    at com.cloudbees.groovy.cps.Next.step(Next.java:83)
    at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:174)
    at com.cloudbees.groovy.cps.Continuable$1.call(Continuable.java:163)
    at org.codehaus.groovy.runtime.GroovyCategorySupport$ThreadCategoryInfo.use(GroovyCategorySupport.java:129)
    at org.codehaus.groovy.runtime.GroovyCategorySupport.use(GroovyCategorySupport.java:268)
    at com.cloudbees.groovy.cps.Continuable.run0(Continuable.java:163)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.access$001(SandboxContinuable.java:18)
    at org.jenkinsci.plugins.workflow.cps.SandboxContinuable.run0(SandboxContinuable.java:51)
    at org.jenkinsci.plugins.workflow.cps.CpsThread.runNextChunk(CpsThread.java:185)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:400)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$400(CpsThreadGroup.java:96)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:312)
    at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:276)
    at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:67)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at hudson.remoting.SingleLaneExecutorService$1.run(SingleLaneExecutorService.java:131)
    at jenkins.util.ContextResettingExecutorService$1.run(ContextResettingExecutorService.java:28)
    at jenkins.security.ImpersonatingExecutorService$1.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

Steps to Reproduce

Pipeline template

    node('docker') {
    def mvn = Artifactory.newMavenBuild()
    def server = Artifactory.server('My Artifactory')
    def items = ['item1', 'item2']
    try{
        timeout(time: 120, unit: 'MINUTES') {
            initialize(mvn, server, items)
            for (item in pipelineConfig.changedItems) {
                if (item == "item1"){
                    currentBuild.description += " > ${item}" //fails
                    clean_item(mvn, item)
                    ...
                }
            }                        
        }
    }
}

initialize.groovy

def call(def maven, def mServer, def mItems){
    stage ("Initialize") {
        currentBuild.description = "" //doesn't fail

        def mTool = 'maven-3.6.2'

        maven.tool = mTool
        maven.opts = '-Xms512m -Xmx1024m -Xss2M'

        maven.resolver server: mServer, releaseRepo: 'libs-releases' , snapshotRepo: 'libs-snapshot'

        pipelineConfig.scmVars = checkout scm
        pipelineConfig.POM_FILE = "pom.xml"
        pipelineConfig.changedItems = []

        def lastSuccessfulCommit = getLastSuccessfulCommit()
        def currentCommit = commitHashForBuild( currentBuild.rawBuild )

        if (lastSuccessfulCommit) {
            for (mItem in mItems){
                noOfChanges = sh(returnStdout: true, script: "git diff --name-only \"$currentCommit\" \"^$lastSuccessfulCommit\" | grep \"$mItem/.*\" | wc -l").trim()
                if(!noOfChanges.equals("0")){
                    pipelineConfig.changedItems.add("${mItem}")
                    pipelineConfig.changedItems.unique()
                }
            }
        } 
    }
return maven
}

def getLastSuccessfulCommit() {
    def lastSuccessfulHash = null
    def lastSuccessfulBuild = currentBuild.rawBuild.getPreviousSuccessfulBuild()
    if ( lastSuccessfulBuild ) {
        lastSuccessfulHash = commitHashForBuild( lastSuccessfulBuild )
    }
    return lastSuccessfulHash
}

@NonCPS
def commitHashForBuild( build ) {
    def scmAction = build?.actions.find { action -> action instanceof jenkins.scm.api.SCMRevisionAction }
    return scmAction?.revision?.hash
}

clean_item.groovy

def call(def maven, def changedItem){
    stage ("Clean ${changedItem}"){
        maven.run pom: "${pipelineConfig.POM_FILE}".toString(), goals: "-B clean"
    }
return maven
}
psig-bah commented 3 years ago

@ux123 tweaked your samples a bit to test from my environment, but was able to recreate the error.

Could you try updating this line in initialize.groovy: pipelineConfig.changedItems.add("${mItem}") to: pipelineConfig.changedItems.add("${mItem}".toString())

I think that's the GString causing the error.

cokieffebah commented 3 years ago

I recommend returning your own object/hash from initialize(...) and using that instead of adding things to pipelineConfig.

ux123 commented 3 years ago

@ux123 tweaked your samples a bit to test from my environment, but was able to recreate the error.

Could you try updating this line in initialize.groovy: pipelineConfig.changedItems.add("${mItem}") to: pipelineConfig.changedItems.add("${mItem}".toString())

I think that's the GString causing the error.

Thanks! I needed to append .toString() to a different variable in the initialize.groovy that was assigned {BUILD_NUMBER}. Doing pipelineConfig.buildNumber = "${BUILD_NUMBER}".toString() fixed the issue for me. Thanks so much for your help.