I'm currently refactoring our Jenkins pipeline from a pipeline project to a multibranch pipeline project and trying to make some functionality more modular and trying to migrate more code to a shared pipeline project. However, this results in compile errors that feels related to groovy scoping, where it tries to use the same scope as the function when calling to a third party library instead of using the global scope.
The original function resided in my scripted pipeline jenkinsfile and looks like this:
def bootstrapPythonEnvironment( String client, String credentials, String label = "#head" ) {
String bootstrapWorkspace = "${client}_BootstrapWorkspace"
def p4 = p4(credential: credentials,
workspace: manualSpec(
charset: 'winansi',
name: bootstrapWorkspace,
spec: clientSpec(
view: "//MyGameContent/BuildScripts/Python/... //${bootstrapWorkspace}/BootstrapScripts/..." )
))
p4.run('sync', "//MyGameContent/...", label)
}
However, when moving it from the Jenkinsfile to: vars/BuildTools.groovy
and I call it through:
BuildTools.bootstrapJenkinsEnvironment( env.MyClient, 'CSSBuildmachine', '#head' )
then I get the following error:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: static BuildTools.bootstrapPythonEnvironment() is applicable for argument types: (java.lang.String, java.lang.String, java.lang.String) values: [jenkins-Stekdatorn-TestWorkspace-null-0, CSSBuildmachine, ...]
Possible solutions: bootstrapPythonEnvironment(java.lang.String, java.lang.String, java.lang.String), bootstrapPythonEnvironment(java.lang.String, java.lang.String)
So I changed the function declaration to incluide static:
static def bootstrapPythonEnvironment( String client, String credentials, String label = "#head" )
This helps a bit, but now the error I get is:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: static BuildTools.clientSpec() is applicable for argument types: (java.util.LinkedHashMap) values: [[view://MyGameContent/BuildScripts/Python/... //jenkins-Stekdatorn-TestWorkspace-null-0_BootstrapWorkspace/BootstrapScripts/...]]
at groovy.lang.MetaClassImpl.invokeStaticMissingMethod(MetaClassImpl.java:1501)
at groovy.lang.MetaClassImpl.invokeStaticMethod(MetaClassImpl.java:1487)
at org.codehaus.groovy.runtime.callsite.StaticMetaClassSite.call(StaticMetaClassSite.java:53)
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 BuildTools.bootstrapPythonEnvironment(BuildTools.groovy:11)
at WorkflowScript.run(WorkflowScript:18)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:84)
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.GeneratedMethodAccessor324.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.CollectionLiteralBlock$ContinuationImpl.dispatch(CollectionLiteralBlock.java:55)
at com.cloudbees.groovy.cps.impl.CollectionLiteralBlock$ContinuationImpl.item(CollectionLiteralBlock.java:45)
at sun.reflect.GeneratedMethodAccessor320.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.dispatchOrArg(FunctionCallBlock.java:107)
at com.cloudbees.groovy.cps.impl.FunctionCallBlock$ContinuationImpl.fixArg(FunctionCallBlock.java:83)
at sun.reflect.GeneratedMethodAccessor324.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ContinuationGroup.methodCall(ContinuationGroup.java:87)
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.GeneratedMethodAccessor324.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at com.cloudbees.groovy.cps.impl.ContinuationPtr$ContinuationImpl.receive(ContinuationPtr.java:72)
at com.cloudbees.groovy.cps.impl.ConstantBlock.eval(ConstantBlock.java:21)
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.CpsThread.runNextChunk(CpsThread.java:186)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.run(CpsThreadGroup.java:370)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup.access$200(CpsThreadGroup.java:93)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:282)
at org.jenkinsci.plugins.workflow.cps.CpsThreadGroup$2.call(CpsThreadGroup.java:270)
at org.jenkinsci.plugins.workflow.cps.CpsVmExecutorService$2.call(CpsVmExecutorService.java:66)
at java.util.concurrent.FutureTask.run(Unknown Source)
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(Unknown Source)
at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at java.lang.Thread.run(Unknown Source)
I have tried moving this file to src/com/coffeestain/build/Python.groovy and putting it in there but in the function:
class Python {
static def bootstrap( String client, String credentials, String label = "#head" ) {
// Snipped out code
}
}
but it just gives me a similar message when I'm trying to import it with:
@Library('MyGameBuildtools') import com.coffeestain.build.*
and call it with:
Python.bootstrap( env.P4CLIENT, 'CSSBuildmachine', "#head" )
However, this gives me the same error in another form:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: static com.coffeestain.build.Python.clientSpec() is applicable for argument types: (java.util.LinkedHashMap) values: [[view://MyGameContent/BuildScripts/Python/... //jenkins-Stekdatorn-TestWorkspace-null-0_BootstrapWorkspace/BootstrapScripts/...]]
My current workaround is to add it to the file vars/bootstrapPythonEnvironment.groovy with the definition:
def call( String client, String credentials, String label = "#head" ) {
// Snipped out code
}
But this feels unfeasible in the long run to have a file for each function I add.
clientSpec()coming from? Sems at the beginning it also needed static. Can you add the full version of your groovy files (can be redacted, but function signatures and function calls should be left intact)? - Dominik Gebhartcontextto your library function, and use it likecontext.p4([...] context.clientSpec([...]))and fill the context withthisin the call to your library function? See also jenkins.io/doc/book/pipeline/shared-libraries the Accessing Steps part. - Dominik Gebhart