Because we have several pipelines that have similar logic and need some common properties, we created a groovy file and put some common methods properties in it. But we found the properties defined in the groovy file can't be accessed.
Here is our groovy file: common.groovy:
def MyProp="value"
def myMethod() {
//Fail here
println MyProp
}
return this
JenkinsFile:
node('test') {
checkout scm
def jenkinsCommon = load "common.groovy"
jenkinsCommon.myMethod()
// Below also fail
println jenkinsCommon.MyProp
}
We got the following exception when running jobs with this Jenkinsfile:
groovy.lang.MissingPropertyException: No such property: MyProp for class: groovy.lang.Binding
at groovy.lang.Binding.getVariable(Binding.java:63)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:242)
at org.kohsuke.groovy.sandbox.impl.Checker$6.call(Checker.java:288)
at org.kohsuke.groovy.sandbox.impl.Checker.checkedGetProperty(Checker.java:292)
at com.cloudbees.groovy.cps.sandbox.SandboxInvoker.getProperty(SandboxInvoker.java:29)
at com.cloudbees.groovy.cps.impl.PropertyAccessBlock.rawGet(PropertyAccessBlock.java:20)
at Script1.myMethod(Script1.groovy:4)
at WorkflowScript.run(WorkflowScript:33)
at ___cps.transform___(Native Method)
at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.get(PropertyishBlock.java:74)
at com.cloudbees.groovy.cps.LValueBlock$GetAdapter.receive(LValueBlock.java:30)
at com.cloudbees.groovy.cps.impl.PropertyishBlock$ContinuationImpl.fixName(PropertyishBlock.java:66)
at sun.reflect.GeneratedMethodAccessor286.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
How to define and use the property in a groovy file loaded by pipeline?
If you want to use a variable defined outside the method then you have to annotate it with @Field
annotation, e.g.
import groovy.transform.Field
@Field
def myProp="value"
def myMethod() {
println myProp
}
Every Groovy script gets compiled to a class that extends groovy.lang.Script
class and each method defined in a script is compiled as a class level method, while the rest of script body is executed inside Script.run()
method.
It means that when your myMethod
tries to access myProp
it fails, because myProp
is compiled as a local variable available inside Script.run()
method. This @Field
annotation promotes given variable to a class level variable, so it can be accessed from any method defined in the script.