Есть ли способ установить переменные среды на основе ветви в декларативном Jenkinsfile? - PullRequest
1 голос
/ 24 апреля 2019

Я надеюсь найти способ удалить дублированные этапы в декларативном Jenkinsfile путем загрузки переменных среды на основе ветви.

В настоящее время у меня есть что-то вроде:

@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"
      }
    }
  }
}

Я хочу иметь возможность сократить это в один этап этапа и динамически загружать в необходимое $tagBaseXXX на основе ветви. Это всего лишь пример, но я планирую иметь четыре или пять переменных, которые будут иметь разные значения для каждой среды.

Я думал создать карты EnvDev, EnvTest и EnvProd с соответствующими значениями, а затем создать карту EnvMap, которая сопоставляет имя ветви с картой среды. Например:

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
]

Затем я пытаюсь создать вызов из общей библиотеки, который выглядит примерно так:

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

Идея состоит в том, чтобы передать карту и вытащить соответствующую карту среды на основе ветви, а затем использовать переменные по мере необходимости.

Итак, у меня есть что-то вроде этого:

@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
      }
    }
  }
}

Но я получаю следующую ошибку:

hudson.remoting.ProxyException: groovy.lang. : [url: dev.com, тег: dev, var: Dev Var], ...]]]

Возможные решения: вызов (java.lang.String, java.util.Map), wait (), any (), wait (long), main ([Ljava.lang.String;), each (groovy.lang) .Closure)

Есть ли более простой способ выполнить то, что я пытаюсь сделать?

Я впервые пытаюсь написать функцию Shared Library, так что я предполагаю, что это может быть какой-то синтаксис / концепция Groovy, с которой я не знаком.

Спасибо!

Ответы [ 3 ]

2 голосов
/ 25 апреля 2019

ваша подпись функции def call(String branch, Map envMapping), но ваш вызов branch: xxx, env_mapping:xxx.

Изменить на sharedLibrarySetupEnv branch: "$env.GIT_BRANCH", envMapping: EnvMap

0 голосов
/ 25 апреля 2019

Проблема была в том, как я пытался вызвать функцию Shared Library. Я думал, что смогу сослаться на имена переменных, которые привели к тому, что Jenkinsfile / pipe передавал LinkedHashMap в общую библиотеку, а не две отдельные переменные.

Для этого есть два решения:

  1. Пусть метод вызова Shared Library принимает Map<String, Object> parms и в ссылке на вызов переменные с parms.varname.

Общая библиотека:

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

Jenkinsfile:

setupEnv branch: "$env.GIT_BRANCH", envMapping: EnvMap
  1. Не передавайте имена переменных в Jenkinsfile, а вызов метода Shared Library принимает соответствующие переменные.

Общая библиотека:

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

Jenkinsfile:

setupEnv $env.GIT_BRANCH, EnvMap
0 голосов
/ 25 апреля 2019

Вы можете использовать переменную BRANCH_NAME и поместить ее в условие, как показано ниже: -

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

Вы можете использовать REGEX в условии.

...