I'm trying to create dynamic Jenkins job pipeline stages based on an array of values but I can't seem to get the loop functioning as expected, it complains about the syntax I'm using but I can't figure it out, is this a Groovy issue?
Approach
uat_nodes:
- 'node1'
- 'node2'
dsl: |
stage('Update UAT dist') {{
build job: '{key}-{module}-DP-BuildNamedDist-UAT'
}}
def UAT_NODES = {uat_nodes}
UAT_NODES.each { UAT_NODE ->
stage('Deploy code to UAT node: ' . ${{UAT_NODE}}) {{
build job: '{key}-{module}-DP-UAT-Nodes', parameters: [
string(name: 'LIMIT', value: '${{UAT_NODE}}'),
string(name: 'PLAYBOOK', value: '{playbook}')
]
}}
}
Error
WorkflowScript: 8: Ambiguous expression could be either a parameterless closure expression or an isolated open code block;
solution: Add an explicit closure parameter list, e.g. {it -> ...}, or force it to be treated as an open block by giving it a label, e.g. L:{...} # line 8, column 56.
e to UAT node: ' . ${{UAT_NODE}}) {{
As the error states, there is a problem with this piece of code: . ${{UAT_NODE}}
If strings would have a $ method, that would call it with a closure inside a closure, that returns UAT_NODE.
I can only assume, that you want to concat strings here similar to perl or php. This is not how it works in groovy.
Use: "Deploy code to UAT node: ${UAT_NODE}". Note the double quotes "! Single quotes ' won't give you replacement (this is every other string you are using in your code).
Related
What does this mean in docker-compose.yml directive?
${{ variable }}
And how is it used?
In a pipeline, template expression variables (${{ variables.var }}) get processed at compile time, before runtime starts. Macro syntax variables ($(var)) get processed during runtime before a task runs. Runtime expressions ($[variables.var]) also get processed during runtime but were designed for use with conditions and expressions. When you use a runtime expression, it must take up the entire right side of a definition.
In the following example, you can see that the template expression still has the initial value of the variable after the variable is updated. The value of the macro syntax variable updates. The template expression value does not change because all template expression variables get processed at compile time before tasks run. In contrast, macro syntax variables are evaluated before each task runs.
variables:
- name: one
value: initialValue
steps:
- script: |
echo ${{ variables.one }} # outputs initialValue
echo $(one)
displayName: First variable pass
- bash: echo "##vso[task.setvariable variable=one]secondValue"
displayName: Set new variable value
- script: |
echo ${{ variables.one }} # outputs initialValue
echo $(one) # outputs secondValue
displayName: Second variable pass
I am testing in declarative pipeline. (if you have idea in scriped pipeline, that is welcome too.)
We know in pipeline, we can set parameter as below:
parameters {
string(name: "parametera", defaultValue : "a value", description: "description a")}
I wannt it to be a value by script executing, like below :
sh("echo ${JOB_NAME} | cut -d '_' -f 3")
something like below
parameters {
string(name: "parametera", defaultValue : sh("echo ${JOB_NAME} | cut -d '_' -f 3"), description: "description a")}
Unfortunately, it didn't work, it will get synax error, like below.
Caused: java.lang.IllegalArgumentException: Could not instantiate {name=parametera, defaultValue={name=sh, args={<anonymous>=echo mlp_loyalty-booster-center_dev_DEV-debugging | cut -d '_' -f 3}}, description=description a} for hudson.model.StringParameterDefinition
How can I do this, any idea please ?
You have a kind of a chicken-and-egg problem.
To run your job (Groovy code), parameters must be set before the code runs. However, you want to set the parameters by running Groovy code. There's a contradiction there.
You may fool the system by having a scripted pipeline before a declarative one, e.g. like this:
def part3 = null
println "The value of part3 before scripted pipeline is ${part3}"
node('master') {
stage('Calculate part3') {
println "The value of part3 before calculation is ${part3}"
part3 = sh returnStdout: true, script: "echo ${JOB_NAME} | cut -d '_' -f 3"
println "The value of part3 after calculation is ${part3}"
}
}
println "The value of part3 after scripted pipeline is ${part3}"
pipeline {
parameters {
string(name: "parametera", defaultValue : part3, description: "description a")}
...
}
This will not work in all cases, specifically first run of your pipeline will use null, and subsequent runs will use the result of a previous run (to get out of chicken-and-egg problem outlined above). This may or may not be what you want. If you have a multi-branch configuration, the previous run on a specific branch is good enough as branches do not change between the runs.
I am using Choice param in my jenkins file to select environment as follows:
pipeline {
agent any
parameters {
choice(
name: 'ENVIRONMENT_URL',
choices: "https://beta1.xyz.com\nhttps://beta2.xyz.com\nhttps://beta3.xyz.com",
description: 'interesting stuff' )
}
in the Stage section, i have the following piece
stage('execute tests') {
steps {
script {
sh """URL=${ENVIRONMENT_URL} npm run e2e:tests"""
sh 'echo -e "\nTest Run Completed.\n"'
}
}
}
However, when i run the pipeline job by selecting the choice parameter i added, the following gets executed (the inserted choice param creates a line break):
+ URL=https://beta1.xyz.com
+ npm run e2e:tests
Using the variable is causing a line break and that's what is causing issue.
I have tried different ways to avoid line break. Tried using a variable but that didn't help. tried with different quotations, that didn't either.
What can i do to avoid line break ?
You can use the trim method on a String class type to remove trailing whitespace and newline:
sh "URL=${params.ENVIRONMENT_URL.trim()} npm run e2e:tests"
Note I also specified your parameter is in the params map and removed the triple quotes as those are for multiline string formatting.
Alternatively, you can specify the choices as an array instead of as a multiline string. The choices argument would then appear like:
choice(
name: 'ENVIRONMENT_URL',
choices: ['https://beta1.xyz.com', 'https://beta2.xyz.com', 'https://beta3.xyz.com'],
description: 'interesting stuff'
)
Either solution would fix your issue.
I cannot get Jenkins to pass a string Parameter down the pipeline.
When I run the pipeline, I input the string value for $ServiceName and the job continues but it doesn't pass this param to the first job in the pipe (NEWSERVICE - Add New). In the jenkins file in the 'build' stage I've tried params.ServiceName, $params.ServiceName, env.ServiceName, $env.ServiceName, $env:ServiceName. No luck.
I need to pass the param to a Powershell build process in the NEWSERVICE job (which currently just echos the Param with $env:ServiceName - but it's always empty) Any help would be vastly appreciated.
pipeline {
agent any
parameters{
string(name: 'ServiceName',
defaultValue: '',
description: '',)
}
stages {
stage('Add new Service'){
steps {
build(job: "NEWSERVICE - Add New", parameters: [string(name: 'ServiceName', value: params.ServiceName)])
}
}
}
}
In Pipeline you need to pass string parameters like this:
parameters: [
[$class: 'StringParameterValue', name: 'ServiceName', value: ServiceName]
],
Refer this to understand different type of variable passing while calling a job from Jenkinsfile.
https://jenkins.io/doc/pipeline/steps/pipeline-build-step/
If you are looking to use a Jenkins env var in a powershell script - which i do all the time! - the env var has to be set up as such in Jenkins first. In other words,
env.myVar in a Jenkins context will be visible as $env:myVar in a PowerShell context. But you need to set it as an env var, local Jenkins variables won't be visible to a child script (unless passed in as a parameter). I have a detailed writeup here: https://stackoverflow.com/a/62538778/556078
I'm trying to pass groovy variable to powershell script inside of jenkins pipeline, all in the same place but i don't know how. i tried different ways without success.
I require this to obtain the name of the person who approved the step of PIPELINE and pass it to powershell, which connects with SQL SERVER
stage('Step1'){
steps{
script{
def approverDEV
approverDEV = input id: 'test', message: 'Hello', ok: 'Proceed?', parameters: [choice(choices: 'apple\npear\norange', description: 'Select a fruit for this build', name: 'FRUIT'), string(defaultValue: '', description: '', name: 'myparam')], submitter: 'user1,user2,group1', submitterParameter: 'APPROVER'
echo "This build was approved by: ${approverDEV['APPROVER']}"
}
}
}
stage('Step2'){
steps{
script{
powershell ('''
# Example echo "${approverDEV['APPROVER']}"
# BUT THIS DOESN'T WORK :(
''')
}
}
}
I expect the output is the name of the approver stored in the variable GROOVY approverDEV
Dagett is correct, use double-quotes around the powershell script, then the variables will be evaluated:
script{
powershell ("""
# Example echo "${approverDEV['APPROVER']}"
# BUT THIS DOESN'T WORK :(
""")
}
Using triple double quotes in Groovy is called 'multi-line GString'. In a GString, variables will be evaluated before creating the actual String.