How to display the selected parameter in Jenkins? - jenkins

There is a job groove pipeline that asks for parameters from the user interactively. After entering, I cannot display the selected parameters.
Here is my code:
node {
stage('Input Stage') {
Tag = sh(script: "echo 123'\n'456'\n'789'\n'111", returnStdout: true).trim()
input(
id: 'userInput', message: 'Choice values: ',
parameters: [
[$class: 'ChoiceParameterDefinition', name:'Tags', choices: "${Tag}"],
[$class: 'StringParameterDefinition', defaultValue: 'default', name:'Namespace'],
]
)
}
stage('Second Stage') {
println("${ChoiceParameterDefinition(Tags)}") //does not work
println("${ChoiceParameterDefinition(Namespace)}") //does not work
}
}
How to display the selected parameter correctly?

You would need to write the input step in a script. This should work.
node {
stage('Input Stage') {
Tag = sh(script: "echo 123'\n'456'\n'789'\n'111", returnStdout: true).trim()
script {
def userInputs =
input(
id: 'userInput', message: 'Choice values: ',
parameters: [
[$class: 'ChoiceParameterDefinition', name:'Tags', choices: "${Tag}"],
[$class: 'StringParameterDefinition', defaultValue: 'default', name:'Namespace'],
]
)
env.TAGS = userInputs['Tags']
env.NAMESPACE = userInputs['Namespace']
}
}
stage('Second Stage') {
echo "${env.TAGS}"
echo "${env.NAMESPACE}"
}
}
References:
Jenkins Declarative Pipeline: How to read choice from input step?
Read interactive input in Jenkins pipeline to a variable

Related

Active choice parameter with declarative Jenkins pipeline

I'm trying to use active choice parameter with declarative Jenkins Pipeline script.
This is my simple script:
environments = 'lab\nstage\npro'
properties([
parameters([
[$class: 'ChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Select a choice',
filterLength: 1,
filterable: true,
name: 'choice1',
randomName: 'choice-parameter-7601235200970',
script: [$class: 'GroovyScript',
fallbackScript: [classpath: [], sandbox: false, script: 'return ["ERROR"]'],
script: [classpath: [], sandbox: false,
script: """
if params.ENVIRONMENT == 'lab'
return['aaa','bbb']
else
return ['ccc', 'ddd']
"""
]]]
])
])
pipeline {
agent any
tools {
maven 'Maven 3.6'
}
options {
disableConcurrentBuilds()
timestamps()
timeout(time: 30, unit: 'MINUTES')
ansiColor('xterm')
}
parameters {
choice(name: 'ENVIRONMENT', choices: "${environments}")
}
stages {
stage("Run Tests") {
steps {
sh "echo SUCCESS on ${params.ENVIRONMENT}"
}
}
}
}
But actually the second parameter is empty
Is it possible to use together scripted active choice parameter and declarative parameter?
UPD
Is there any way to pass list variable into script? For example
List<String> someList = ['ttt', 'yyyy']
...
script: [
classpath: [],
sandbox: true,
script: """
if (ENVIRONMENT == 'lab') {
return someList
}
else {
return['ccc', 'ddd']
}
""".stripIndent()
]
You need to use Active Choices Reactive Parameter which enable current job parameter to reference another job parameter value
environments = 'lab\nstage\npro'
properties([
parameters([
[$class: 'CascadeChoiceParameter',
choiceType: 'PT_SINGLE_SELECT',
description: 'Select a choice',
filterLength: 1,
filterable: true,
name: 'choice1',
referencedParameters: 'ENVIRONMENT',
script: [$class: 'GroovyScript',
fallbackScript: [
classpath: [],
sandbox: true,
script: 'return ["ERROR"]'
],
script: [
classpath: [],
sandbox: true,
script: """
if (ENVIRONMENT == 'lab') {
return['aaa','bbb']
}
else {
return['ccc', 'ddd']
}
""".stripIndent()
]
]
]
])
])
pipeline {
agent any
options {
disableConcurrentBuilds()
timestamps()
timeout(time: 30, unit: 'MINUTES')
ansiColor('xterm')
}
parameters {
choice(name: 'ENVIRONMENT', choices: "${environments}")
}
stages {
stage("Run Tests") {
steps {
sh "echo SUCCESS on ${params.ENVIRONMENT}"
}
}
}
}
As of Jenkins 2.249.2 without any plugin and using a declarative pipeline,
the following pattern prompt the user with a dynamic dropdown menu (for him to choose a branch):
(the surrounding withCredentials bloc is optional, required only if your script and jenkins configuratoin do use credentials)
node {
withCredentials([[$class: 'UsernamePasswordMultiBinding',
credentialsId: 'user-credential-in-gitlab',
usernameVariable: 'GIT_USERNAME',
passwordVariable: 'GITLAB_ACCESS_TOKEN']]) {
BRANCH_NAMES = sh (script: 'git ls-remote -h https://${GIT_USERNAME}:${GITLAB_ACCESS_TOKEN}#dns.name/gitlab/PROJS/PROJ.git | sed \'s/\\(.*\\)\\/\\(.*\\)/\\2/\' ', returnStdout:true).trim()
}
}
pipeline {
agent any
parameters {
choice(
name: 'BranchName',
choices: "${BRANCH_NAMES}",
description: 'to refresh the list, go to configure, disable "this build has parameters", launch build (without parameters)to reload the list and stop it, then launch it again (with parameters)'
)
}
stages {
stage("Run Tests") {
steps {
sh "echo SUCCESS on ${BranchName}"
}
}
}
}
The drawback is that one should refresh the jenkins configration and use a blank run for the list be refreshed using the script ...
Solution (not from me): This limitation can be made less anoying using an aditional parameters used to specifically refresh the values:
parameters {
booleanParam(name: 'REFRESH_BRANCHES', defaultValue: false, description: 'refresh BRANCH_NAMES branch list and launch no step')
}
then wihtin stage:
stage('a stage') {
when {
expression {
return ! params.REFRESH_BRANCHES.toBoolean()
}
}
...
}

Unable to pass a parameter from one pipeline job to another

Editing the question: I am trying to run a simple pipeline job which triggers another pipeline job and sends parameter values.
I tried a simplified usecase in the example below
Piepeline - Parent
pipeline{
agent any
options {
buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '5')
}
stages {
stage('Invoke sample_pipleline') {
steps {
CommitID = 'e2b6cdf1e8018560b3ba51cbf253de4f33647b5a'
Branch = "master"
input id: 'Environment', message: 'Approval', parameters: [choice(choices: ['FRST', 'QA', 'PROD'], description: '', name: 'depServer')], submitter: 'FCMIS-SFTP-LBAAS', submitterParameter: 'user'
build job: 'simple_child',
parameters: [string(name: 'CommitID', value: 'e2b6cdf1e8018560b3ba51cbf253de4f33647b5a'),string(name: 'Environment', value: depServer), string(name: 'Branch', value: 'master')],
quietPeriod: 1
}
}
}
}
Pipeline - child
pipeline{
agent any
parameters {
string defaultValue: '', description: 'K', name: 'depServer'
}
options {
buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '5')
}
stages {
stage('CodePull') {
steps {
echo "Testing"
echo "${depServer}"
}
}
}
}
When I run the parent pipeline it did not trigger child pipeline but gave error.
Started by user ARAV
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Windows_aubale in C:\Users\arav\Documents\Proj\Automation\Jenkins\Jenkins_slave_root_directory\workspace\sample_parent2
[Pipeline] {
[Pipeline] stage
[Pipeline] { (Invoke sample_pipleline)
[Pipeline] input
Input requested
Approved by ARAV
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
groovy.lang.MissingPropertyException: No such property: depServer for class: groovy.lang.Binding
After implementing changes suggested and with some tweaks The parent job triggers the child job but the child log shows that it doesn't receive the parameter passed.
Started by upstream project "sample_parent" build number 46
originally caused by:
Started by user ARAV
Running in Durability level: MAX_SURVIVABILITY
[Pipeline] Start of Pipeline
[Pipeline] node
Running on Jenkins in /var/jenkins_home/workspace/simple_child
[Pipeline] {
[Pipeline] stage
[Pipeline] { (CodePull)
[Pipeline] echo
Testing
[Pipeline] echo
[Pipeline] }
[Pipeline] // stage
[Pipeline] }
[Pipeline] // node
[Pipeline] End of Pipeline
Finished: SUCCESS
Please help me understand what am I doing wrong here.
Appreciate your help!!
If your child pipeline has parameter named "depServer":
parameters {
string name: 'depServer', defaultValue: '', description: ''
}
You should provide a value for it:
build job: 'simple_child',
parameters: [string(name: 'depServer', value: 'SOMETHING']
Finally, you should address it:
steps {
echo "Testing"
echo "${params.depServer}"
}
groovy.lang.MissingPropertyException: No such property: depServer for
class: groovy.lang.Binding
This means that you don't have defined a variable depServer.
Fix it by assigning the result of the input step to variable depServer:
steps {
script {
def input_env = input id: 'Environment', message: 'Approval', parameters: [choice(choices: ['FRST', 'QA', 'PROD'], description: '', name: 'depServer')], submitter: 'FCMIS-SFTP-LBAAS', submitterParameter: 'user'
build job: 'simple_child',
parameters: [string(name: 'CommitID', value: 'aa21a592d1039cbce043e5cefea421efeb5446a5'),string(name: 'Environment', value: input_env.depServer), string(name: 'Branch', value: "master")],
quietPeriod: 1
}
}
I've added a script block, to be able to create and assign a variable.
The input actually returns a HashMap that looks like this:
[depServer:QA, user:someUser]
That's why we have to write input_env.depServer as argument for the build job.
Thank you so much zett42 and MaratC! So finally the code that worked is as follows(combining both the answers):
Parent script:
pipeline{
agent any
options {
buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '5')
}
stages {
stage('Invoke sample_pipleline') {
steps {
script{
def CommitID
def depServer
def Branch
CommitID = 'e2b6cdf1e8018560b3ba51cbf253de4f33647b5a'
Branch = "master"
userip = input id: 'Environment', message: 'Approval', parameters: [choice(choices: ['FRST', 'QA', 'PROD'], description: '', name: 'input_env')], submitter: 'FCMIS-SFTP-LBAAS', submitterParameter: 'user'
depServer = userip.input_env
echo "${depServer}"
build job: 'simple_child',
parameters: [string(name: 'CommitID', value: "${CommitID}"),
string(name: 'Environment', value: "${depServer}"),
string(name: 'Branch', value: "${Branch}")],
quietPeriod: 1
}
}
}
}
}
Child script:
pipeline{
agent any
parameters {
string defaultValue: '', description: 'K', name: 'Environment'
}
options {
buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '', numToKeepStr: '5')
}
stages {
stage('CodePull') {
steps {
echo "Testing"
echo "${params.Environment}"
}
}
}
}

Jenkins pipeline input script with one prompt only

Don't need 2 prompt in Jenkins pipeline with input script. In snippet, there is highlighted 1 and 2 where pipeline prompt 2 times for user input.
If execute this pipeline, prompt 1 will provide user to "Input requested" only, so no option to "Abort". Prompt 2 is okay as it ask to input the value and also "Abort" option.
Prompt 1 is almost useless, can we skip promt this and directly reach to prompt 2?
pipeline {
agent any
parameters {
string(defaultValue: '', description: 'Enter the Numerator', name: 'Num')
string(defaultValue: '', description: 'Enter the Denominator', name: 'Den')
}
stages {
stage("foo") {
steps {
script {
if ( "$Den".toInteger() == 0) {
echo "Denominator can't be '0', please re-enter it."
env.Den = input message: 'User input required', ok: 'Re-enter', // 1-> It will ask whether to input or not
parameters: [string(defaultValue: "", description: 'Enter the Denominator', name: 'Den')] // 2-> It will ask to input the value
}
}
sh'''#!/bin/bash +x
echo "Numerator: $Num\nDenominator: $Den"
echo "Output: $((Num/Den))"
'''
}
}
}
}
Yes, you can simplify the input by using $class: 'TextParameterDefinition'.
e.g.
pipeline {
agent any
parameters {
string(defaultValue: '', description: 'Enter the Numerator', name: 'Num')
string(defaultValue: '', description: 'Enter the Denominator', name: 'Den')
}
stages {
stage("foo") {
steps {
script {
if ( "$Den".toInteger() == 0) {
env.Den = input(
id: 'userInput', message: 'Wrong denominator, give it another try?', parameters: [
[$class: 'TextParameterDefinition', defaultValue: '', description: 'Den', name: 'den']
]
)
}
}
sh'''#!/bin/bash +x
echo "Numerator: $Num\nDenominator: $Den"
echo "Output: $((Num/Den))"
'''
}
}
}
}
If you want to go the extra mile and ask for both values:
def userInput = input(
id: 'userInput', message: 'Let\'s re-enter everything?', parameters: [
[$class: 'TextParameterDefinition', defaultValue: '', description: 'Denominator', name: 'den'],
[$class: 'TextParameterDefinition', defaultValue: '', description: 'Numerator', name: 'num']
]
)
print userInput
env.Den = userInput.den
env.Num = userInput.num

Extended Choice Parameter implementation

I'm setting up a new job in which we are required to select Multiple values. Need to select Service1 and Service2...
Went through link How to pass multi select value parameter in Jenkins file(Groovy)
However, I am not sure how to pass values in my Jenkinsfile
A snippet of Jenkinsfile
stage('parallel'){
parallel(
"service1": {stage('service1-deployment') {
if (params.ServiceName == 'Service1' || params.ServiceName == 'ALL'){
b = build(job: 'job name', parameters: [string(name: 'ENVIRONMENT', value: TARGET_ENVIRONMENT),string(name: 'IMAGE_TAG', value: value)], propagate: false).result
if(b=='FAILURE'){
echo "job failed"
currentBuild.result = 'UNSTABLE'
}
}
}
},
"service2": {stage('service2t') {
if (params.ServiceName == 'service2' || params.ServiceName == 'ALL'){
b = build(job: 'Job name', parameters: [string(name: 'ENVIRONMENT', value: TARGET_ENVIRONMENT),string(name: 'IMAGE_TAG', value: value)], propagate: false).result
if(b=='FAILURE'){
echo "job failed"
currentBuild.result = 'UNSTABLE'
}
}
}
},
I see that you're using declarative pipeline syntax for your job.
So, if the accepted answer for that question with booleanParam is useful for you, then you can use it inside parameters section (see the official documentation for more details):
pipeline {
agent any
parameters {
booleanParam(defaultValue: false, name: 'ALL', description: 'Process all'),
booleanParam(defaultValue: false, name: 'OPTION_1', description: 'Process option 1'),
booleanParam(defaultValue: false, name: 'OPTION_2', description: 'Process options 2'),
}
stages {
stage('Example') {
steps {
echo "All: ${params.ALL}"
echo "Option 1: ${params.OPTION_1}"
echo "Option 2: ${params.OPTION_2}"
}
}
}
}
However, if you want to use extended choice parameter with multiselect input, you need to use scripted pipeline syntax, see this example (already mentioned here).

How to get user input data in shell (Jenkinsfile)

I am trying to take user input through Jenkinsfile but I can't use that in the shell. Here is the code:
def userInput = timeout(time:60, unit:'SECONDS') {input(
id: 'userInput', message: 'URL Required', parameters: [
[$class: 'TextParameterDefinition', defaultValue: '', description: 'URL', name: 'url'],
])
}
node{
echo "Env jsfsjaffwef:"+userInput) //this works
echo "${userInput}" //but this does not
sh '''
python test.py ${userInput}
'''
}
Be careful about string interpolation: Variables will be replaced inside double quotes ("..", or the multi-line variant """), but not inside single quotes ('..', resp. '''..'''). So the sh step shouldn't have it replaced, the echo above should have it correctly.
def userInput = timeout(time:60, unit:'SECONDS') {input(
id: 'userInput', message: 'URL Required', parameters: [
[$class: 'TextParameterDefinition', defaultValue: '', description: 'URL', name: 'url'],
])
}
node {
echo "Env jsfsjaffwef:"+userInput) //this works
echo "${userInput}" // this should have also worked before
sh """
python test.py ${userInput}
"""
}
So make sure that you exactly apply the right quotes and don't just replace them compared to what people suggest here.
The following works for me on Jenkins 2.62:
def userInput = input(
id: 'userInput', message: 'URL Required', parameters: [
[$class: 'TextParameterDefinition', defaultValue: '', description: 'URL', name: 'url'],
])
node('master') {
sh "echo userInput is: ${userInput}"
}

Resources