I'm trying to access a variable from an input step using the declarative pipelines syntax but it seems not to be available via env or params.
This is my stage definition:
stage('User Input') {
steps {
input message: 'User input required', ok: 'Release!',
parameters: [choice(name: 'RELEASE_SCOPE', choices: 'patch\nminor\nmajor', description: 'What is the release scope?')]
echo "env: ${env.RELEASE_SCOPE}"
echo "params: ${params.RELEASE_SCOPE}"
}
}
Both echo steps print null. I also tried to access the variable directly but I got the following error:
groovy.lang.MissingPropertyException: No such property: RELEASE_SCOPE for class: groovy.lang.Binding
at groovy.lang.Binding.getVariable(Binding.java:63)
at org.jenkinsci.plugins.scriptsecurity.sandbox.groovy.SandboxInterceptor.onGetProperty(SandboxInterceptor.java:224)
What is the correct way to access this choice parameter?
Since you are using declarative pipelines we will need to do some tricks. Normally you save the return value from the input stage, like this
def returnValue = input message: 'Need some input', parameters: [string(defaultValue: '', description: '', name: 'Give me a value')]
However this is not allowed directly in declarative pipeline steps. Instead, what you need to do is wrap the input step in a script step and then propagate the value into approprierte place (env seems to work good, beware that the variable is exposed to the rest of the pipeline though).
pipeline {
agent any
stages {
stage("foo") {
steps {
script {
env.RELEASE_SCOPE = input message: 'User input required', ok: 'Release!',
parameters: [choice(name: 'RELEASE_SCOPE', choices: 'patch\nminor\nmajor', description: 'What is the release scope?')]
}
echo "${env.RELEASE_SCOPE}"
}
}
}
}
Note that if you have multiple parameters in the input step, then input will return a map and you need to use map references to get the entry that you want. From the snippet generator in Jenkins:
If just one parameter is listed, its value will become the value of the input step. If multiple parameters are listed, the return value will be a map keyed by the parameter names. If parameters are not requested, the step returns nothing if approved.
Using the Input Step in the following form works for multiparameters:
script {
def params = input message: 'Message',
parameters: [choice(name: 'param1', choices: ['1', '2', '3', '4', '5'],description: 'description'),
booleanParam(name: 'param2', defaultValue: true, description: 'description')]
echo params['param1']
echo params['param2']
}
#DavidParker, I have figured out what you are asking. Just try to use it in your code. I have input params and using them 1 by 1. I am printing only "variable" key in job which is working. You can also try this way.
steps{
script {
deploymentParams.findAll{ key, value -> key.startsWith('backendIP') }.each { entry ->
stage("Node_$entry.key "){
echo $entry.value
}
}
}
}
Related
I need a plugin where a team lead can approve if a pipeline can move to the next stage in Jenkins. I am planning to use multistage pipeline(declarative) so after dev stage I need a person to approve(only he can approve) and the developer folks can just run the job. Is there any such plugin available so that only one person can approve such request?
tried role based access plugin but here there is no ways to control segregate people who can do stage approvals
#sidharth vijayakumar, I guess you can make use of the 'Pipeline: Input Step' plugin.
As per my understanding, this plugin pauses Pipeline execution and allows the user to interact and control the flow of the build.
The parameter entry screen can be accessed via a link at the bottom of the build console log or via link in the sidebar for a build.
message
This parameter gives a prompt which will be shown to a human:
Ready to go?
Proceed or Abort
If you click "Proceed" the build will proceed to the next step, if you click "Abort" the build will be aborted.
Your pipeline script should look like some what similar to below snippet
// Start Agent
node(your node) {
stage('Checkout') {
// scm checkout
}
stage('Build') {
//build steps
}
stage('Tests') {
//test steps
}
// Input Step
{
input message: 'Do you want to approve if flow can proceeded to next stage?', ok: 'Yes'
}
stage('Deploy') {
...
}
}
Reference link : https://www.jenkins.io/doc/pipeline/steps/pipeline-input-step/
To solve the problem of role based approval i used input block with submitter. This means that person who listed as the submitter will only be able to give stage approvals.
stage('Approval') {
agent none
steps {
script {
def deploymentDelay = input id: 'Deploy', message: 'Deploy to production?', submitter: 'rkivisto,admin', parameters: [choice(choices: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24'], description: 'Hours to delay deployment?', name: 'deploymentDelay')]
sleep time: deploymentDelay.toInteger(), unit: 'HOURS'
}
}
}
Please note there submitter must be a valid user. Use role based access plugin and create a user with relevant access.
Reference link for the script :
https://support.cloudbees.com/hc/en-us/articles/360029265412-How-can-I-approve-a-deployment-and-add-an-optional-delay-for-the-deployment
Can we write like this in pipeline script?. Need to populate the string by choice parameter. I am new to Jenkins world.
parameters { choice(name: 'CHOICE', choices: ['FirstName', 'LastName'], description: 'Pick something') }
script {
if (${CHOICE} == "FirstName")
{
parameters { string(name: 'FirstName', defaultValue: '', description: 'This is FirstName')}
}
else
{
parameters { string(name: 'LastName', defaultValue: '', description: 'This is LastName') }
}
}
Is there any other way to do it inside the jenkins? Any plugin which can help!
It's a bit unclear what exactly you are trying to achieve.
If what you want is interactivity — when you make a choice in the dropdown box, the contents of another parameter changes based on your choice — then ActiveChoice plugin can help you with that.
If you want to define different params as depending on your choice of the first one, then it's not possible. Jenkins needs to fully parse your Jenkinsfile (parameters and all) in order to present you with the parameters screen, but you seem to want to define your parameters based on the results of the presentation. This is a kind of a chicken and egg problem here.
In jenkins I'd like to do this:
parameters {
choice(
name: 'blah',
choices: 'one\ntwo\ncustom',
description: 'if you choose custom enter a custom number'
)
}
So they have three options on the drop down, but it would be nice if when they select the "custom" choice jenkins pops an input box to type in raw user input.
Is this possible? I don't want to use user input during the pipeline run because that means they need to choose custom then wait for jenkins to get to the stage where it asks them for input.
Yep, Once the build starts, check the value of params.blah and throw up an input step with a String param, so
if (params.blah == 'custom' ) {
timeout(time: 1, unit: 'minute') { // change to a convenient timeout for you
userInput = input(
id: 'Proceed1', message: 'Custom value?', parameters: [
[$class: 'StringParameterDefinition', defaultValue: '',
description: 'Enter Custom value', name: 'Value']
])
}
}
In my Jenkins multi pipeline project i am having a input step like this:
input message: 'Merge', parameters: [[$class: 'BooleanParameterDefinition', defaultValue: true, description: '', name: "Merge ${branchConfig.merge} to ${env.BRANCH_NAME}?"]]
I am starting this job by calling this url:
http://user:api-token#awesome.jenkins.de/job/myTest/job/dev/build
Now I want to add a GET parameter like this:
http://user:api-token#awesome.jenkins.de/job/myTest/job/dev/build?skipInput=true
My question now is, how can I get this parameter in groovy?
UPDATE: Following the first comment, I did the following:
// Add parameter to skip MergeInput.
properties([[$class: 'ParametersDefinitionProperty', parameterDefinitions: [[$class: 'BooleanParameterDefinition', name: 'skipMergeInput', defaultValue: false]]]])
And adjusted the input like that:
input message: 'Merge', parameters: [[$class: 'BooleanParameterDefinition', defaultValue: params.skipMergeInput, description: '', name: "Merge ${branchConfig.merge} to ${env.BRANCH_NAME}?"]]
When I am now starting my job, it shows me a popup that ask for the value that should be set. But no matter what i decide, the input is always false. I am trying to figure out what is going wrong and will update my post then.
UPDATE 2:
So I kept on debugging. I added the following to my groovy script:
// Add parameter to skip MergeInput.
def doMerge = properties([[$class: 'ParametersDefinitionProperty', parameterDefinitions: [[$class: 'BooleanParameterDefinition', name: 'doMerge', defaultValue: true]]]])
println doMerge;
The output returns me NULL, and when I am doing something like
println params.doMerge
It tells me that params is not defined. Any idea what is going wrong?
UPDATE 3:
Call URL: /job/dg_test/job/master/buildWithParameters?test=true
Groovy Script:
properties([[$class: 'ParametersDefinitionProperty', parameterDefinitions: [[$class: 'BooleanParameterDefinition', name: 'test', defaultValue: false]]]])
println params.test
Result:
No such property: params for class: groovy.lang.Binding
I finally solved it, this post really helped me: https://stackoverflow.com/a/41276956/1565249
And this is my implementation:
// Add fancy build parameter.
properties([
parameters([
booleanParam(
defaultValue: false,
description: 'Some description',
name: 'developmentMerge'
),
])
])
if (developmentMerge == "true" || developmentMerge == true) {
// Your code here
}
else {
// Your code here
}
When I now start my job manually from the GUI, it asks me which value should be set for "developmentMerge".
And I also can start my job by calling this URL:
"/job/dg_test/job/master/buildWithParameters?developmentMerge=true"
Where "dg_test" is the name of my Jenkins project and "master" is the job i wanted to start.
The if statement must be done like this:
if (developmentMerge == "true" || developmentMerge == true)
because when you start the job from GUI, it will send a boolean "true", but when you start the job by the URL call, you receive a string.
This is achievable in 3 simple steps:
Set a boolean parameter for your pipeline build:
Use the "params." prefix to access your parameter in your input message step:
input message: 'Merge', parameters: [[$class: 'BooleanParameterDefinition', defaultValue: params.skipInput, description: '', name: "Merge ${branchConfig.merge} to ${env.BRANCH_NAME}?"]]
Use the "buildWithParameters" api command rather than "build":
http://user:api-token#awesome.jenkins.de/job/myTest/job/dev/buildWithParameters?skipInput=true
I wanted to run a jenkins job by accepting a date field (in format YYYY-MM-DD) from user. I found a link where user can enter a string parameter:
job('example') {
parameters {
stringParam('myParameterName', 'my default stringParam value', 'my description')
}
}
But in string param user can enter any thing. So how do I force user to enter a date field like a calender field and select date from the calender ?
There seems to be no plugin which provides a date chooser.
But you can use the Validating String Parameter Plugin, which can use a regular expression to validate a string parameter. See Regex to validate date format dd/mm/yyyy for regular expressions matching date values.
The Job DSL plugin has no built-in support for the Validating String Parameter Plugin, but you can use a Configure Block to add the relevant config XML.
job('example') {
configure { project ->
project / 'properties' / 'hudson.model.ParametersDefinitionProperty' / parameterDefinitions << 'hudson.plugins.validating__string__parameter.ValidatingStringParameterDefinition' {
name('DATE')
description('date in YYYY-MM-DD format')
defaultValue('2016-03-01')
regex(/\d\d\d\d-\d\d-\d\d/)
failedValidationMessage('Enter a YYYY-MM-DD date value!')
}
}
}
I came across this same issue today and this is how I solved it.
Using: Active Choice Plugin
In a Declarative Pipeline I added the following parameter
[$class: 'DynamicReferenceParameter',
choiceType: 'ET_FORMATTED_HIDDEN_HTML',
description: '',
name: 'YOUR_PARAMETER_NAME',
omitValueField: true,
referencedParameters: '',
script: [
$class: 'GroovyScript',
fallbackScript: [classpath: [], sandbox: false, script: ''],
script: [
classpath: [],
sandbox: false,
script: 'return "<input type=\\"date\\" name=\\"value\\" value=\\"\\" />"'
]
]
]
Basically it adds an HTML Input Element of type Date, which you can then catch the value during the run.
pipeline {
agent { label "master" }
stages {
stage('Output Date') {
steps {
script {
println params.YOUR_PARAMETER_NAME
}
}
}
}
}
Here's a picture of how it looks on Chrome:
HTML Date parameter
Note: You can also use it to add parameters of type TextArea and so on.