Lorsque j'exécute le script de pipeline Jenkins ci-dessous:
def some_var = "some value"
def pr() {
def another_var = "another " + some_var
echo "${another_var}"
}
pipeline {
agent any
stages {
stage ("Run") {
steps {
pr()
}
}
}
}
Je reçois cette erreur:
groovy.lang.MissingPropertyException: No such property: some_var for class: groovy.lang.Binding
Si def
est supprimé de some_var
, ça fonctionne bien. Quelqu'un pourrait-il expliquer les règles de portée qui provoquent ce comportement?
def
dans le corps du script principal ne sont pas accessibles à partir d'autres méthodes.def
sont accessibles directement par n'importe quelle méthode même à partir de différents scripts. C'est une mauvaise pratique.def
et @Field
l'annotation est accessible directement à partir des méthodes définies dans le même script.Lorsque groovy compile ce script, il déplace tout dans une classe qui à peu près ressemble à ceci
class Script1 {
def pr() {
def another_var = "another " + some_var
echo "${another_var}"
}
def run() {
def some_var = "some value"
pipeline {
agent any
stages {
stage ("Run") {
steps {
pr()
}
}
}
}
}
}
Vous pouvez voir que some_var
Est clairement hors de portée pour pr()
parce que c'est une variable locale dans une méthode différente.
Lorsque vous définissez une variable sans def
vous placez cette variable dans un Binding du script (donc -called variables de liaison). Donc, quand groovy exécute la méthode pr()
tout d'abord, il essaie de trouver une variable locale avec un nom some_var
Et s'il n'existe pas, il essaie ensuite de trouver cette variable dans une liaison (qui existe parce que vous l'avez défini sans def
).
Les variables de liaison sont considérées comme une mauvaise pratique car si vous chargez plusieurs scripts (load
étape), les variables de liaison seront accessibles dans tous ces scripts car Jenkins partage la même liaison pour tous les scripts. Une bien meilleure alternative consiste à utiliser @Field
annotation. De cette façon, vous pouvez rendre une variable accessible dans toutes les méthodes à l'intérieur d'un script sans l'exposer à d'autres scripts.
import groovy.transform.Field
@Field
def some_var = "some value"
def pr() {
def another_var = "another " + some_var
echo "${another_var}"
}
//your pipeline
Quand groovy compile ce script dans une classe, il ressemblera à ceci
class Script1 {
def some_var = "some value"
def pr() {
def another_var = "another " + some_var
echo "${another_var}"
}
def run() {
//your pipeline
}
}