I'm iterating through building a Jenkins pipeline shared library, so my Jenkinsfile is a little cleaner.
I'm using the following page for guidance: https://jenkins.io/doc/book/pipeline/shared-libraries/ .
I first defined several methods in individual files, like "vars/methodName.groovy
", with a "call()
" method in the code. This works ok, and I particularly note that "println
" calls in these methods are seen in the Jenkins console output.
I then decided I wanted to save some state between method calls, so I added a new file in "vars
" named "uslutils.groovy
" that begins like this (minus some required imports):
class uslutils implements Serializable {
I defined some "with<property>
" methods that set a property and return this.
I then wrote a "public String toString()
" method in "uslutils
" that looks something like this:
public String toString() {
println "Inside uslutils.toString()."
return "[currentBuild[${currentBuild}] mechIdCredentials[${mechIdCredentials}] " +
"baseStashURL[${baseStashURL}] jobName[${jobName}] codeBranch[${codeBranch}] " +
"buildURL[${buildURL}] pullRequestURL[${pullRequestURL}] qBotUserID[${qBotUserID}] " +
"qBotPassword[${qBotPassword}]]"
}
Then, inside my Jenkinsfile, after setting the uslutils properties, I added a line like this:
println "uslutils[${uslutils}]"
Then, I ran my job, and the curious thing that happened is that I didn't see the "uslutils" line, or the Inside uslutils.toString()
. line. However, I did modify the one functional method I've added so far to "uslutils" (besides the "with" methods), which returns a string value, and I just added an "x" to the value. My Jenkinsfile was printing the result from that, and it did show the additional "x".
Note that no errors occurred here, it just seemed to omit the println
output from within the shared library class, and even stranger, omitted the output from the println
call in the Jenkinsfile that was implicitly calling the uslutils.toString()
method. Note that the println
calls in the original call()
methods WERE seen in the console output.
Any ideas what might be happening here?
Update:
I now have the following lines in my Jenkinsfile (among others):
println "uslutils.qBotPassword[${uslutils.qBotPassword}]"
println "uslutils[${uslutils}]"
println "uslutils.toString()[${uslutils.toString()}]"
And to repeat, here is the "uslutils.toString()" method:
public String toString() {
println "Inside uslutils.toString()."
return "[currentBuild[${currentBuild}] mechIdCredentials[${mechIdCredentials}] " +
"baseStashURL[${baseStashURL}] jobName[${jobName}] codeBranch[${codeBranch}] " +
"codeURL[${codeURL}] buildURL[${buildURL}] pullRequestURL[${pullRequestURL}] qBotUserID[${qBotUserID}] " +
"qBotPassword[${qBotPassword}]]"
}
Here are corresponding lines of output from the build:
[Pipeline] echo
uslutils.qBotPassword[...]
[Pipeline] echo
uslutils.toString()[[currentBuild[org.jenkinsci.plugins.workflow.support.steps.build.RunWrapper@41fb2c94] mechIdCredentials[121447d5-0fe4-470d-b785-6ce88225ef01] baseStashURL[https://...] jobName[unified-service-layer-build-pipeline] codeBranch[master] codeURL[ssh://git@...] buildURL[http://...] pullRequestURL[] qBotUserID[...] qBotPassword[...]]
As you can see, the line attempting to print "uslutils[${uslutils}]"
was simply ignored. The line attempting to print "uslutils.toString()[${uslutils.toString()}]"
did render, but also note that the Inside uslutils.toString()
. did not render.
I'm still looking for an explanation for this behavior, but perhaps this summarizes it more succinctly.
I did some digging and found this issue, https://issues.jenkins-ci.org/browse/JENKINS-41953, basically in normal pipeline script println
is aliased to echo
step. But when you're in a class, e.g. outside of the pipeline CPS, then the echo step isn't available and the println
is ignored (since, as I understand it, there is no logger available).
What you can do is to propagate the script environment into your class methods using a variable and call echo
through the variable (found solution in this thread). Like this:
class A {
Script script;
public void a() {
script.echo("Hello")
}
}
def a = new A(script:this)
echo "Calling A.a()"
a.a()
outputs:
Started by user jon
[Pipeline] echo
Calling A.a()
[Pipeline] echo
Hello
[Pipeline] End of Pipeline
Finished: SUCCESS
Which is what we want. For comparison, here is without propagation:
class A {
public void a() {
println "Hello"
}
}
def a = new A()
echo "Calling A.a()"
a.a()
Gives:
Started by user jon
[Pipeline] echo
Calling A.a()
[Pipeline] End of Pipeline
Finished: SUCCESS
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