Loop variable is not passed to shell script in Jenkins - jenkins

I am trying to pass a loop variable to a shell script, but my shell script is getting an empty variable value
pipeline {
agent any
stages {
stage('Test') {
steps {
script {
elements = ['1', '2', '3', '4']
for (String val in elements){
echo val
check = sh (script: """bash ./check_access/check.sh ${val}""", returnStdout: true).trim()
echo "check: ${check}"
}
}
}
}
}
}
./check_access/check.sh
#!/bin/sh
echo "val: $val"
the result i get
18:13:30 1
18:13:31 + bash ./check_access/check.sh 1
18:13:31 check: val:
.
.
.
18:13:31 4
18:13:32 + bash ./check_access/check.sh 4
18:13:32 check: val:
desired result
bash ./check_access/check.sh 1
check: val: 1
.
.
.
bash ./check_access/check.sh 4
check: val: 4
Could you please help

Solution:
I pass val as the first parameter to my script. So I should use $1 inside the script, not $val

Related

How to convert a jenkins boolean param into all caps "TRUE" or "FALSE" string parameter?

I have the following defined in my multibranch declarative pipeline:
steps {
script {
BUILD_PROD_FLAG = sh(returnStdout: true, script: "[ ${BUILD_PROD} = true ] && echo TRUE || echo FALSE; ").trim()
BUILD_PROD_FLAG_SECOND = expression { if (params.BUILD_PROD) { return "TRUE" } else { return "FALSE" } }
}
sh "echo alternative way to get true/false set (want this to say FALSE): ${BUILD_FLAG_SECOND}"
}
The first variable BUILD_PROD_FLAG works fine.
I would like to eliminate the convoluted bash spawning employed there.
The second one does not work:
Multibranch_PR-1#tmp/durable-212f3652/script.sh: 1: /home/ubuntu/workspace/s_InsightCamera_Multibranch_PR-1#tmp/durable-212f3652/script.sh: Syntax error: "(" unexpected
This apparently is due to
Which I am not able to comprehend.
When the expression block is removed it fails to parse:
org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
WorkflowScript: 67: unexpected token: if # line 67, column 57.
BUILD_FLAG_SECOND = if (params
^
1 error
And when I tried something else that is different:
BUILD_FLAG_SECOND = expression { return params.BUILD_PROD ? "TRUE" : "FALSE" }
I get the same Syntax error: "(" unexpected error. I don't understand why this is a .sh shell script, by the way.
Update: OK I think I get why it's a .sh, that's just the sh clause near the bottom that I have.
I also thought I solved it because I did neglect to quote things for the shell, but with the adjustment:
sh "echo 'alternative way to get true/false set (want this to say FALSE):' ${BUILD_FLAG_SECOND}"
Still the same error:
I think it is for real trying to interpolate the string #expression(<anonymous>=org.jenkinsci.plugins.workflow.cps.CpsClosure2#4a286654) in place of the BUILD_FLAG_SECOND variable...
Are you ready for the epic facepalm that is the solution?
BUILD_FLAG_SECOND = params.BUILD_PROD ? "TRUE" : "FALSE"
That's it.

How to read contents from properties file from Jenkins pipeline

I have a Jenkins pipeline script and it has to read the contents from a properties one by one which is having as a key-value pair. I need to split key and value separately. Below are the properties and groovy file which I am using.
To be read file (mypropsfile.properties) :
product1=workspacename1:path1/path2/path3
product2=workspacename2:path1/path2/path3
product3=workspacename3:path1/path2/path3
My groovy file:
stage('readfromfile') {
steps {
script{
def readpropscontent = readProperties file: 'mypropsfile.properties'
echo 'readpropscontent ::: '+readpropscontent
for (String item : readpropscontent) {
echo "item ::: "+item
def readpropscontentfile2 = item.split("=")[0];
echo 'readpropscontentfile2 ::: '+readpropscontentfile2
}
}
}
}
Updated groovy file to split the value:
def readpropscontent = readFile file: 'mypropsfile.properties'
echo 'readpropscontent ::: '+readpropscontent
for (String item : readpropscontent.split('\n')) {
echo "item ::: "+item
def PropsFileValue = item.split("=")[1];
echo 'PropsFileValue ::: '+PropsFileValue
for (String splittingparams : PropsFileValue) {
def path1= splittingparams.split(":")[0];
echo 'path1::: '+path1
//def path2= splittingparams.split(":")[1];
//def path3= splittingparams.split("/")[1];
}
when I try to run it in Jenkins pipeline, I face the below issue:
hudson.remoting.ProxyException: groovy.lang.MissingMethodException: No signature of method: java.util.AbstractMap$SimpleImmutableEntry.split() is applicable for argument types: (java.lang.String) values: [=]
Possible solutions: split(groovy.lang.Closure), wait(), wait(long), sprintf(java.lang.String, [Ljava.lang.Object;), getAt(java.lang.String), print(java.io.PrintWriter)
I don't want to hardcode the key to fetch its value, by reading the file line by line I need to get the key and value. Can someone provide the inputs to resolve this? Thank you !
The readProperties method returns a Map of properties. So you don't have to iterate to read them, simply use the key(name of the property) to extract the value for a specific property.
stage('readfromfile') {
steps {
script{
def readpropscontent = readProperties file: 'mypropsfile.properties'
echo 'readpropscontent ::: '+readpropscontent
echo "PROP1 :::: ${readpropscontent['product1']}"
echo "PROP2 :::: ${readpropscontent['product2']}"
echo "PROP3 :::: ${readpropscontent['product3']}"
}
}
}
Update 1
Printing all keys and values from properties.
stage('readfromfile') {
steps {
script{
def readpropscontent = readProperties file: 'mypropsfile.properties'
echo 'readpropscontent ::: '+readpropscontent
readpropscontent.each{ k,v ->
echo "KEY = $k :::: VAL = $v "
}
}
}
}
Update 2
Using readFile instead of readProperties
steps {
script{
def readpropscontent = readFile file: 'mypropsfile.properties'
echo 'readpropscontent ::: '+readpropscontent
for (String item : readpropscontent.split('\n')) {
echo "item ::: "+item
def readpropscontentfile2 = item.split("=")[0];
echo 'readpropscontentfile2 ::: '+readpropscontentfile2
}
}
}

Jenkinsfile/Groovy: why is result of dictionary AND integer an integer?

In Groovy/Jenkinsfile declarative syntax, why is the result of the boolean AND operation on dictionary, dictionary, and integer objects an integer instead of boolean true/false?
pipeline {
agent any
stages {
stage( "1" ) {
steps {
script {
a = [:]
a.a = [:]
a.a["a"] = "1"
a.a["b"] = "2"
echo "${a}"
echo "${a.a}"
echo "${a.a.size()}"
def my_bool = (a && a.a && a.a.size())
echo "my_bool ${my_bool}"
}
}
}
stage( "2" ) {
when {
expression { true == (a && a.a && a.a.size()) } // Fails because result is integer "2", not boolean "true"
}
steps {
script {
echo "hello, world!"
}
}
}
}
}
My biases from other programming languages led me to think that a && a.a && a.a.size() should implicitly be converted to a boolean value. The echo reveals that the value is integer 2.
What is the Jenkins/Groovy idiomatic way to deal with this? I.e. if a stage is conditional on "dictionaries being non-null and having nonzero size", what is the idiomatically correct/preferred way to write that conditional?
Update:
Note: the echo "my_bool ${my_bool}" statement prints "my_bool 2". This is with Jenkins version 2.222.3.
expression { a?.a?.size() }
or even
expression { a?.a }

Ignore lines starting with # while reading a file in groovy

I'm writing a code in groovy to read a file line by line and perform an action (for ex: build a code for a specific configuration) based on the information available in the line.
The following groovy code runs fine for me, except that i want to ignore or skip the first line or rather any line which starts with # or comment (//).
__SAMPLE_GROOVY_CODE__
input_file = '/home/user/inputFile.txt'
// read all the lines into a list, each line is an element in the list
File FH1 = new File(input_file)
def lines = FH1.readLines()
for (line in lines)
{
env.c_num = sh(returnStdout: true, script: "echo '${line}' | cut -d ':' -f 1").trim();
env.p_num = sh(returnStdout: true, script: "echo '${line}' | cut -d ':' -f 2").trim();
env.p_len = p_num.length();
println("INFO: Length is ${p_len} \n");
if(env.p_len != '0')
{
println ("INFO: Build is required !! \n");
println ("INFO: c_num is: ${c_num} \n");
println ("INFO: p_num is: ${p_num} \n");
// Code for build will come here..!!
}
else
{
println("INFO: Build is NOT required !! \n");
}
}
__INPUT_FILE__
$> cat /home/user/inputFile.txt
# Details of inputFile.txt
1234-A0: aa ab ac ad ae al
5678-B0:
2345-B0: ba
3456-B0:
4567-B0: ca

passing items in two lists simultaneoulsy in each loop Jenkinsfile

I have a list foo = ['tea',''sugar','milk'] and col = ['black','white','pink'] what I am trying to do is nested loop
def foo = ['tea','sugar','milk']
def col = ['black','white','pink']
[foo, col].transpose().each { x, y ->
sh """aws deploy push --application-name "${x}" --source "${y}" """
}
Desired Result
--application-name "tea" --source "black"
--application-name "sugar" --source "white"
--application-name "milk" --source "pink"
the result I am getting
[Pipeline] script
[Pipeline] {
[Pipeline] echo
--application-name "[tea, black]" --source "null"
[Pipeline] echo
--application-name "[sugar, white]" --source "null"
[Pipeline] echo
--application-name "[milk, pink]" --source "null"
[Pipeline] }
[Pipeline] // script
[Pipeline] }
I want the list items in foo and col to be injected one by one to the above shell script
Is there a way where we can pass both list items at once to the above shell script
Ref Nested `each` loops in Groovy
Can we do something like (foo,col).each
or maybe using for loop for(x in foo && y in col)
Ref my Jenkinsfile
pipeline {
agent any
stages {
stage('hello'){
steps{
script{
def foo = ['tea','sugar','milk']
def col = ['black','white','pink']
[foo, col].transpose().each { x, y ->
sh """aws deploy push --application-name "${x}" --source "${y}" """
//echo """--application-name \"${x}\" --source \"${y}\" """
}
}
}
}
}
}
I believe transpose is the method you are after, to pair up the two lists, then you can iterate through the result:
[foo, col].transpose().each { x, y ->
...
}
UPDATE:
This is what I was aiming at. Note that some of the parameters are removed for brevity
def foo = ['tea','sugar','milk']
def col = ['black','white','pink']
[foo, col].transpose().each { x, y ->
println """--application-name "${x}" --source "${y}" """
}
results
--application-name "tea" --source "black"
--application-name "sugar" --source "white"
--application-name "milk" --source "pink"

Resources