Reputation: 6285
This question follows from Why is this Groovy class static function not executed from its calling Jenkins pipeline?.
I have a Jenkins/groovy shared library set up like this:
+- src # Groovy source files
| +- org
| +- company
| +- Stage.groovy # for org.company.Stage class
+- vars
+- func.groovy # for global var func()
The shared library is set up as a Global Pipeline Library named 'foo':
The shared library implements a global variable:
// vars/func.groovy
def func(d) {
println("func.groovy:func()")
}
...and class Stage
with member function func
:
// src/org/company/Stage.groovy
package org.company;
class Stage implements Serializable {
def func(d) {
println("org.company.Stage.func()")
return 'hello, world!`
}
}
Note that both the global variable and the class member function do the same thing: println
of some static string.
My Jenkins pipeline calls both the global variable and the class member function:
// Jenkinsfile
@Library('foo@dev')
import org.company.Stage
pipeline {
agent any
stages {
stage('1') {
steps {
testLoadLib()
}
}
}
}
void testLoadLib() {
loadLibrary('foo@dev')
}
void loadLibrary(String libraryName) {
def lib = library(libraryName)
def d = [:]
func.func(d)
def myvar = new Stage()
def ret = myvar.func()
println(ret)
}
The output of this Jenkins pipeline is:
Only using first definition of library foo
[Pipeline] echo
func.groovy:func()
[Pipeline] echo
hello, world!
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Question: why is the println()
in org.company.Stage.func()
not reflected in the Jenkins console log whereas the println()
in the global variable func.func()
is reflected in the Jenkins console log?
By using the return-value from org.company.Stage.func()
, it's clear that the function is being executed...but its functionality is "crippled" -- I don't know how else to describe it...the println
is muted...what other functionality is compromised?
Why would the behavior of this println()
statement be different between invoking a global variable versus invoking a class function?
I have tried various combinations of class Stage
vs. public class Stage
, def func(d)
vs. public def func(d)
, removing/keeping implements Serializable
, and the @NonCPS
annotation -- none of that appears to affect the behavior described above.
Upvotes: 1
Views: 555
Reputation: 6285
I discovered this by throwing spaghetti at the wall and seeing what stuck.
Starting with a Jenkinsfile like this:
// Jenkinsfile
@Library('foo@dev')
import org.company.Stage
...
def myvar = new Stage(steps)
myvar.func()
...this works:
// src/org/company/Stage.groovy
package org.company;
class Stage {
def steps
Stage(steps) {this.steps = steps}
def func(d) {
steps.echo("org.company.Stage.func()")
}
}
This does not work:
// src/org/company/Stage.groovy
package org.company;
class Stage {
def steps
Stage(steps) {this.steps = steps}
def func(d) {
steps.println("org.company.Stage.func()")
}
}
I.e. two things appear necessary as an answer to the question asked:
steps
.steps.echo
, and not steps.println
.Jenkins/Groovy continues to slowly drive me insane.
Upvotes: 0