web-dev-qa-db-fra.com

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?

8
Daniel Bingham

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.

12
Vitalii Vitrenko