How do I reassign parameters in a Jenkins pipeline script? - jenkins

I'm new to Jenkins and groovy scripting. I'm trying to reassign the parameters in the Jenkins script.
I tried the following
def reasignParams() {
if(params.B == '') {
params.B = params.A
}
}
pipeline{
parameters {
string(name: 'A', defaultValue: '1.1', description: "Master Value")
string(name: 'B', defaultValue: '', description: "Slave value")
}
}
After running the above Jenkins pipeline script (groovy), I ran into the following error
java.lang.UnsupportedOperationException
The alternative that I thought to this is as below
def reasignParams() {
if(params.B == '') {
def temp = params.A
# use temp variable instead of params.B; But this is inconvenient
}
}
I would like to learn if there is a way to reassign parameters in the Jenkins pipeline script? Any help would be greatly appreciated, Thanks in advance!

The params object in Jenkins Pipeline does not support write operations on its member variables. You can only initially assign them in the parameters directive (think of it like a constructor in that sense). If you want to reassign parameter values, then you do indeed need to make a deep copy like the following:
newParams = [:]
newParams.A = params.A

Related

Using env variables in a Jenkinsfile function?

I'm triggering one Jenkins job from the other, all via Jenkinsfiles.
stage("Trigger another job")
{
build([job:"Job2", wait:true, propagate:true, parameters: [string(name:'branch_my',value:"${env.ghprbActualCommit}")]])
}
Note that parameter branch_my is sent to Job2. However, the pipeline Job2 needs to work even when branch_my is NOT defined, for example when it is triggered manually.
Jenkinsfile for Job2 looks like:
pipeline
{
// ...
steps
{
customBranches()
// etc...
}
}
def customBranches()
{
if ( env.branch_my != null)
{
sh "switch_to ${env.branch_my}"
}
}
However, the customBranches() if statement never evaluates to true. When I do
sh "echo 'Env branch_my is: ${env.branch_my} '"
I get Env branch_my is: some_value , which is OK, and if statement should evaluate to true - but it does not.
I tried adding ${} like so: if ( ${env.branch_my} != null), but that failed completely: No such DSL method "$" found.
What's wrong with my customBranches()?
Problem isn't the Jenkinsfile syntax, but the Jenkins job configuration: it must be labeled as "parametrized" in the GUI and a string parameter branch_my needs to be defined:
Note, the parameters can be added via the Jenkinsfile itself:
parameters { string(name: 'branch_my', defaultValue: 'master', description: '') }
However, this just adds the parameter to the GUI, so you end up with the same thing.

Jenkins Pipeline build job parameter Syntax

I was wondering if anyone can explain the following Jenkins groovy syntax for build job and parameter. I could not find any documentation to explain it.
There's this + syntax at the end of the parameter block with a function, I am wondering if there function is supposed to return value to replace the original parameters? Or just add to them?
Function
def some_function(a, b) {
build job: SomeJob,
parameters: [
string(name: 'p1', value: "..."),
...
] + some_other_function()
}
def some_other_function() {
...
return some_value
}
The operator + here is to append an element to a list in Groovy. If you write println([1] + 2) in Groovy you will get [1, 2]. You may try this on https://www.jdoodle.com/execute-groovy-online/.
And back to your original question, it's just to add the return value of some_other_function() to the parameters list. It's useful when you need to decide the parameters dynamically based on the job context. For example
def some_other_function() {
return string(name: 'tag', value: 'master' == env.GIT_BRANCH ? 'release':'dev')
}

How Jenkinsfile implements the default value obtained from the file

This method cannot be achieved, is there a way to achieve my needs.
def VERSION = readFile(file: '/opt/version').trim()
pipeline {
agent {
label 'maven'
}
parameters {
string(name: 'version', defaultValue: VERSION, description: 'version')
}
}
readFile is a Declarative Pipeline Step
https://www.jenkins.io/doc/pipeline/steps/workflow-basic-steps/#readfile-read-file-from-workspace
This means it can only be used in a steps block.
e.g.
stage("Stage1"){
steps{
script{
fileContents = readFile('/opt/version').trim()
}
}
}
To make dynamic parameters you would need to use the https://plugins.jenkins.io/uno-choice/ plugin.
But it would also depend on where the file you are trying to open is located as to whether this is possible or not.

Jenkins pipelineJob DSL not interpreting variables in pipeline script

I'm trying to generate Jenkins pipelines using the pipelineJob function in the jobDSL pluging, but cannot pass parameters from the DSL to the pipeline script. I have several projects that use what is essentially the same Jenkinsfile, with differences only in a few steps. I'm trying to use the JobDSL plugin to generate these pipelines on the fly, with the values I want changed in them interpreted to match the parameters to the DSL.
I've tried just about every combination of string interpretation that I can in the pipeline script, as well as in the DSL, but cannot get Jenkins/groovy to interpret variables in the pipeline script.
I'm calling the job DSL in a pipeline step:
def projectName = "myProject"
def envs = ['DEV','QA','UAT']
def repositoryURL = 'myrepo.com'
jobDsl targets: ['jobs/*.groovy'].join('\n'),
additionalParameters: [
project: projectName,
environments: envs,
repository: repositoryURL
],
removedJobAction: 'DELETE',
removedViewAction: 'DELETE'
The DSL is as follows:
pipelineJob("${project} pipeline") {
displayName('Pipeline')
definition {
cps {
script(readFileFromWorkspace(pipeline.groovy))
}
}
}
pipeline.groovy:
pipeline {
agent any
environment {
REPO = repository
}
parameters {
choice name: "ENVIRONMENT", choices: environments
}
stages {
stage('Deploy') {
steps {
echo "Deploying ${env.REPO} to ${params.ENVIRONMENT}..."
}
}
}
}
The variables that I pass in additionalParameters are interpreted in the jobDSL script; a pipeline with the correct name does get generated. The problem is that the variables are not passed to the pipeline script read from the workspace - the Jenkins configuration for the generated pipeline looks exactly the same as the file, without any interpretation on the variables.
I've made a number of attempts at getting the string to interpret, including a lot of variations of "${environments}", ${environments}, $environments, \$environments...I can't find any that work. I've also tried reading the file as a gstringImpl:
script("${readFileFromWorkspace(pipeline.groovy)}")
Does anyone have any ideas as to how I can make variables propagate down to the pipeline script? I know that I could just use a for loop to do string.replaceAll() on the script text, but that seems cumbersome; there's got to be a better way.
I've come up with a way to make this work. It's not what I'd prefer, which is having the string contents of the file implicitly interpreted during job creation, but it does work; it just adds an extra step.
import groovy.text.SimpleTemplateEngine
def fileContents = readFileFromWorkspace "pipeline.groovy"
def engine = new SimpleTemplateEngine()
template = engine.createTemplate(fileContents).make(binding.getVariables()).toString()
pipelineJob("${project} pipeline") {
displayName('Pipeline')
definition {
cps {
script(template)
}
}
}
This reads a file from your workspace, then uses it as a template with the binding variables. The other changes needed to make this work are escaping any variables used in your Jenkinsfile script, like \${VARIABLE} so that they are expanded at runtime, not at the time you build the job. Any variables you want to be expanded at job creation should be referenced as ${VARIABLE}.
You could achieve what you're trying to do by defining environment variables in the pipelineJob and then using those variables in your pipeline.
They are a bit limited because environment variables are strings, but it should work for basic stuff
Ex.:
//job-dsl
pipelineJob('example') {
environmentVariables {
// these vars could be specified by parameters of this job
env('repository', 'blah')
env('environments', "a,b,c"]) //comma separated string
}
displayName('Pipeline')
definition {
cps {
script(readFileFromWorkspace(pipeline.groovy))
}
}
}
}
And then in the pipeline:
//pipeline.groovy
pipeline {
agent any
environment {
REPO = env.repository
}
parameters {
choice name: "ENVIRONMENT", choices: env.environments.split(',')
//note the need to split the comma separated string above
}
}
You need to use the complete job name as a variable without the quotes. E.g., if JOBNAME is a parameter containing the entire job name:
pipelineJob(JOBNAME) {
displayName('Pipeline')
definition {
cps {
script(readFileFromWorkspace(pipeline.groovy))
}
}
}

String interpolation and concatenation for Jenkinsfile

I am trying to setup a Jenkinsfile that gets a job to call other jobs, based on the parameters passed into itself.
Instead of having multiple when conditions, I'm thinking that it would be smarter (and manageable for future scaling) if the names of the jobs being called would ideally be concatenating a common prefix with the parameter being passed in, for example:
CICD_api-gateway
CICD_front-end
CICD_customer-service
I'm having difficulty mixing string interpolation with string concatenation to achieve this:
build job: 'CICD_"${params.SERVICE_NAME}"', wait : false
In Linux, we are able to use eval to achieve this. I'm not sure what the equivalent is in Jenkinsfile syntax.
The full code below:
pipeline {
agent any
parameters { string(name: 'SERVICE_NAME', defaultValue: '', description: 'Service being deployed.') }
stages {
stage('Build Trigger'){
steps{
echo "CICD_${params.SERVICE_NAME}"
build job: 'CICD_"${params.SERVICE_NAME}"', wait : false
}
}
}
}
Change it to be a Gstring from the beginning, no need for the single quotes:
build job: "CICD_${params.SERVICE_NAME}", wait : false

Resources