Jenkins: set a parameter defaultValue dynamically - jenkins

I'm trying to set up a multibranch pipeline configuration where the "Deploy" boolean checkbox is defaulted to true on non-production branches, and false on the production build.
pipeline {
parameters{
booleanParam(defaultValue: true, description: 'Do deploy after build', name: 'DEPLOY')
Is there some method to conditionally set defaultValue=false when $BRANCH_NAME == "production"?

I think I might have answered my own question through a bunch of experimentation. This seems crazy simple, but my test between two branches shows the Deploy parameter is properly defaulted on/off depending on the $BRANCH_NAME
def defaultDeploy = true
if ( BRANCH_NAME == "production" )
{
defaultDeploy = false
}
pipeline {
parameters{
booleanParam(defaultValue: defaultDeploy,
description: 'Do deploy after build', name: 'DEPLOY')

Answering the question of the poster in a more generic way, the parameters default values can also be set dynamically injecting properties with EnvInject plugin. Also Extended Choice Parameter plugin is needed to run the example. Create a declarative pipeline project with the following content:
pipeline {
agent any
parameters {
extendedChoice(
name: 'ArchitecturesCh',
defaultValue: "${env.BUILD_ARCHS}",
multiSelectDelimiter: ',',
type: 'PT_CHECKBOX',
value: 'linux-x86_64,android-x86_64,android-arm,android-arm64,ios-arm64,Win32,Win64'
)
string(name: 'ArchitecturesStr', defaultValue: "${env.BUILD_ARCHS}", description: "")
}
stages {
stage('Test') {
steps {
echo params.ArchitecturesCh
echo params.ArchitecturesStr
echo "${env.BUILD_ARCHS}"
}
}
}
}
Then prepare an environment with the EnvInject plugin. NOTE: Be careful not to clash with other environment variables. In my case I lost much time thinking the method was not working because an ARCHITECTURES variable is set somewhere else. In the same pipeline project GUI:
Save and build the pipeline, refresh the page. The default parameters will be available in the following build.

In your question, it's a bit unclear whether BRANCH_NAME refers to an environment variable (as in env.BRANCH_NAME) or to another parameter (as in params.BRANCH_NAME).
If former, then there's some environment variables, meaning that there's an environment, and so a node must have been allocated with its environment set. To allocate a node, the pipeline needs to start running. To start running, the user needs to select the parameters to run the pipeline. So it's a chicken-and-egg problem: you can't have environment variable before running pipelines, and you need to determine the parameters before running the pipeline.
If latter, and you are thinking of a case where, maybe, there's a String parameter that goes by the name of BRANCH_NAME, and a Boolean parameter that goes by the name of DEPLOY, and on the parameters page the checkbox DEPLOY is unchecked when you type maste into BRANCH_NAME, but once you press the r it magically becomes checked ... then it could be done — with a lot of pain — by using the Active Choice plugin.
Finally, if what you want is to prevent any deploying from the master branch, you may check for both the parameter and the branch name before deploying, and refuse to deploy if the parameter is false or if the branch is master.

Related

Jenkins parameter does not exist on first run (multibranch)

I'm having a problem with a Jenkins multibranch pipeline, which is parameterized. The parameters are all declared in the Jenkinsfile.
The problem is that these parameters do not exist on the very first run of the job. So, the very first execution will fail with groovy.lang.MissingPropertyException. Any subsequent run is now aware of the parameters and will not fail.
Since this is a multibranch pipeline this happens for every new pull request or tracked branch. Is there any workaround to avoid this problem?
I tried setting the parameters in the UI as well, however there is no option on the pipeline configuration page to set parameters. Probably because this is a multibranch pipeline?
Cheers
This is a known issue with Parameters in Pipelines. To know which parameters are needed, Jenkins needs to execute the Jenkinsfile once. For example the parameters in the GUI are not available until after the first run of the pipeline.
To prevent errors, you could specify sensible default values like this:
pipeline {
agent any
parameters {
string(name: 'Greeting', defaultValue: 'Hello', description: 'How should I greet the world?')
}
stages {
stage('Example') {
steps {
echo "${params.Greeting} World!"
}
}
}
}

How to pass environment variable to Jenkins Remote API when submitting job

I have a declarative pipeline job (this is not multi-branch pipeline job using Jenkinsfile) without parameters but some stages are conditional based on value in environment variable:
stage('deploy-release') {
when {
environment name: 'GIT_BRANCH', value: 'master'
}
steps {
sh "mvn deploy:deploy-file -B -DpomFile=pom.xml -Dfile=target/example.jar -DrepositoryId=maven-releases -Durl=${NEXUS_URL}/repository/maven-releases/"
}
}
I want to trigger the job from external system but I need to pass correct value of given environment variable. Is there some way how to do that via Jenkins Remote API?
For passing value of given environment variable, you need to define parameters with the exact same name as that of environment variable for your job by selecting "This build is parameterized".
You can refer Parameterized Build

How to retrieve job name in parameterized Jenkins Pipeline Project

I have a parameterized pipeline project with active choices parameter, where choice list is dynamically populated by groovy script. I need to retrieve and use current job name in the script. The following line works for me in Freestyle Projects:
def jobName = this.binding.jenkinsProject.name
However when I try to use it in Pipeline Project I get:
No such property: jenkinsProject for class: groovy.lang.Binding
In Retrieving Jenkins job name using groovy script in Active Choice Reactive Parameter it's stated that this has been resolved in Active Choices plugin v1.4. I'm using version 2.2.1 and the issue still persists. Is this property not available in Pipeline Project? Is there a workaround or an alternative?
If you trying to get the current build job name inside running job
There is a builtin env variable for it:
JOB_BASE_NAME
You can see list of available env variable in your Jenkins at
http://{hostname}/job/{jobname}/pipeline-syntax/globals
Jest replace hostname with your Jenkins address and jobname with some job you have in your Jenkins.
My Jenkins
Jenkins version: 2.176.2
Active Choices Plug-in: 2.2.1
Worked with pipeline job.
If you trying to do it in the parameters script I'm not sure that possible.
I faced the same issue and came up with a solution.
You can use Jenkins pipeline currentBuild variable, more about its properties - open page jenkins-server-url/jenkins/pipeline-syntax/globals on your Jenkins server
String currentJobParentFolderName = currentBuild.fullProjectName.split('/')[0]
String currentJobName = currentBuild.projectName
String paramValue = getParamValue(currentJobName)
properties([
buildDiscarder(logRotator(daysToKeepStr: '10')),
disableResume(),
parameters([
[$class: 'CascadeChoiceParameter',
name: 'PARAM',
choiceType: 'PT_SINGLE_SELECT',
description: 'param1',
filterLength: 1,
filterable: false,
randomName: 'choice-parameter-99999999999',
script: [
$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: false,
script:
'return ["Failed to get values"]'
],
script: [
classpath: [],
sandbox: false,
script:
"""return ['$paramValue']"""
]
]
]
])
])
timestamps {
job's main logic
}
private static def getParamValue(String jobName) {
Map paramValMapping = [
'jobName1': 'value1',
'jobName2': 'value2',
]
String paramValue = paramValMapping.get(jobName)
if (!paramValue) {
throw new Exception("Failed to get value")
}
return paramValue
}
currentBuild.fullProjectName - job name including upper level folders (I needed exactly this)
currentBuild.projectName - just a job name
Unfortunately I didn't manage to place all this logic inside of CascadeChoiceParameter script section.
Also I needed only one value, but this approach can be used for a list of values as well, just don't forget about quotes for string values.
Pay attention that such script changes may require script approve from Jenkins admin in jenkins/scriptApproval for EACH incoming value paramValue
So for everyone who's still looking for a solution to this problem, there are actually three ways you could go about solving this.
The reason why the jenkinsProject variable is not available in Pipeline jobs is due to an issue with the active choices plugin itself. You can read more about this in the following ticket: https://issues.jenkins.io/browse/JENKINS-29407. There's a separate feature branch in the Active Choices project on GitHub that (kinda) solves this issue: https://github.com/jenkinsci/active-choices-plugin/tree/pipeline-support. It wasn't merged into master (and it looks like it never will be), because adding this to Pipeline jobs breaks this functionality for the Freestyle jobs. What you can do is you can compile the plugin from the source yourself and install it on your Jenkins. Pipeline jobs will have the binding variables available in their active choice parameters, however Freestyle jobs will no longer have them. Only use this if the following two options are for some reason not possible in your case.
You can use the properties{} step to configure job parameters from the pipeline run. During pipeline run you could simply use the JOB_BASE_NAME environment variable as an expression of the GString that you'd pass as a script text. The only disadvantage here is that the parameters will only become available after the first build. So if you have a new job you'd need to trigger it once before it becomes parameterized.
You could just use the input() step. Your job won't be parametrized, but users will be able to provide their input to the build during its run. It's not very convenient if you need it to be triggered by some other job or an external webhook, but for cases where the job is expected to only be triggered manually it's probably the best option.

How to create a mask with parameters from the pipeline source code automatically in Jenkins?

I have some pipelines in Jenkins (storeed on github) and they successfully work when run.
All of these pipelines have the own set of parameters written in this way:
pipeline {
agent any
environment {
...
}
parameters {
booleanParam(name: 'TEST', defaultValue: false, description: 'Run task in test mode')
choice(name: 'TASK', choices: ['REFRESH', 'BUILD'], description: 'Pick task')
}
...
}
However the mask is not automatically reflected on the Jenkins server unless I manually use the option in Configure General -> This project is parameterised and add all the variable singularly (duplication of work).
Is there any way to make Jenkins able to build the mask form the coded committed on Github (or any Git server)?

How do I set a Jenkins environment variable based on a job parameter?

I have a project where I need to set an environment variable based on a choice parameter the user chooses. Each project has a theme project dependency. I'd like to have the user choose the project and then load the theme name from a property file. Something like
proj1=theme1
proj2=theme2
proj3=theme3
If the user chooses proj1 from the PROJECT_NAME choice parameter, I want to automatically set THEME_NAME to be theme1. What would be the best way to go about this?
I don't want to modify the Jenkins job config whenever a new project is added. Instead, I want to have the mapping in a file so I can have it in version control.
I will provide an alternative solution which I used. I hope it can also be useful for others.
I used Environment Injector Plugin. Go to the plugin manager and install it.
Check Inject environment variables to the build process property of the Build Environment. Define the following in Groovy Script:
Aha, I found a simple solution! Using the EnvInject plugin, in the job config:
Build Environment
[X] Inject environment variables to the build process
Properties File Path C:\pathtofile\mapping.properties
Properties Content THEME_NAME=${${PROJECT_NAME}}
Works like a charm!
Sometimes its nice to be able to set parameters through Jenkins and in turn trickle those as Jenkins env. vars. Things like passwords can be protected in parameters but cannot through the Environment Injector Plugin.
An example to do this:
environment {
AWS_ECR_ACCOUNT_ID="${params.AWS_ECR_ACCOUNT_ID}"
AWS_ACCESS_KEY_ID="${params.AWS_ACCESS_KEY_ID}"
AWS_SECRET_ACCESS_KEY="${params.AWS_SECRET_ACCESS_KEY}"
AWS_SESSION_TOKEN="${params.AWS_SESSION_TOKEN}"
}
parameters {
string(name: 'AWS_ECR_ACCOUNT_ID', defaultValue: '', description: 'AWS ECR account ID')
password(name: 'AWS_ACCESS_KEY_ID', defaultValue: '', description: 'The AWS access key ID')
password(name: 'AWS_SECRET_ACCESS_KEY', defaultValue: '', description: 'The AWS secret access key')
password(name: 'AWS_SESSION_TOKEN', defaultValue: '', description: 'The AWS session token')
}
And just set the params in the UI:
I hope you are talking about parameterized build in jenkins. So if you give choice parameter the name PROJECT_NAME and the choices to be :-
proj1
proj2
proj3
then, Jenkins will automatically assign one of these value(i.e proj1, proj2, proj3) to variable PROJECT_NAME as per the choice triggered to start the build. You can infact use $PROJECT_NAME as a variable anywhere in the job configuration page.
But you require the values (theme1, theme2, theme3)..such mapping to my knowledge is not provided by jenkins.
However you could use a build shell to perform your mapping:-
if [ $PROJECT_NAME = "proj1" ]
then <your logic goes here for implementing theme1>
fi
.....

Resources