What are gradle task definitions in groovy language? - groovy

I'm completely new to both gradle and groovy and I'm having trouble to find information about what the below actually is in the groovy language
task myTask(dependsOn: 'compile') << {
println 'I am not affected'
}
AFAIK the {...} part is a closure which seems to be passed to whatever is defined before <<.
Is task myTask() a call to a constructor?
And what is the thing with the colon that looks like a parameter?
What does << do? Is it an operator that was overloaded by gradle or is it standard groovy?

dependsOn: 'compile' is a named argument. << is an overloaded operator that adds a task action to the task. (See Gradle User Guide for more information.) { ... } is a closure that implements the task action. myTask is syntactically a nested method call (task(myTask(dependsOn: 'compile') << ...)), but gets rewritten to a String using a Groovy compiler plugin (task('myTask', dependsOn: 'compile') << ...).

Related

Is a Jenkinsfile in pure Groovy? What Groovy language construct is used in `steps` in a Jenkinsfile?

What Groovy language construct, syntax or control structure is used in the following code fragment in a Jenkinsfile?
stage('Stage 1') {
steps {
// One or more steps
}
}
i.e. What are blocks in Jenkinsfile, in terms of pure Groovy language?
what is 'steps'? or stage?
Is it calling a function? or definition? or a function call with anonymous (lambda) argument?
Inherent in this question is another question:
Question 2:
Is a Jenkinsfile, a code fragment in groovy language?
In other words, 1. Does a Jenkinsfile follow all syntax and control structures of pure Groovy? (perhaps by an implicit library import-ed or #include d silently in beginning),
As opposed to being a DSL: 2. Jenkinsfile being almost a groovy source file augmented with new Jenkins-specific constructs not originally in Groovy, e.g. Jenkins using a preprocessing.
Which of the above two hold?
Related:
https://www.jenkins.io/doc/book/pipeline/syntax/
https://www.jenkins.io/doc/book/pipeline/getting-started/#directive-generator
What is a Jenkins Stage in terms of Groovy? (despite similar title, the ask is different. The related comments are inconclusive).
In Jenkins (or Gradle) 2 main features are used:
Groovy (java) idiomatic structures like loops, switches, chain of command etc
DSLBuilder facility based on Closures to allow for nesting and invoking of domain-specific methods as they were a part of Groovy itself.
So, if you write something like
stage('Stage 1') {
steps {
// One or more steps
}
}
it translates internaly to roughly:
jenkinsContext.stage('Stage 1') {
jenkinsContext.steps {
// One or more steps
}
}
so it is way clearer to write and read. Here the Closures - the {...} blocks - represent nesting or grouping of your code.
In this block you can also see Groovy's way of calling methods where the last argument is a Closure. The code above could be rewritten as:
jenkinsContext.stage 'Stage 1', { // here no brackets around args
jenkinsContext.steps( { // here with normal java-style brackets
// One or more steps
} )
}
In jenkins you can mix and match DSL calls with Groovy structures:
[ 'Stage 1', 'Stage 2' ].each{
stage( it ) {}
}
or even have your DSL names generated dynamically:
[ 'Stage 1':'stage', 'step 2':'steps' ].each{ value, name ->
"$name"( value ) {}
}
would create the DSL (as example ONLY!):
stage( 'Stage 1') {}
steps( 'Step 2' ) {}
So, Jenkins pipeline syntax is Groovy + Jenkins DSL
Looks like it's primarily Groovy, so if you're looking for simply syntax highligting adding something like the following does the job.
<!-- language: lang-groovy -->
There are caveats however documented in the online docs, so maybe this implies it's not written in pure groovy but some specialized/constrained form of it?
The basic statements and expressions which are valid in Declarative Pipeline follow the same rules as Groovy’s syntax with the following exceptions:
The top-level of the Pipeline must be a block, specifically: pipeline { }.
No semicolons as statement separators. Each statement has to be on its own line.
Blocks must only consist of Sections, Directives, Steps, or assignment statements.
A property reference statement is treated as a no-argument method invocation. So, for example, input is treated as input().
https://www.jenkins.io/doc/book/pipeline/syntax/#declarative-pipeline

Request clarification of Gradle task rule syntax from documentation

Pursuant to this spot in the Gradle documentation:
https://docs.gradle.org/current/userguide/more_about_tasks.html#N10F07
tasks.addRule("Pattern: ping<ID>") { String taskName ->
if (taskName.startsWith("ping")) {
task(taskName) << {
println "Pinging: " + (taskName - 'ping')
}
}
}
It says, "Sometimes you want to have a task whose behavior depends on a large or infinite number value range of parameters. A very nice and expressive way to provide such tasks are task rules.".
It's not at all clear to me from this block of code how those parameters are defined nor how they get into the task scope so that they can be used.
It's also not clear if they have to be all the same type. I really need an example that shows these.
I'm not a Groovy guy in the first place. Gradle is my reason for learning Groovy.

Which method in project is getting invoked when I define a task?

I have defined a task in a gradle file as shown below:
task groupTherapy (dependsOn: yayGradle2) << {
println 'This is not fun!'
}
I believe that below are the methods that get called when a task is defined:
Task task(Map<String,?> args, String name)
Task task(Map<String,?> args, String name, Closure configureClosure)
Task task(String name)
Task task(String name, Closure configureClosure)
Can you please explain me in my case which of these methods will get invoked? And help me understand why?
Here you can find an answer that might be interesting. dependsOn: yayGradle2 will be passed as an instance of Map. The name of the task will be extracted internally by gradle and passed as a name.

What's the operator << (double less than) in gradle?

The following piece of code defines 4 gradle tasks:
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
But what is the << operator? What does it do in groovy?
The << is a left-shift operator. In this scenario, task "task$counter" is a Task object declaration, and << is overloaded as an alias to the doLast method, which appends the closure to the list of actions to perform when executing the task.
If you don't specify the <<, the closure is treated as a configuration closure and will be executed by default during the configuration phase of your project's build lifecycle, regardless of whatever task argument is given on the command line.
Example:
If you take the configuration specified in the question:
4.times { counter ->
task "task$counter" << {
println "I'm task number $counter"
}
}
And run gradle task3, the output will be:
:task3
I'm task number 3
Because each closure was defined to be an execution action specific to the task. Since task3 was named as the task to execute, that was the only action closure executed.
But if you remove the << and make the configuration as follows:
4.times { counter ->
task "task$counter" {
println "I'm task number $counter"
}
}
And run gradle task3, the output will then be:
I'm task number 0
I'm task number 1
I'm task number 2
I'm task number 3
:task3 UP-TO-DATE
This is because all closures were defined to configure the tasks themselves, not be executed as actions when running the tasks. So in this case, Gradle executed all of the closures while configuring the project, then when it came time to execute task3, there were no actions to perform, so it reported the task as UP-TO-DATE.
Basically this is a leftShift operator - You can find more details here.
In gradle << operator is used to add action to a particular task. A task consists of multiple actions that are run (in order they were added) during the execution of the task. << just adds an action to tasks collection of actions. More about tasks and actions can be found here.

Populate List<Callable<String>> in Groovy with Groovy objects

In What JVM-based scripting language support #WebService to create services at runtime? I was suggested to use Groovy to provide web services configured in a script read in at runtime.
To make this work with our existing infrastructure I need essentially to be able to add new entries to a List<Callable<String>> which I then can ask an executor to invokeAny upon.
The basic structure will be something like:
Groovy is embedded using GroovyScriptEngine
Initial list passed in from Java as "l" in the Binding passed in.
Groovy script defines and instantiates N objects, all implementing Callable<String> and add them to the list.
Back in Java the list is then further processed and then passed to the executor.
My initial feeble steps show that I will most likely need to use def c = { ... } as Callable<String> but then I get a ClassCastException. Reading up I see that it appears that this is a bit hard and involves closures.
What is the correct way to define and instantiate an object in Groovy which implements Callable<String>?
In Groovy 1.8 and later, groovy.lang.Closure implements Callable by default so you don't need any "as" magic., simply:
l << { "hello" }
l << { "world" }
For earlier versions of Groovy (1.6 and 1.7 certainly, not sure about "ancient" versions) you need to use as:
import java.util.concurrent.Callable
l << ({ "hello" } as Callable)

Resources