Calling writeFile for every entry of a map requires somewhat ugly code

classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Calling writeFile for every entry of a map requires somewhat ugly code

David Karr
I'm posting this mostly so people can find it.  Perhaps it's already well-known, and perhaps I'm missing some simple thing that makes this easier to do, but I think not.

In my Jenkinsfile, I need to iterate over a map created with Groovy, calling "writeFile" with the key as the file name, and the value as the contents.  If you haven't had to do this, you might assume this is simple. If you have, you either discovered what I did, or you gave up.

What I tried to write first was this:
dataMap.each {
    writeFile
(file: "target/generated." + key, text: value)
}

This gets serialization errors.  I then discovered that calling pipeline steps within closures would not work, so I changed it to a plainer iteration:

for(Map.Entry entry : dataMap) {
    writeFile
(file: "target/generated." + entry.getKey(), text: entry.getValue())
}

This also does not work. It appears that you simply can't call a pipeline step with a map anywhere in scope.

What DOES work is something like the following:
def keyValueList = []
for (Map.Entry entry : dataMap) {
    keyValueList
.add(entry.getKey())
    keyValueList
.add(entry.getValue())
}
dataMap
= null
for (int ctr = 0; ctr < keyValueList.size(); ctr += 2) {
    writeFile
(file: "target/generated." + keyValueList.get(ctr), text: keyValueList.get(ctr + 1))
}
keyValueList
= null

Suggestions would be useful, or perhaps other people will just do the same thing I've done.

--
You received this message because you are subscribed to the Google Groups "Jenkins Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/jenkinsci-users/2a0ee3c2-00db-4fa0-8ae0-d3149ae664ado%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: Calling writeFile for every entry of a map requires somewhat ugly code

Gianluca
I use a different approach ... but it may not fits your use case.
In any case, usually when I have to perform operation on each element of a Map, I end up on transform the Map on steps that I can feed to parallel

steps {
  stepsMap
= [:]

  stepsMap
= dataMap.collectEntries{[
   
"Name of step to perfom (that will appear on BlueOcean": {
       
// pipeline code, I usually use script block here to be able to do stuff not available in declarative
   
}
 
]}

  parallel stepsMap

}


By default collectEntries put the value into a variable called $it ... but the there is a syntax that allow to use key and value variables and use them inside.




On Saturday, 18 July 2020 19:28:32 UTC+1, David Karr wrote:
I'm posting this mostly so people can find it.  Perhaps it's already well-known, and perhaps I'm missing some simple thing that makes this easier to do, but I think not.

In my Jenkinsfile, I need to iterate over a map created with Groovy, calling "writeFile" with the key as the file name, and the value as the contents.  If you haven't had to do this, you might assume this is simple. If you have, you either discovered what I did, or you gave up.

What I tried to write first was this:
dataMap.each {
    writeFile
(file: "target/generated." + key, text: value)
}

This gets serialization errors.  I then discovered that calling pipeline steps within closures would not work, so I changed it to a plainer iteration:

for(Map.Entry entry : dataMap) {
    writeFile
(file: "target/generated." + entry.getKey(), text: entry.getValue())
}

This also does not work. It appears that you simply can't call a pipeline step with a map anywhere in scope.

What DOES work is something like the following:
def keyValueList = []
for (Map.Entry entry : dataMap) {
    keyValueList
.add(entry.getKey())
    keyValueList
.add(entry.getValue())
}
dataMap
= null
for (int ctr = 0; ctr < keyValueList.size(); ctr += 2) {
    writeFile
(file: "target/generated." + keyValueList.get(ctr), text: keyValueList.get(ctr + 1))
}
keyValueList
= null

Suggestions would be useful, or perhaps other people will just do the same thing I've done.

--
You received this message because you are subscribed to the Google Groups "Jenkins Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/jenkinsci-users/569ba94d-b5e6-4956-ac7d-cd2e3bf4b692o%40googlegroups.com.
Reply | Threaded
Open this post in threaded view
|

Re: Calling writeFile for every entry of a map requires somewhat ugly code

Baptiste MATHUS
Extract this in a shell script or so.
Use Jenkins pipeline for orchestration, not for programming.

It sounds tempting to use pipeline like it's Groovy. But first it's not *really* Groovy as you've discovered and second it'll make it very hard to develop locally if the build process steps are only runnable within Jenkins.

Cheers
-- Baptiste

Le sam. 18 juil. 2020 à 21:07, Gianluca <[hidden email]> a écrit :
I use a different approach ... but it may not fits your use case.
In any case, usually when I have to perform operation on each element of a Map, I end up on transform the Map on steps that I can feed to parallel

steps {
  stepsMap
= [:]

  stepsMap
= dataMap.collectEntries{[
   
"Name of step to perfom (that will appear on BlueOcean": {
       
// pipeline code, I usually use script block here to be able to do stuff not available in declarative
   
}
 
]}

  parallel stepsMap

}


By default collectEntries put the value into a variable called $it ... but the there is a syntax that allow to use key and value variables and use them inside.




On Saturday, 18 July 2020 19:28:32 UTC+1, David Karr wrote:
I'm posting this mostly so people can find it.  Perhaps it's already well-known, and perhaps I'm missing some simple thing that makes this easier to do, but I think not.

In my Jenkinsfile, I need to iterate over a map created with Groovy, calling "writeFile" with the key as the file name, and the value as the contents.  If you haven't had to do this, you might assume this is simple. If you have, you either discovered what I did, or you gave up.

What I tried to write first was this:
dataMap.each {
    writeFile
(file: "target/generated." + key, text: value)
}

This gets serialization errors.  I then discovered that calling pipeline steps within closures would not work, so I changed it to a plainer iteration:

for(Map.Entry entry : dataMap) {
    writeFile
(file: "target/generated." + entry.getKey(), text: entry.getValue())
}

This also does not work. It appears that you simply can't call a pipeline step with a map anywhere in scope.

What DOES work is something like the following:
def keyValueList = []
for (Map.Entry entry : dataMap) {
    keyValueList
.add(entry.getKey())
    keyValueList
.add(entry.getValue())
}
dataMap
= null
for (int ctr = 0; ctr < keyValueList.size(); ctr += 2) {
    writeFile
(file: "target/generated." + keyValueList.get(ctr), text: keyValueList.get(ctr + 1))
}
keyValueList
= null

Suggestions would be useful, or perhaps other people will just do the same thing I've done.

--
You received this message because you are subscribed to the Google Groups "Jenkins Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/jenkinsci-users/569ba94d-b5e6-4956-ac7d-cd2e3bf4b692o%40googlegroups.com.

--
You received this message because you are subscribed to the Google Groups "Jenkins Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to [hidden email].
To view this discussion on the web visit https://groups.google.com/d/msgid/jenkinsci-users/CANWgJS7GD4ixsERgnEzdVbeM61dihexe06SzPCZMh96Fdg_m-Q%40mail.gmail.com.