I have a build pipeline. I am still learning groovy. I am doing something simple like this
stage('test'){
def temp = 3 \\ reading this value from other env variable
while(temp != 1) {
temp=temp-1
echo temp
}
}
It always echoes 3 and while is never-ending.
When you read the value from the environment variable, you're getting it as a String
You need to convert it to an Integer
def temp = env.SOMETHING.toInteger()
Or, define it as an integer instead of using def:
int temp = env.SOMETHING
Related
I have a Jenkins variable BUILDVERSION_DATE in stage which is calculated and formatted correctly. Everything works perfectly.
script {
def now = new Date();
def inOneHour = new Date(now.getTime() + 1 * 3600 * 1000);
println inOneHour.format("yyyy-MM-dd-HH-mm-ss", TimeZone.getTimeZone('UTC'))
def BUILDVERSION_DATE=inOneHour.format("yyyy-MM-dd-HH-mm-ss", TimeZone.getTimeZone('UTC'))
}
Now I would like to use this calculated variable in multiple stages (without code repetition).
I have tried to put this code into environment {...} section but it fails.
If it was static variable I know I can define it in environment segment.
But how this calculated variable be defined and used in multiple stages?
Thanks!
If you want to add this value to an environment variable named BUILDVERSION_DATE, then you can assign it to the env object intrinsic to Jenkins Pipeline:
env.BUILDVERSION_DATE=inOneHour.format("yyyy-MM-dd-HH-mm-ss", TimeZone.getTimeZone('UTC'))
I'm using the Jenkins scripted pipeline and having trouble understanding how to nest environment variables within each other, here is a MWE:
// FROM https://jenkins.io/doc/pipeline/examples/#parallel-multiple-nodes
def labels = []
if (HOST == 'true') {
labels.add(<HOSTNAME>)
}
def builders = [:]
for (x in labels) {
def label = x
builders[label] = {
ansiColor('xterm') {
node(label) {
stage('cleanup') {
deleteDir()
}
stage('build') {
env.test = "TESTA"
env.intern = '''
TEST = "${env.test}"
'''
sh '''
echo $intern
printenv
'''
}
}
}
}
}
parallel builders
The idea here is that env.test contains the value TESTA, which sets env.intern to TEST = TESTA this is what I want to happen. After this the code is just to print out the values.
Sadly the result is TEST = "${env.test}".
How can I use nested string environment variables in Jenkins scripted pipeline?
The syntax difference here is literal strings versus interpolated strings in Groovy versus shell interpreters within shell step methods.
": interpolated string in Groovy
': literal string in Groovy and interpolated string in shell interpreter
Essentially, a Groovy variable is interpolated within " in the pipeline execution, and an environment variable is interpolated within " in the pipeline execution and within ' in the shell interpreter (and within the pipeline must also be accessed within the env object, but is a first class variable expression in the shell step method).
Therefore, we can fix the assigned value of env.intern with:
env.intern = "TEST = ${env.test}"
where the assigned value of env.test will be interpolated within the Groovy string and assigned to the env pipeline object at the intern key. This will then also be accessible to the shell interpreter within shell step methods, and the rest of your pipeline is already correct and will behave as expected.
Try the following:
env.intern = "TEST = ${env.test}"
As you're setting it now, the actual result of env.intern will be "TEST= ${env.test}". So long as you set env.test before you set env.intern you should be good. Also, good to note that if you change the value of env.test then you need to reset the value of env.intern or it's going to hold the original value of env.test that it was set to.
I am using branch name to pass it into build script. $(env.BRANCH_NAME).
I would like to manipulate the value before using it. For example in case we build from trunk I want suffix for the build output be empty but in case of branch I want it to be -branch name.
currently I am doing it by defining environment section.
environment {
OUTPUT_NAME_SUFFIX = ($(env.BRANCH_NAME) == 'trunk') ? '': $(env.BRANCH_NAME)
}
I am getting this error:
WorkflowScript: 4: Environment variable values must either be single quoted, double quoted, or function calls. # line 4, column 62.
(env.BRANCH_NAME) == 'trunk') ? '': $(en
^
What the best way to define variables and eval their values in scope of pipeline.
TIA
You can use string interpolation to evaluate the expression:
environment {
OUTPUT_NAME_SUFFIX = "${env.BRANCH_NAME == 'trunk' ? '': env.BRANCH_NAME}"
}
This will fix the error you're getting, however pipeline does not allow you to have environment variables that are of 0 length, aka empty string (JENKINS-43632).
That means that setting OUTPUT_NAME_SUFFIX to '' is like unseting it. You might want to precalculate the whole name of your output, so that your env variable is never an empty string.
I have solved it by adding following code. So far had no issues with empty strings.
stage('Set Environmnet'){
steps {
script {
if(BRANCH_NAME == 'trunk'){
env.OUTPUT_NAME_SUFFIX = ''
}else if (BRANCH_NAME.startsWith("branches")){
env.OUTPUT_NAME_SUFFIX = "-" + BRANCH_NAME.substring(BRANCH_NAME.lastIndexOf("/")+1)
}else{
env.OUTPUT_NAME_SUFFIX = ''
}
}
}
}
I need to accept all kinds of global Jenkins variables as strings (basically as parameters to ansible like system - a template stored in \vars).
def proof = "\"${params.REPOSITORY_NAME}\""
echo proof
def before = "\"\${params.REPOSITORY_NAME}\""
echo before
def after = Eval.me(before)
echo after
The result is:
[Pipeline] echo
"asfd"
[Pipeline] echo
"${params.REPOSITORY_NAME}"
groovy.lang.MissingPropertyException: No such property: params for class: Script1
the first echo proves that the param value actually exists.
the second echo is the what the input actually looks like.
the third echo should have emitted asdf instead I get the exception.
Any ideas? I'm hours into this :-(
You may want to check:
groovy: Have a field name, need to set value and don't want to use switch
1st Variant
In case you have: xyz="REPOSITORY_NAME" and want the value of the parameter REPOSITORY_NAME you can simply use:
def xyz = "REPOSITORY_NAME"
echo params."$xyz" // will print the value of params.REPOSITORY_NAME
In case if your variable xyz must hold the full string including params. you could use the following solution
#NonCPS
def split(string) {
string.split(/\./)
}
def xyz = "params.REPOSITORY_NAME"
def splitString = split(xyz)
echo this."${splitString[0]}"."${splitString[1]}" // will print the value of params.REPOSITORY_NAME
2nd Variant
In case you want to specify an environment variable name as parameter you can use:
env.“${params.REPOSITORY_NAME}”
In plain groovy env[params.REPOSITORY_NAME] would work but in pipeline this one would not work inside the sandbox.
That way you first retrieve the value of REPOSITORY_NAME and than use it as key to a environment variable.
Using directly env.REPOSITORY_NAME will not be the same as it would try to use REPOSITORY_NAME itself as the key.
E.g. say you have a job named MyJob with the following script:
assert(params.MyParameter == "JOB_NAME")
echo env."${params.MyParameter}"
assert(env."${params.MyParameter}" == 'MyJob')
This will print the name of the job (MyJob) to the console assuming you did set the MyParameter parameter to JOB_NAME. Both asserts will pass.
Please don’t forget to open a node{} block first in case you want to retrieve the environment of that very node.
After trying all those solutions, found out that this works for my problem (which sounds VERY similar to the question asked - not exactly sure though):
${env[REPOSITORY_NAME]}
I am new to Jenkins pipeline scripting. I am developing a Jenkins pipeline in which the Jenkins code is as follows. The logic looks like this:
node{
a=xyz
b=abc
//defined some global variables
stage('verify'){
verify("${a}","${b}")
abc("${a}","${b}")
echo "changed values of a and b are ${a} ${b}"
}}
def verify(String a, String b)
{ //SOme logic where the initial value of a and b gets changed at the end of this function}
def verify(String a, String b){
//I need to get the changed value from verify function and manipulate that value in this function}
I need to pass the initial a and b(multiple) values to the verify function and pass the changed value on to the other function. I then need to manipulate the changed value, and pass it to the stage in the pipeline where echo will display the changed values. How can I accomplish all this?
Ok, here's what I meant:
def String verify_a(String a) { /* stuff */ }
def String verify_b(String b) { /* stuff */ }
node {
String a = 'xyz'
String b = 'abc'
stage('verify') {
a = verify_a(a)
b = verify_b(b)
echo "changed values of a and b are $a $b"
}
stage('next stage') {
echo "a and b retain their changed values: $a $b"
}
}
The easiest way I have found to pass variables between stages is to just use Environment Variables. The one - admittedly major - restriction is that they can only be Strings. But I haven't found that to be a huge issue, especially with liberal use of the toBoolean() and toInteger() functions. If you need to be passing maps or more complex objects between stages, you might need to build something with external scripts or writing things to temporary files (make sure to stash what you need if there's a chance you'll switch agents). But env vars have served me well for almost all cases.
This article is, as its title implies, the definitive guide on environment variables in Jenkins. You'll see a comment there from me that it's really helped me grok the intricacies of Jenkins env vars.