2
votes

Existe-t-il un moyen de définir des variables d'environnement basées sur une branche dans un fichier Jenkins déclaratif?

J'espère trouver un moyen de supprimer les étapes dupliquées dans un fichier Jenkins déclaratif en chargeant des variables d'environnement basées sur la branche.

Actuellement, j'ai quelque chose comme:

@Library("MySharedLibrary@v1") _

def EnvDev = [
  url: "dev.com",
  tag: "dev",
  var: "Dev Var"
]

def EnvProd = [
  url: "prod.com",
  tag: "prod",
  var: "prod Var"
]

def EnvMap = [
  dev: EnvDev,
  prod: EnvProd
]

pipeline {
  agent {label 'docker-slave'}
  stages {
    stage ('Test Env Vars') {
      steps {
        echo "$env.GIT_BRANCH"
        sharedLibrarySetupEnv branch: "$env.GIT_BRANCH", evnMapping: EnvMap
      }
    }
  }
}

Je veux être capable de réduire cela en un bloc d'étape et de charger dynamiquement le $ tagBaseXXX nécessaire en fonction de la branche. Ceci n'est qu'un exemple mais je prévois d'avoir quatre ou cinq variables qui auront des valeurs différentes pour chaque environnement.

Ma pensée était de créer EnvDev , EnvTest et EnvProd mappe avec les valeurs correspondantes, puis créez une EnvMap qui est une carte qui met en corrélation le nom de la branche avec la carte d'environnement. Par exemple:

def call(String branch, Map envMapping) {
    Map use_me = envMapping.get("${branch}")
    String url = use_me.get("URL")
    echo ("${url}")
}

J'essaye ensuite de créer un appel à la bibliothèque partagée qui ressemble à ceci:

def EnvDev = [
  url: "dev.com",
  tag: "dev",
  var: "Dev Var"
]

def EnvProd = [
  url: "prod.com",
  tag: "prod",
  var: "prod Var"
]

def EnvMap = [
  dev: EnvDev,
  prod: EnvProd
]

Avec le l'idée étant de passer la carte et de tirer la carte d'environnement correspondante en fonction de la branche, puis d'utiliser les variables selon les besoins.

J'ai donc quelque chose comme ceci:

@Library("MySharedLibrary@v1") _

String tagBaseDev = "repo.org/myspace/image:dev"
String tagBaseTest = "repo.org/myspace/image:test"
String tagBaseProd = "repo.org/myspace/image:prod"

pipeline {
  agent none
  stages {
    // Always Run This
    stage ('Maven Build and Unit Tests') {
      agent {label 'docker-slave'}
      steps {
        sharedLibraryBuild mavenGoals:'clean package', additionalProps:['ci.env':'']
        stash 'artifacts'
      }
    }
    // Dev Only
    stage ('Build Dev Docker Image and Push') {
      when {
        branch 'dev'
      }
      agent {label 'docker-slave'}
      steps {
        unstash 'artifacts'
        sharedLibraryDockerImageBuildPush tag:"$tagBaseDev"
      }
    }
    // Test Only
    stage ('Build Test Docker Image and Push') {
      when {
        branch 'test'
      }
      agent {label 'docker-slave'}
      steps {
        unstash 'artifacts'
        sharedLibraryDockerImageBuildPush tag:"$tagBaseTest"
      }
    }
    // Prod Only
    stage ('Build Prod Docker Image and Push') {
      when {
        branch 'prod'
      }
      agent {label 'docker-slave'}
      steps {
        unstash 'artifacts'
        sharedLibraryDockerImageBuildPush tag:"$tagBaseProd"
      }
    }
  }
}

Mais j'obtiens l'erreur suivante:

hudson.remoting.ProxyException: groovy.lang.MissingMethodException: Aucune signature de la méthode: setupEnv.call () n'est applicable pour les types d'argument: (java.util.LinkedHashMap) valeurs: [[branch: dev, env_mapping: [dev : [url: dev.com, tag: dev, var: Dev Var], ...]]]

Solutions possibles: appel (java.lang.String, java.util.Map), wait (), any (), wait (long), main ([Ljava.lang.String;), each (groovy.lang .Fermeture)

Existe-t-il un moyen plus simple d'accomplir ce que j'essaie de faire?

C'est la première fois que j'essaie d'écrire une fonction de bibliothèque partagée, donc je suppose que c'est peut-être juste une syntaxe / concept Groovy que je ne connais pas.

Merci!


0 commentaires

3 Réponses :


0
votes

Vous pouvez utiliser la variable BRANCH_NAME et la mettre dans une condition comme ci-dessous: -

if (env.BRANCH_NAME == master)
{
    //set all the environment variable you need
} else {
    //variable required if the condition doesn't match
}

Vous pouvez utiliser REGEX dans la condition.


2 commentaires

Cela fonctionnerait dans un fichier Jenkins scripté ou dans un bloc Script dans un fichier Jenkins déclaratif, mais j'espérais trouver un moyen de le rendre plus propre au lieu d'avoir plusieurs blocs if / else à chaque étape.


oui, mais vous pouvez créer une fonction et l'appeler à différentes étapes plutôt que de spécifier le même bloc à chaque étape



2
votes

votre signature de fonction est def call (String branch, Map envMapping) , mais votre appel est branch: xxx, env_mapping: xxx .

Passez à la branche sharedLibrarySetupEnv: "$ env.GIT_BRANCH", envMapping: EnvMap


1 commentaires

Désolé ... Erreur lors de la rédaction du message original. Je modifierai pour refléter ce changement. Je vois toujours le même comportement: hudson.remoting.ProxyException: groovy.lang.MissingMethodException: Aucune signature de méthode: sharedLibrarySetupEnv.call () est applicable pour les types d'argument: (java.util.LinkedHashMap) valeurs: [ [branche: dev, envMapping: [dev: [url: dev.com, tag: dev, var: Dev Var], ...]]]



1
votes

Le problème venait de la façon dont j'essayais d'appeler la fonction de bibliothèque partagée. Je pensais être en mesure de référencer les noms de variables qui ont conduit le Jenkinsfile / pipeline à passer un LinkedHashMap à la bibliothèque partagée et non à deux variables séparées.

Il y a deux solutions à cela: p >

  1. Demandez à la méthode d'appel de la bibliothèque partagée de prendre un parms Map et dans l'appel de référence les variables avec parms.varname .

Bibliothèque partagée:

setupEnv $env.GIT_BRANCH, EnvMap

Jenkinsfile:

def call(String branch, Map<String, Map> envMapping) {
    echo "${branch}"
    Map use_this_map = envMapping.get(branch)
}


0 commentaires