字符串变量分配在Jenkinsfile中不包含字符串引用

时间:2020-02-24 16:05:28

标签: jenkins groovy jenkins-pipeline

我正在构建一个脚本化的Jenkinsfile(用Groovy编写,对此我不太了解,我也不知道Java)

我有一个特定的字符串变量,由于某种原因,该变量不想正常运行,我感到困惑。

[Pipeline] echo
FOOBAR: Mary had a little lamb whose fleece was white as snow
[Pipeline] echo
FOO & BAR: Mary had a little lamb whose fleece was white as snow

结果如您所愿

// THIS DOES NOT WORK AS EXPECTED
@Field def BAR = "and she murdered it"
@Field def FOO = "Mary had a little lamb"
if (FOO) {
    BAR = "whose fleece was white as snow"
}
@Field def FOOBAR = "${FOO} ${BAR}"
echo "FOOBAR: ${FOOBAR}"
echo "FOO & BAR: ${FOO} ${BAR}"

但是,以下内容:

[Pipeline] echo
FOOBAR: Mary had a little lamb and she murdered it
[Pipeline] echo
FOO & BAR: Mary had a little lamb whose fleece was white as snow

结果

BAR

我不了解Java / Groovy中事件的顺序是否有些细微差别? (我是一个蟒蛇人) FOOBAR被覆盖,但是在定义变量BAR时会出现,它使用BAR的原始值,而当在echo语句中简单地构建字符串时,它使用{{ 1}}。什么?!
还是Jenkins与Groovy一起工作的细微差别?

1 个答案:

答案 0 :(得分:3)

编写Groovy脚本时,groovy有效地将脚本包装在方法run()内的标准Java类中。

因此,如果我们删除@Field批注,则脚本:

def FOO = "Mary had a little lamb"
def BAR = "whose fleece was white as snow"
def FOOBAR = "${FOO} ${BAR}"
echo "FOOBAR: ${FOOBAR}"
echo "FOO & BAR: ${FOO} ${BAR}"

有效地发挥作用:

public class script1582564680906 extends groovy.lang.Script { 

    public java.lang.Object run() {
        java.lang.Object FOO = 'Mary had a little lamb'
        java.lang.Object BAR = 'whose fleece was white as snow'
        java.lang.Object FOOBAR = "$FOO $BAR"
        this.echo("FOOBAR: $FOOBAR")
        this.echo("FOO & BAR: $FOO $BAR")
    }

}

再加上一些对这个问题不重要的东西...没关系,但是如果您向脚本中添加方法,就像这样:

def something() {
    FOO = 'tim'
}

def FOO = "Mary had a little lamb"
def BAR = "whose fleece was white as snow"
def FOOBAR = "${FOO} ${BAR}"
echo "FOOBAR: ${FOOBAR}"
echo "FOO & BAR: ${FOO} ${BAR}"

该类变为:

public class script1582564855552 extends groovy.lang.Script { 

    public java.lang.Object run() {
        java.lang.Object FOO = 'Mary had a little lamb'
        java.lang.Object BAR = 'whose fleece was white as snow'
        java.lang.Object FOOBAR = "$FOO $BAR"
        this.echo("FOOBAR: $FOOBAR")
        this.echo("FOO & BAR: $FOO $BAR")
    }

    public java.lang.Object something() {
        FOO = 'tim'
    }

}

如您所见,在我的something()方法中,我试图访问FOO,但这仅在run()方法内部有效。

这就是存在@Field批注的原因。它告诉Groovy将定义上移到类级别,而不是移到run()内部,因此:

import groovy.transform.Field

@Field def FOO = "Mary had a little lamb"
@Field def BAR = "whose fleece was white as snow"
@Field def FOOBAR = "${FOO} ${BAR}"
echo "FOOBAR: ${FOOBAR}"
echo "FOO & BAR: ${FOO} ${BAR}"

成为这个:

public class script1582565001609 extends groovy.lang.Script { 

    java.lang.Object FOO = 'Mary had a little lamb'
    java.lang.Object BAR = 'whose fleece was white as snow'
    java.lang.Object FOOBAR = "$FOO $BAR"

    public java.lang.Object run() {
        this.echo("FOOBAR: $FOOBAR")
        this.echo("FOO & BAR: $FOO $BAR")
    }

}

现在我们来解决您的问题......:

@Field def BAR = "and she murdered it"
@Field def FOO = "Mary had a little lamb"
if (FOO) {
    BAR = "whose fleece was white as snow"
}
@Field def FOOBAR = "${FOO} ${BAR}"
echo "FOOBAR: ${FOOBAR}"
echo "FOO & BAR: ${FOO} ${BAR}"

并按照上述规则进行转换可以得到:

public class script1582565140864 extends groovy.lang.Script { 

    java.lang.Object BAR = 'and she murdered it'
    java.lang.Object FOO = 'Mary had a little lamb'
    java.lang.Object FOOBAR = "$FOO $BAR"

    public java.lang.Object run() {
        if ( FOO ) {
            BAR = 'whose fleece was white as snow'
        }
        this.echo("FOOBAR: $FOOBAR")
        return this.echo("FOO & BAR: $FOO $BAR")
    }
}

您可以看到... FOOBAR被设置为一个字段,因此在您将BAR修改为'whose fleece was white as snow'之前是初始化方式

但是FOO和BAR符合您调试它们的期望...

如果可以避免的话,请避免使用@Field,因为这样会使事情难以推理