Gradle set ext property in one task and use it in another - gradle

I have several tasks which executes different SQL scripts via psql.
task runScript1(type: Exec) {
commandLine 'cmd', '/c', "psql -f script1.sql"
}
task runScript2(type: Exec) {
commandLine 'cmd', '/c', "psql -f script2.sql"
}
Now I want to write one generic exec task and pass only the script name to it.
ext {
scriptName = ''
}
task runScriptGeneric(type: Exec) {
commandLine 'cmd', '/c', "psql -f ${scriptName}"
}
task runScript1() {
scriptName = 'script1.sql'
}
runScript1.finalizedBy runScriptGeneric
task runScript2() {
scriptName = 'script2.sql'
}
runScript2.finalizedBy runScriptGeneric
Unfortunately this approach is not working. The scriptName stays empty in the runScriptGeneric task.
I suspect this has to do with the Exec type because the following simple task working well.
ext {
scriptName = ''
}
task runScriptGeneric() {
doLast {
println "${scriptName}"
}
}
task runScript1() {
doLast {
scriptName = 'script1.sql'
}
}
runScript1.finalizedBy runScriptGeneric
task runScript2() {
doLast {
scriptName = 'script2.sql'
}
}
runScript2.finalizedBy runScriptGeneric
I do not want do pass it over as a command line parameter (-PscriptName), because I want to keep the individual tasks for each script. Is there any other way to pass the scriptName from each individual task to the generic task?

Actually, it's not an answer to my question, but it's a solution I can live with.
I've created a dynamic task instead of passing the variable to the executing script:
['Script1', 'Script2'].each {taskName ->
task "run${taskName}"(type: Exec) {
commandLine 'cmd', '/c', "psql -f ${taskName}"
}
}

Related

Gradle custom task extends Exec is throwing error

My intention is to run a docker save command by creating a custom task in Gradle:
Below is my build.gradle file:
class SaveTask extends Exec {
#TaskAction
void saveImage() {
commandLine "bash","-c","docker save someimage:latest | gzip > someimage.tar.gz"
}
}
// Create a task using the task type
task save(type: SaveTask)
When I run the task it is giving me the below error:
Execution failed for task ':save'.
> execCommand == null!
Can someone suggest me where I am going wrong?
You probably don't need to create a custom task type at all, just use the regular Exec task type for your task save:
task save(type: Exec) {
commandLine "bash", "-c", "docker save someimage:latest | gzip > someimage.tar.gz"
}
The problem why your approach fails is that the Exec task type defines a #TaskAction internally. This #TaskAction runs the command defined by commandLine. In your SaveTask task type, another #TaskAction is defined, but it will run after the original #TaskAction. This is the reason why the commandLine is still null / empty for the original #TaskAction.
If you still want to create a custom task type, e.g. because you want to define a configuration interface that will be used by multiple tasks, use a doFirst closure to define the commandLine, as it will be executed before any task action:
class SaveTask extends Exec {
String image
SaveTask() {
doFirst {
commandLine "bash", "-c", "docker save ${image} | gzip > someimage.tar.gz"
}
}
}
task saveImageA(type: SaveTask) {
image = 'imageA:latest'
}
task saveImageB(type: SaveTask) {
image = 'imageB:latest'
}
I modified the above code as below and it's working for me
class SaveTask extends Exec {
SaveTask() {
commandLine "bash", "-c", "someimage:latest | gzip > someimage.tar.gz"
}
}
task saveImageA(type: SaveTask)

A Gradle task (type: Exec) is not executed during the configuration phase

I am reading about Gradle build lifecycle
Here is my script:
task startTomcat(type:Exec) {
commandLine 'cmd', '/c', 'echo init startTomcat'
}
task stopTomcat(type:Exec) {
// on windows:
commandLine 'cmd', '/c', 'echo init stopTomcat!'
doLast {
commandLine 'cmd', '/c', 'echo doLast stopTomcat!'
}
}
task configured(type:Exec) {
println 'configured. method body'
}
task test2 {
doLast {
println 'test2 doLast'
}
}
task testBoth2 {
doFirst {
println 'testBoth2 doFirst'
}
doLast {
println 'testBoth2 doLast'
}
println 'testBoth2. method body'
}
I run task2:
gradlew test2
This is the output:
Parallel execution with configuration on demand is an incubating feature.
configured. method body
testBoth2. method body
:test2
test2 doLast
BUILD SUCCESSFUL
It looks like the calls to commandLine were ignored. Why?
The Exec task's commandLine properly only configures what to do if the task is executed. As such you don't see the actual command doing anything during the configuration phase.

Gradle, task type: Exec - commandLine not work in onLast

I want execute some command from command line in gradle task(e.g. print all files in dir):
task dir(type: Exec) {
def adbCommand = ["dir", "*.*"]
commandLine adbCommand
standardOutput = new ByteArrayOutputStream()
doLast {
println ("result = " + standardOutput)
}
}
It's work. OK. But when I put it on onLast section it's not work:
task dir(type: Exec) {
doLast {
def adbCommand = ["dir", "*.*"]
commandLine adbCommand
standardOutput = new ByteArrayOutputStream()
println ("result = " + standardOutput)
}
}
I get error:
FAILURE: Build failed with an exception.
What went wrong:
Execution failed for task ':app:dir'.
execCommand == null!
The reason is in the fact, that task of Exec should be configured during configuration phase of the build, otherwise your task will be not configured and fail.
In you first example everything works due to configuration happens at the configuratyion phase. Your second example tries to configure the task within doLast closure - right after the task is executed yet.
If you really need to execute something in doLast, you can use something like this, without creating special task:
task someTaskName {
doLast {
exec {
commandLine adbCommand
}
}
}
Here is exec-specification used to execute some command and it's configured and executed at the same time.

Gradle, commandLine 'cmd', '/c', 'echo doLast!' does nothing

I'm reading about Gradle Exec and created the following build.gradle:
task startTomcat(type:Exec) {
commandLine 'cmd', '/c', 'echo init startTomcat'
}
task stopTomcat(type:Exec) {
// on windows:
commandLine 'cmd', '/c', 'echo init stopTomcat!'
doLast {
commandLine 'cmd', '/c', 'echo doLast stopTomcat!'
}
}
When I run gradlew stopTomcat, the output looks like this:
Parallel execution with configuration on demand is an incubating feature.
:stopTomcat
init stopTomcat!
I don't see the line doLast stopTomcat! Why can't I execute a command in doLast?
Your task is of type Exec. The commandLine method call configures the task by passing the cmd, /c and echo init stopTomcat! to it. This happens in the config phase.
Then the task runs in execution phase and prints:
init stopTomcat!
Then the doLast blocks starts and configures the task, passing cmd, /c and echo doLast stopTomcat! to it. This configuration has no effect as the taks already ran.
To get the second print out, you could do:
task stopTomcat(type:Exec) {
// on windows:
commandLine 'cmd', '/c', 'echo init stopTomcat!'
doLast {
exec {
commandLine 'cmd', '/c', 'echo doLast stopTomcat!'
}
}
}
This is another way how to invoke the exec task.

Run shell command in gradle but NOT inside a task

What I currently have is:
task myTask (type : Exec) {
executable "something.sh"
... (a lot of other things)
args "-t"
args ext.target
}
task doIt {
myTask.ext.target = "/tmp/foo"
myTask.execute();
myTask.ext.target = "/tmp/gee"
myTask.execute();
}
With this I thought I could run "myTask" with different parameters when I start "doIt". But only the first time the script is executed because gradle takes care that a task only runs once.
How can I rewrite the "myTask" so that I can call it more than once? It is not necessary to have it as a separate task.
You can do something like the following:
def doMyThing(String target) {
exec {
executable "something.sh"
args "-t", target
}
}
task doIt {
doLast {
doMyThing("/tmp/foo")
doMyThing("/tmp/gee")
}
}
The exec here is not a task, it's the Project.exec() method.

Resources