Jenkins pipeline 如何使用jenkins管道共享库定义全局变量或常量?

Jenkins pipeline 如何使用jenkins管道共享库定义全局变量或常量?,jenkins-pipeline,Jenkins Pipeline,虽然我能够定义方法,但到目前为止,使用Jenkins共享库定义变量似乎是一项尚未解决的任务 我在这个主体中添加了/vars/True.groovy def call() { return true } 现在在Jenkinsfile中,我尝试测试它是否按预期工作: println "evaluation ${ true == True }" 但令人惊讶的是,它认为true!=类True。我的印象是,true==true()可能会起作用,但这不是重点,我需要一个实变量,因为这样做的全部目

虽然我能够定义方法,但到目前为止,使用Jenkins共享库定义变量似乎是一项尚未解决的任务

我在这个主体中添加了
/vars/True.groovy

def call() {
    return true
}
现在在Jenkinsfile中,我尝试测试它是否按预期工作:

println "evaluation ${ true == True }"
但令人惊讶的是,它认为
true!=类True
。我的印象是,
true==true()
可能会起作用,但这不是重点,我需要一个实变量,因为这样做的全部目的是避免人们使用错误的大小写所导致的一些错误


那么什么是魔术呢?

变量
True
肯定是一个变量,但它包含对
True
类型的对象的引用(您在
/vars/True.groovy
中定义的对象)。您有两个选择
好的: 这样用吧

println "evaluation ${ true == True() }"
那个奇怪的人: 您可以在
/vars/True.groovy

public boolean equals(obj) {
    return obj == true;
}
那么这就行了

println "evaluation ${ true == True }"

但这真的很奇怪,可能会导致误解。

看起来
vars
目录中定义的全局变量必须更低/camel/可能是其他一些特殊的大小写。本节的任何地方都没有说明这一点,但顶部有一个注释:

vars
目录承载定义可从管道访问的全局变量的脚本。每个
*.groovy
文件的基名应该是一个groovy(~Java)标识符,通常是
camelCased
。匹配的
*.txt
(如果存在)可以包含通过系统配置的标记格式化程序处理的文档(也可能是HTML、Markdown等,尽管需要扩展名
txt

以下是我尝试过的:

  • vars/MyTrue.groovy

    public boolean equals(obj) {
        return obj == true;
    }
    
    类MyTrue实现可序列化{
    }
    
  • vars/myTrue.groovy

    public boolean equals(obj) {
        return obj == true;
    }
    
    类myTrue实现可序列化{
    }
    
  • vars/mytrue.groovy

    public boolean equals(obj) {
        return obj == true;
    }
    
    类mytrue实现可序列化{
    }
    
  • vars/doesCasingMatter.groovy

    public boolean equals(obj) {
        return obj == true;
    }
    
    类DoesCasingMatter实现可序列化{
    }
    
并在我的管道脚本中测试它们是实例还是
类型(此处未启用脚本安全性):

echo(“MyTrue:${Class.isInstance(MyTrue)}”)
echo(“myTrue:${Class.isInstance(myTrue)}”)
echo(“mytrue:${Class.isInstance(mytrue)}”)
echo(“有什么绑定?:${binding.variables}”)
这将打印出:

[Pipeline]echo
真的
[管道]回声
myTrue:false
[管道]回声
mytrue:false
[管道]回声
有哪些绑定?:[步骤:org.jenkinsci.plugins.workflow.cps。DSL@e96256,myTrue:myTrue@8a1ddc5,mytrue:mytrue@392ff649]

这似乎表明类名决定了如何编译和创建它。第一个示例类似于
vars/True.groovy
,只是作为类导入,而不是实例化。另外两个被编译和实例化,并用它们定义的类名绑定到脚本。我认为,如果希望类成为全局变量,就必须以不同的方式定义它们。

我找到了实现这一点的方法,但有一点需要注意:变量必须在类中定义/包装。然而,这样做的好处是提供更好的组织,以避免对全球空间造成太多污染

例如,我们经常对构建状态重用四个标准的“魔术字符串”,我希望将其保存为全局常量以促进互操作性。因此,我创建了一个全局
status
类,在
vars/status.groovy
中定义:

class status {
  final String STARTED = "STARTED"
  final String SUCCESS = "SUCCESS"
  final String FAILURE = "FAILURE"
  final String ABORTED = "ABORTED"
}
然后,可以通过引用其父类来使用这些常量:

echo status.STARTED
echo status.SUCCESS
echo status.FAILURE
echo status.ABORTED

特别感谢@mkobit为我指明了正确的方向

虽然第一个“有效”,但它没有解决定义变量的问题,因此没有用。第二个没有定义变量。当我尝试引用它时,我得到了一个异常groovy.lang.MissingPropertyException:No-this-property:False for-class:groovy.lang.Binding可能的解决方案:org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.sandboxiterceptor.onGetProperty(sandboxiterceptor.java:242)上的groovy.lang.Binding.getVariable.java:63处的类这是因为
/vars/
不是导入,相反,Jenkins似乎对它们中的每一个进行求值,并将其实例化为单独的类。我想知道是否有办法逃出这个监狱。目录名为vars这一事实确实令人误解。@sorin您的错误表明没有
False
变量。您确定您在
/vars/TrueDefiner.groovy
中定义了它而没有
def
关键字吗?显示完整的代码这并没有误导,因为Jenkins实际上创建了一个带有对象引用的变量。您想要实现的是相当奇怪的代码气味。
vars
被假定为单例实例,我认为它们会与某种名称绑定。文档似乎暗示应该有一种方法来定义全局变量,但我不确定这个魔术是什么。我相信
call()
定义将其编译为一种方法,因此我认为这种方法不起作用,但类似
class True的东西实现了可序列化的{//some equals()定义和东西}
我认为会起作用。但是,正如你所说,有一些魔法詹金斯咒语需要施展。这帮我想出了一个答案,因为我不知道可以在vars目录中定义类!这看起来很有趣,我第一次看到这个图案。因此,与在管道中使用
function()
调用
vars/function.groovy类似,您可以直接使用
status.STARTED
作为值?有可能把同一个文件放进去吗<