Reputation: 143
I'm hoping to find a way to remove duplicated stages in a Declarative Jenkinsfile by loading environment variables based on the branch.
Currently I have something like:
@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"
}
}
}
}
I want to be able to reduce that into one stage block and dynamically load in the needed $tagBaseXXX
based on branch. This is just an example but I'm planning to have four or five variables that will have different values for each environment.
My thought was to create EnvDev
, EnvTest
, and EnvProd
maps with corresponding values and then create a EnvMap
which is a Map that correlates the branch name to Environment Map. For instance:
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
]
I then try to create a Shared Library call that looks something like this:
def call(String branch, Map envMapping) {
Map use_me = envMapping.get("${branch}")
String url = use_me.get("URL")
echo ("${url}")
}
With the idea being to pass the Map and pull the corresponding environment map based on the branch and then use the variables as needed.
So I have something like this:
@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
}
}
}
}
But I get the following error:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: setupEnv.call() is applicable for argument types: (java.util.LinkedHashMap) values: [[branch:dev, env_mapping:[dev:[url:dev.com, tag:dev, var:Dev Var], ...]]]
Possible solutions: call(java.lang.String, java.util.Map), wait(), any(), wait(long), main([Ljava.lang.String;), each(groovy.lang.Closure)
Is there an easier way to accomplish what I'm trying to do?
This is my first time trying to write a Shared Library function so I'm guessing it may just be some Groovy syntax/concept I'm not familiar with.
Thanks!
Upvotes: 3
Views: 2954
Reputation: 143
The problem was with how I was trying to invoke the Shared Library function. I thought I was able to reference the variable names which led to the Jenkinsfile/pipeline passing a LinkedHashMap
to the shared library and not two separate variables.
There are two solutions to this:
Map<String, Object> parms
and within the call reference the variables with parms.varname
.Shared Library:
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
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
Upvotes: 1
Reputation: 13712
your function signature is def call(String branch, Map envMapping)
, but your calling is branch: xxx, env_mapping:xxx
.
Change to sharedLibrarySetupEnv branch: "$env.GIT_BRANCH", envMapping: EnvMap
Upvotes: 2
Reputation: 1974
You can use the variable BRANCH_NAME and put it in a condition like below:-
if (env.BRANCH_NAME == master)
{
//set all the environment variable you need
} else {
//variable required if the condition doesn't match
}
You can use REGEX in the condition.
Upvotes: 0