While I was able to define methods, defining variables using Jenkins Shared library seems to an unresolved quest so far.
I added /vars/True.groovy
with this body
def call() {
return true
}
And now inside Jenkinsfile, I tried to test if it works as expected:
println "evaluation ${ true == True }"
But surprise, this fails as it considers true != class True
. My impression is that true == True()
may work but that's not the point, I need a real variable because that whole purpose was to avoid some errors caused by people using wrong case.
So what is the magic trick?
We can set global properties by navigating to “Manage Jenkins -> Configure System -> Global properties option”.
Jenkins pipeline environment variables: You can define your environment variables in both — global and per-stage — simultaneously. Globally defined variables can be used in all stages but stage defined variables can only be used within that stage. Environment variables can be defined using NAME = VALUE syntax.
Setting Stage Level Environment Variable It is by using the env variable directly in the script block. We can define, let us say, USER_GROUP and display it. You will see that the underlying shell also has access to this environment variable. You can also set an environment variable using withEnv block.
It looks like Global Variables defined in the vars
directory must be lower/camel/maybe some other special casing. This isn't stated anywhere in on the Defining global variables section, but there is this note at the top:
The
vars
directory hosts scripts that define global variables accessible from Pipeline. The basename of each*.groovy
file should be a Groovy (~ Java) identifier, conventionallycamelCased
. The matching*.txt
, if present, can contain documentation, processed through the system’s configured markup formatter (so may really be HTML, Markdown, etc., though thetxt
extension is required).
Here is what I tried:
vars/MyTrue.groovy
class MyTrue implements Serializable {
}
vars/myTrue.groovy
class myTrue implements Serializable {
}
vars/mytrue.groovy
class mytrue implements Serializable {
}
vars/doesCasingMatter.groovy
class DoesCasingMatter implements Serializable {
}
And in my pipeline script to test if they are instances or Class
types (no script security enabled here):
echo("MyTrue: ${Class.isInstance(MyTrue)}")
echo("myTrue: ${Class.isInstance(myTrue)}")
echo("mytrue: ${Class.isInstance(mytrue)}")
echo("What bindings are there?: ${binding.variables}")
This prints out:
[Pipeline] echo
MyTrue: true
[Pipeline] echo
myTrue: false
[Pipeline] echo
mytrue: false
[Pipeline] echo
What bindings are there?: [steps:org.jenkinsci.plugins.workflow.cps.DSL@e96256, myTrue:myTrue@8a1ddc5, mytrue:mytrue@392ff649]
Which seems to indicate that something about the class name determines how it gets compiled and created. The first example, which is similar to your vars/True.groovy
, is only imported as a class and not instantiated. The other two are compiled and instantiated and are bound to the script with their defined class names. I think you will have to define your classes differently if you want them to be global variables.
I've found a way to achieve this, but with a slight caveat: the variables must be defined/wrapped within a class. However, this does have the upside of providing better organization, in order not to pollute the global space too much.
For example, we often reuse four standard "magic strings" for build statuses, which I wanted to save as global constants to facilitate interoperability. So I created a global status
class, defined in vars/status.groovy
:
class status {
final String STARTED = "STARTED"
final String SUCCESS = "SUCCESS"
final String FAILURE = "FAILURE"
final String ABORTED = "ABORTED"
}
The constants can then be used by referring to their parent class:
echo status.STARTED
echo status.SUCCESS
echo status.FAILURE
echo status.ABORTED
Specials thanks to @mkobit for pointing me in the right direction!
Variable True
is definitely a variable but it holds a reference to object of type True
(that you defined in /vars/True.groovy
). You have two options
The good one:
Use it this way
println "evaluation ${ true == True() }"
The strange one:
You can override equals()
method in /vars/True.groovy
public boolean equals(obj) {
return obj == true;
}
Then this should work
println "evaluation ${ true == True }"
But it would be really strange and can lead to misunderstandings.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With