有没有办法在Declarative Jenkinsfile中基于分支设置环境变量?

问题描述 投票:1回答:3

我希望通过加载基于分支的环境变量来找到一种方法来删除Declarative 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。这只是一个例子,但我计划有四到五个变量,每个环境都有不同的值。

我的想法是用相应的值创建EnvDevEnvTestEnvProd地图,然后创建一个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}")
}

想法是传递Map并根据分支拉出相应的环境贴图,然后根据需要使用变量。

所以我有这样的事情:

@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.MissingMethodException:没有方法签名:setupEnv.call()适用于参数类型:(java.util.LinkedHashMap)值:[[branch:dev,env_mapping:[dev:[url] :dev.com,标签:dev,var:Dev Var],...]]]

可能的解决方案:call(java.lang.String,java.util.Map),wait(),any(),wait(long),main([Ljava.lang.String;),每个(groovy.lang.Closure)

有没有更简单的方法来完成我想要做的事情?

这是我第一次尝试编写共享库函数,所以我猜它可能只是一些我不熟悉的Groovy语法/概念。

谢谢!

jenkins groovy jenkins-pipeline jenkins-groovy
3个回答
2
投票

你的函数签名是def call(String branch, Map envMapping),但你的调用是branch: xxx, env_mapping:xxx

改为sharedLibrarySetupEnv branch: "$env.GIT_BRANCH", envMapping: EnvMap


0
投票

您可以使用变量BRANCH_NAME并将其置于以下条件中: -

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

您可以在条件中使用REGEX。


0
投票

问题在于我是如何尝试调用共享库函数的。我以为我能够引用导致Jenkinsfile /管道传递LinkedHashMap到共享库而不是两个单独变量的变量名。

有两种解决方案:

  1. 让共享库调用方法接受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. 不要在Jenkins文件中传递变量名,并让共享库调用方法接受相应的变量。

共享库:

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

Jenkinsfile:

setupEnv $env.GIT_BRANCH, EnvMap
© www.soinside.com 2019 - 2024. All rights reserved.