Quelle est la relation entre l'environnement et les paramètres dans les builds paramétrés Jenkinsfile?
J'ai récemment rencontré quelque chose d'un casse-tête en travaillant sur certaines versions de Jenkins avec un collègue. Il utilise params.VARIABLE
Et env.VARIABLE
De manière interchangeable et n'a aucun problème avec. Pendant ce temps, j'ai commencé à obtenir des erreurs d'objet nul sur l'un de ses appels à un objet paramètre via l'environnement sur cette ligne de code:
if(!deploy_environments.contains(env.ENVIRONMENT_NAME.trim()) || params.INVOKE_PARAMETERS ) {
ENVIRONMENT_NAME
Voici un paramètre. J'ai commencé à recevoir cette erreur:
Java.lang.NullPointerException: Cannot invoke method trim() on null object
Cette build s'exécute en tant qu'enfant d'une autre build. Le paramètre ENVIRONMENT_NAME
Est transmis à l'enfant à partir de cette génération parent.
Il ne voyait pas du tout cette erreur sur un autre maître Jenkins. Lorsque j'ai changé la référence ci-dessus de env.ENVIRONMENT_NAME
À params.ENVIRONMENT_NAME
, Le problème a disparu.
Je n'ai pu trouver aucune référence à params == env
Dans la documentation Jenkins, j'ai donc créé une version pour essayer de clarifier leur relation.
pipeline {
agent {
label 'jenkins-ecs-slave'
}
environment {
ENV_VARIABLE = 'Environment'
}
parameters {
string(description: 'Parameter', name: 'PARAMETER_VARIABLE', defaultValue: 'Parameter')
}
stages {
stage('Output Parameters'){
steps {
script {
echo "Environment: ${env.ENV_VARIABLE}"
echo "Parameter: ${params.PARAMETER_VARIABLE}"
echo "Environment from params: ${params.ENV_VARIABLE}"
echo "Parameter from Env: ${env.PARAMETER_VARIABLE}"
echo "Inspecific reference ENV_VARIABLE: $ENV_VARIABLE"
echo "Inspecific reference PARAMETER_VARIABLE: $PARAMETER_VARIABLE"
sh 'echo "Shell environment: $ENV_VARIABLE"'
sh 'echo "Shell parameter: $PARAMETER_VARIABLE"'
}
}
}
}
}
La première fois que j'ai exécuté ceci sur mon maître Jenkins, il ne comprenait que les quatre premières lignes (echo env.ENV
, echo param.PARAM
, echo env.PARAM
, echo param.ENV
) Avec lesquelles il a réussi la sortie suivante:
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: null
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
Et j'ai pensé: "Aha!" Problème résolu. Ce ne sont pas les mêmes.
Cependant, cette boîte s'est rapidement figée sur moi après et a refusé de faire la queue pour les builds. Je n'ai pas fini de le déboguer, mais ce n'est pas hors de propos de se demander si ce maître est juste foiré.
Je suis donc allé et l'ai couru sur un troisième maître Jenkins que nous avons autour. C'est à ce stade que j'ai ajouté les lignes supplémentaires que vous voyez dans le script ci-dessus pour clarifier davantage. La première fois que j'ai exécuté ce script sur cette boîte, il a échoué sur la "référence Inspecific à la ligne $ PARAMETER_VARIABLE" avec la sortie suivante:
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: null
[Pipeline] echo
Inspecific reference ENV_VARIABLE: Environment
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: PARAMETER_VARIABLE for class: groovy.lang.Binding
D'accord, jusqu'ici tout va bien. C'est logique. Ce ne sont pas les mêmes. Vous pouvez référencer les variables d'environnement dans les échos et les shells sans référencer spécifiquement l'objet environnement, mais vous ne pouvez pas faire de même avec les paramètres. Cohérent, raisonnable, je suis bon avec ça.
Alors j'ai supprimé les deux lignes faisant la "référence inspecific" et le script a réussi avec la sortie suivante:
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: Parameter
[Pipeline] sh
[Environment Testing] Running Shell script
+ echo 'Shell environment: Environment'
Shell environment: Environment
[Pipeline] sh
[Environment Testing] Running Shell script
+ echo 'Shell parameter: Parameter'
Shell parameter: Parameter
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
Et maintenant, je suis complètement confus. Que se passe-t-il? Je l'ai exécuté plusieurs fois juste pour être sûr, et j'ai obtenu la même sortie réussie que ci-dessus, de manière cohérente.
Certes, aucune des versions précédentes qui montraient env.PARAM
Comme null
n'avait vraiment réussi dans un environnement propre (celle qui a réussi était dans un environnement qui m'a implosé rapidement après). Alors peut-être que s'il y a une erreur dans le pipeline Jenkins, il court-circuite le chargement des paramètres dans l'environnement ou quelque chose? J'ai essayé d'ajouter echo "$I_SHOULD_FAIL"
Au script pour forcer une erreur dans une tentative de reproduire ce que je voyais. Pas de dé:
[Pipeline] {
[Pipeline] withEnv
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Output Parameters)
[Pipeline] script
[Pipeline] {
[Pipeline] echo
Environment: Environment
[Pipeline] echo
Parameter: Parameter
[Pipeline] echo
Environment from params: null
[Pipeline] echo
Parameter from Env: Parameter
[Pipeline] sh
[Environment Testing] Running Shell script
+ echo 'Shell environment: Environment'
Shell environment: Environment
[Pipeline] sh
[Environment Testing] Running Shell script
+ echo 'Shell parameter: Parameter'
Shell parameter: Parameter
[Pipeline] }
[Pipeline] // script
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // withEnv
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: I_SHOULD_FAIL for class: groovy.lang.Binding
Alors qu'est-ce qui se passe ici? Quelle est la relation entre environment
et parameters
dans les pipelines Jenkins? Quelle est cette relation censée être et pourquoi semble-t-elle incohérente?
Fondamentalement, cela fonctionne comme suit
env
contient tous variables d'environnement- Le pipeline Jenkins crée automatiquement une variable globale pour chaque variable d'environnement
params
contient tous les paramètres de construction- Jenkins crée également automatiquement une variable d'environnement pour chaque paramètre de construction (et en conséquence du deuxième point une variable globale).
Les variables d'environnement peuvent être remplacées ou non définies mais params
est une carte immuable et ne peut pas être modifiée. La meilleure pratique consiste à toujours utiliser params
lorsque vous devez obtenir un paramètre de génération.