Accessing variable outside of a closure in Groovy - groovy

Is there a way, i can access a variable outside the closure. The closure here is a stage in the Jenkinsfile. So, the snippet looks like this:
node('pool'){
try{
stage('init'){
def list = []
//some code to create the list
}
stage('deploy'){
//use the list create in the above stage/closure
}
}
catch(err){
//some mail step
}
}
With this code, i cannot access the list which was created in the first stage/closure.
How can i set to get this newly created list accessible to the next stage/closure?

#tim_yates.. with your suggestion. This works. It was easy at the end :)
node('pool') {
try {
def list = [] //define the list outside of the closure
stage('init') {
//some code to create/push elements in the list
}
stage('deploy') {
//use the list create in the above stage/closure
}
} catch (err) {
//some mail step
}
}

I know it's late, but worths mentioning that when you define a type or def (for dynamic resolution) you're creating a local scope variable that will be available only inside the closure.
If you omit the declaration the variable will be available to the whole script:
node('pool'){
try {
stage('Define') {
list = 2
println "The value of list is $list"
}
stage('Print') {
list += 1
echo "The value of list is $list"
}
1/0 // making an exception to check the value of list
}
catch(err){
echo "Final value of list is $list"
}
}
Returns :
The value of list is 2
The value of list is 3
Final value of list is 3

Related

How to make some changes when calling shouldUpdate?

I want to do the following:
When the property "mobile" is changed, check to see if X is true, if so, set set a variable Y and call requestUpdate to re-render the element. The element will render something different based on variable X.
so shouldUpdate function could be:
shouldUpdate(changedProperties) {
if (changedProperties.has("mobile")) {
this._showDialog = true;
this.requestUpdate();
await this.updateComplete;
}
return this.openingDialog;
}
What's the best way to do this without using the shouldUpdate function?
You can use willUpdate to compute Y variable. willUpdate used to compute values needed during the update.
willUpdate(changedProperties) {
if (changedProperties.has("mobile")) {
this._showDialog = true;
}
}

Groovy closure without preceding equal sign prop = {} vs prop {}

I'm trying to create a config file for my java app that can have lazy evaluation, for instance, contain an e-mail template with current date time. I use ConfigSlurper to parse the config file.
For some reason I can't find at https://groovy-lang.org/closures.html the description of the commonly used form (see build.gradle): prop1 { ... } prop2 { ... }. Am I looking at the wrong place?
My tests show that such closures are evaluated immediately and the example above can be rewritten as: prop1 = { ... }() prop2 = { ... }() (notice the parentheses, without them the evaluation is lazy).
I also don't understand why using dots in property without the equal sign cause MissingMethodException: No signature of method: groovy.util.ConfigObject.URL() if I use: server.URL { System.out.println('ccc'); 'asd' } in the example below.
It's disappointing that the choice is completely transparent for Groovy, but you have to check that a value is instance of Closure or GString when using java.
I used this article as the starting point https://blog.mrhaki.com/2009/08/grassroots-groovy-configuration-with.html
// We can group settings.
// The following settings are created:
// app.version, app.setting1, app.setting2, app.setting3, app.date, app.active
app {
System.out.println('aaa')
version = "1.0"
// We can write code to set up settings.
[1, 2, 3].each {
this."setting${it}" = it * 10
}
// We can use Java objects
date = new Date()
active = true
}
server.URL = "http://default"
// Environment specific settings override settings with the
// same name.
environments {
development {
server = { System.out.println('ccc'); 'asd' }
// server.URL = "${-> System.out.println('bbb');new Date()}http://localhost"
}
test {
server.URL = 'http://test:9080'
}
integrationtest {
server.URL = 'http://integrationtest/url'
}
production {
server.URL = 'http://prod/url'
}
}
My tests show that such closures are evaluated immediately and the
example above can be rewritten as: prop1 = { ... }()
Closures are not evaluated immediately. The parens above are causing the closure to be evaluated.
For some reason I can't find at https://groovy-lang.org/closures.html
the description of the commonly used form (see build.gradle): prop1 {
... } prop2 { ... }.
prop1 {} is invoking a method named prop1 and passing a closure as a parameter That code is equivalent to this:
def myClosure = {}
prop1(myClosure)
I also don't understand why using dots in property without the equal
sign cause MissingMethodException: No signature of method:
groovy.util.ConfigObject.URL()
Something like server.URL = 'http://test:9080' is assigning a value (http://test:9080) to a property (server.URL). If you remove the equal sign you are changing the expression fundamentally and then would be invoking a method named URL on an object named server and passing http://test:9080 as a parameter.

Groovy closure return of value to variable

Very basic question but I cannot find an answer:
I have the below code in a file g.groovy, and it functions in printing output:
#! /usr/env/groovy
def matchFiles = { match ->
new File(".").eachFile() {
if (it.name =~ match) {
println it
}
}
}
matchFiles('.groovy') prints ./g.groovy to screen.
But I want to capture the output of the closure in a variable and use it elsewhere, e.g.
def fileMatches = matchFiles('.groovy')
but cannot figure this out.
Tried changing println it to return it and then running
def fileMatches = matchFiles('.groovy')
fileMatches.println { it }
but this prints something like g$_run_closure2#4b168fa9
Any help is much appreciated, sorry for any incorrect nomenclature, very new to Groovy
according to the name matchFiles I assume you want to return all matched files
so, you have to define an array result variable where you are going to store each matched file
and then return this result variable after eachFile{...} closure
def matchFiles = { match ->
def result=[]
new File(".").eachFile {
if (it.name =~ match) {
result.add(it)
}
}
return result
}
println matchFiles(/.*/)

How I could create a table model with closure put multiple variable form loop

I see this code for how create a table with closure
https://varomorf.wordpress.com/2014/09/22/update-jtable-using-groovy/
but now I need create a table with closure
but using a text title for create all closure variable
like this; this code get the table but using the last value of xbn in this case 4
theTable = table(){
tableModel(){
var1="fecha"
xbn=0
stx="date;product;quant;weight;price".split(";")
println it
while(xbn<4) {
closureColumn(header:stx[xbn], read:{it[stx[xbn]]}) ;xbn=xbn+1 }
}
}
normally my code without loop
look like this
theTable = table(){
tableModel(){
var1="fecha"
xbn=0
stx="date;product;quant;weight;price".split(";")
println it
closureColumn(header:"date", read:{it["date"]})
closureColumn(header:"product", read:{it["product"]})
closureColumn(header:"quant", read:{it["quant"]})
closureColumn(header:"weight", read:{it["weight"]})
closureColumn(header:"price", read:{it["price"]})
}
}
please help me
Most DSLs don't prevent you from using the regular groovy stuff. So you can iterate multipl times, but you have to name your closure loop vars (e.g. your outer loop is the tableModel and it's implicitly named it).
...
tableModel() { // it ->
...
"date;product;quant;weight;price".split(";").each { hdr -> // name the loop var
closureColumn(header:hdr, read:{it[hdr]})
}
...
}
...

How can I retrieve the build parameters from a queued job?

I would like to write a system groovy script which inspects the queued jobs in Jenkins, and extracts the build parameters (and build cause as a bonus) supplied as the job was scheduled. Ideas?
Specifically:
def q = Jenkins.instance.queue
q.items.each { println it.task.name }
retrieves the queued items. I can't for the life of me figure out where the build parameters live.
The closest I am getting is this:
def q = Jenkins.instance.queue
q.items.each {
println("${it.task.name}:")
it.task.properties.each { key, val ->
println(" ${key}=${val}")
}
}
This gets me this:
4.1.next-build-launcher:
com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty$ScannerJobPropertyDescriptor#b299407=com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty#5e04bfd7
com.chikli.hudson.plugin.naginator.NaginatorOptOutProperty$DescriptorImpl#40d04eaa=com.chikli.hudson.plugin.naginator.NaginatorOptOutProperty#16b308db
hudson.model.ParametersDefinitionProperty$DescriptorImpl#b744c43=hudson.mod el.ParametersDefinitionProperty#440a6d81
...
The params property of the queue element itself contains a string with the parameters in a property file format -- key=value with multiple parameters separated by newlines.
def q = Jenkins.instance.queue
q.items.each {
println("${it.task.name}:")
println("Parameters: ${it.params}")
}
yields:
dbacher params:
Parameters:
MyParameter=Hello world
BoolParameter=true
I'm no Groovy expert, but when exploring the Jenkins scripting interface, I've found the following functions to be very helpful:
def showProps(inst, prefix="Properties:") {
println prefix
for (prop in inst.properties) {
def pc = ""
if (prop.value != null) {
pc = prop.value.class
}
println(" $prop.key : $prop.value ($pc)")
}
}
def showMethods(inst, prefix="Methods:") {
println prefix
inst.metaClass.methods.name.unique().each {
println " $it"
}
}
The showProps function reveals that the queue element has another property named causes that you'll need to do some more decoding on:
causes : [hudson.model.Cause$UserIdCause#56af8f1c] (class java.util.Collections$UnmodifiableRandomAccessList)

Resources