Jenkins 有没有一种方法可以基于声明性文件中的分支设置环境变量?

Jenkins 有没有一种方法可以基于声明性文件中的分支设置环境变量?,jenkins,groovy,jenkins-pipeline,jenkins-groovy,Jenkins,Groovy,Jenkins Pipeline,Jenkins Groovy,我希望找到一种方法,通过基于分支加载环境变量来删除声明性Jenkins文件中重复的阶段 目前我有一些类似于: @Library("MySharedLibrary@v1") _ String tagBaseDev = "repo.org/myspace/image:dev" String tagBaseTest = "repo.org/myspace/image:test" String tagBaseProd = "repo

我希望找到一种方法,通过基于分支加载环境变量来删除声明性Jenkins文件中重复的阶段

目前我有一些类似于:

@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
      }
    }
  }
}
其思想是传递映射并基于分支拉取相应的环境映射,然后根据需要使用变量

所以我有这样的想法:

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.MissingMethodException:method:setupEnv.call()的签名不适用于参数类型:(java.util.LinkedHashMap)值:[[branch:dev,env_mapping:[dev:[url:dev.com,tag:dev,var:dev-var],…]]

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

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

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


谢谢!

您可以使用变量BRANCH\u名称并将其置于如下条件下:-

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

您可以在条件中使用REGEX

您的函数签名是
def-call(String-branch,Map-envMapping)
,但您的调用是
branch:xxx,env\u-mapping:xxx


更改为
sharedLibrarySetupEnv分支:“$env.GIT\u分支”,envMapping:EnvMap

问题在于我如何调用共享库函数。我认为我能够引用变量名,这导致Jenkins文件/管道将
LinkedHashMap
传递到共享库,而不是两个单独的变量

有两种解决方案:

  • 让共享库调用方法接受
    Map parms
    ,并在调用中使用
    parms.varname
    引用变量
  • 共享库:

    def call(Map<String, Object> parms) {
        echo "${parms.branch}"
        Map use_this_map = parms.envMapping.get(branch)
    }
    
    setupEnv branch: "$env.GIT_BRANCH", envMapping: EnvMap
    
    def call(String branch, Map<String, Map> envMapping) {
        echo "${branch}"
        Map use_this_map = envMapping.get(branch)
    }
    
    setupEnv $env.GIT_BRANCH, EnvMap
    
  • 不要在Jenkins文件中传递变量名,让共享库调用方法接收相应的变量
  • 共享库:

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

    抱歉…撰写原始帖子时出错。我将进行编辑以反映此更改。我仍然看到相同的行为:
    hudson.remoting.ProxyException:groovy.lang.MissingMethodException:没有方法签名:sharedLibrarySetupEnv.call()适用于参数类型:(java.util.LinkedHashMap)值:[[branch:dev,envMapping:[dev:[url:dev.com,tag:dev,var:dev-var],…]]
    这在脚本化的Jenkins文件中或在声明性Jenkins文件的脚本块中都会起作用,但我希望找到一种方法使它更干净,而不是在每个阶段都有多个if/else块。是的,但您可以创建一个函数并在不同阶段调用它,而不是在每个阶段都指定同一个块