"vars/foo.groovy"的"call"方法中的println有效,但不在课堂上的方法中

Dav*_*arr 7 groovy jenkins jenkins-pipeline

我正在迭代构建一个Jenkins管道共享库,所以我的Jenkinsfile更清洁一点.

我正在使用以下页面获取指导:https://jenkins.io/doc/book/pipeline/shared-libraries/.

我首先在单个文件中定义了几个方法,例如" vars/methodName.groovy",call()在代码中使用" "方法.这工作正常,我特别注意println在Jenkins控制台输出中可以看到这些方法中的" "调用.

然后我决定在方法调用之间保存一些状态,所以我在" vars"中添加了一个名为" uslutils.groovy" 的新文件,它以这样开头(减去一些必需的导入):

class uslutils implements Serializable {
Run Code Online (Sandbox Code Playgroud)

我定义了一些with<property>设置属性并返回它的方法.

然后我public String toString()在" uslutils"中写了一个" "方法,看起来像这样:

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}]]"
}
Run Code Online (Sandbox Code Playgroud)

然后,在我的Jenkinsfile里面,在设置了uslutils属性之后,我添加了这样一行:

println "uslutils[${uslutils}]"
Run Code Online (Sandbox Code Playgroud)

然后,我完成了我的工作,发生了奇怪的事情是我没有看到"uslutils"行,或者说Inside uslutils.toString().线.但是,我确实修改了我迄今为止添加的一个函数方法"uslutils"(除了"with"方法),它返回一个字符串值,我只是在值中加了一个"x".我的Jenkinsfile正在打印结果,它确实显示了额外的"x".

注意,这里没有发生错误,它似乎只是省略了println共享库类中的输出,甚至更奇怪,省略println了Jenkins文件中隐式调用该uslutils.toString()方法的调用的输出.请注意,在控制台输出中看到println原始call()方法中的调用.

任何想法可能会发生在这里?

更新:

我现在在Jenkinsfile中有以下几行(以及其他行):

println "uslutils.qBotPassword[${uslutils.qBotPassword}]"
println "uslutils[${uslutils}]"
println "uslutils.toString()[${uslutils.toString()}]"
Run Code Online (Sandbox Code Playgroud)

重复一下,这里是"uslutils.toString()"方法:

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}]]"
}
Run Code Online (Sandbox Code Playgroud)

以下是构建的相应输出行:

[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[...]]
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,尝试的线路print "uslutils[${uslutils}]"被忽略了.该行试图print "uslutils.toString()[${uslutils.toString()}]"做渲染,但也注意到了Inside uslutils.toString().没有呈现.

我仍在寻找这种行为的解释,但也许这更简洁地总结了它.

Jon*_*n S 17

我做了一些挖掘并发现了这个问题,https://issues.jenkins-ci.org/browse/JENKINS-41953,基本上在正常的管道脚本中println是别名的echo步骤.但是当你在一个班级时,例如在管道CPS之外,那么回声步骤不可用并且println被忽略(因为据我所知,没有可用的记录器).

您可以做的是使用变量将脚本环境传播到类方法中并echo通过变量调用(在此线程中找到解决方案).像这样:

class A {
    Script script;
    public void a() {
        script.echo("Hello")
    }
}
def a = new A(script:this)
echo "Calling A.a()"
a.a()
Run Code Online (Sandbox Code Playgroud)

输出:

Started by user jon
[Pipeline] echo
Calling A.a()
[Pipeline] echo
Hello
[Pipeline] End of Pipeline
Finished: SUCCESS
Run Code Online (Sandbox Code Playgroud)

这就是我们想要的.为了比较,这里没有传播:

class A {
    public void a() {
        println "Hello"
    }
}
def a = new A()
echo "Calling A.a()"
a.a()
Run Code Online (Sandbox Code Playgroud)

得到:

Started by user jon
[Pipeline] echo
Calling A.a()
[Pipeline] End of Pipeline
Finished: SUCCESS
Run Code Online (Sandbox Code Playgroud)

  • 是的,您可能需要使用@NonNCP 注释方法 Aa(),类需要实现 Serializable 接口,该接口可以防止然后将脚本作为参数传递给方法... (2认同)
  • @eelghEEz是的,所以如果你使用`@ NonCPS`注释方法然后你不能调用全局范围中的任何步骤,也不能使用上面的技巧,当你尝试引用中的东西时会出现错误上面的脚本变量.这与您所处的主/从环境无关.但请注意,print ant println是在groovy中的函数中构建的,因此不包括在内,但如上所示,消息并不总是打印在控制台输出中. (2认同)