Gradle: run pre and post tasks also when tasks are chained? - gradle

Assume the build.gradle at the end of this post.
If I run task WorkA or WorkB I get:
> Task :preTask
PreTask
> Task :WorkB (or A)
WorkB (or A)
> Task :finishTask
FinishTask
However If run the task allWork, the pre and finish task is only executed once! How to fix this?
> Task :preTask
PreTask
> Task :WorkA
WorkA
> Task :WorkB
WorkB
> Task :finishTask
FinishTask
> Task :AllWork
Combined
build.gradle
task preTask {
doFirst {
println "PreTask"
}
}
task finishTask {
doFirst {
println "FinishTask"
}
}
task WorkA {
dependsOn preTask
mustRunAfter preTask
finalizedBy finishTask
doFirst {
println "WorkA"
}
}
task WorkB {
dependsOn preTask
mustRunAfter preTask
finalizedBy finishTask
doFirst {
println "WorkB"
}
}
task AllWork {
dependsOn WorkA
dependsOn WorkB
WorkB.mustRunAfter WorkA
doFirst {
println "Combined"
}
}

Related

How to force task execution order in gradle 6.7.1

I am making a gradle script that must execute tasks in a specific order.
Despite looking that this forum post and this documentation, I do not understand how I am supposed to force task execution order.
I have this very complicated script:
task copyProjectTemplate(type: Copy) {
doLast {
println("copoying")
}
// from project_template_path_internal
// into project_path
}
task createProject {
mustRunAfter copyProjectTemplate
doLast {
println("project has been created")
}
}
When executed with gradle -b create_project.gradle createProject, only the createProject task is executed.
Using the following alternative has the same behaviour:
task copyProjectTemplate(type: Copy) {
doLast {
println("copoying")
}
// from project_template_path_internal
// into project_path
}
task createProject {
doLast {
println("project has been created")
}
}
createProject.mustRunAfter copyProjectTemplate
The output in both cases is:
$ gradle -b create_project.gradle createProject
> Task :createProject
project has been created
BUILD SUCCESSFUL in 2s
1 actionable task: 1 executed
How can I force task execution order ?
Edit 1:
Using the documentation sample, I realise that the Copy type seems to "break" (or not work as I expect it) things.
For example:
task createProject {
doLast {
println 'createProject'
}
}
task copyTemplate() {
doLast {
println 'copyTemplate'
}
}
task taskZ {
doLast {
println 'taskZ'
}
}
createProject.dependsOn copyTemplate
copyTemplate.dependsOn taskZ
>gradle -b create_project.gradle createProject
Executes the task in order:
$ gradle -b create_project.gradle createProject
> Task :taskZ
taskZ
> Task :copyTemplate
copyTemplate
> Task :createProject
createProject
BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 executed
But:
task createProject {
doLast {
println 'createProject'
}
}
task copyTemplate(type: Copy) {
doLast {
println 'copyTemplate'
}
}
task taskZ {
doLast {
println 'taskZ'
}
}
createProject.dependsOn copyTemplate
copyTemplate.dependsOn taskZ
>gradle -b create_project.gradle createProject
Does not execute copyTemplate:
$ gradle -b create_project.gradle createProject
> Task :taskZ
taskZ
> Task :createProject
createProject
BUILD SUCCESSFUL in 1s
2 actionable tasks: 2 executed
Why is that ?
Edit 2:
With actual copy commands (from into), the task is executed "correctly":
task createProject {
doLast {
println 'createProject'
}
}
task copyTemplate(type: Copy) {
doFirst {
println "first copy ?"
}
doLast {
println 'last copy ?'
}
from "./README.md"
into "./yolo_project/"
}
task taskZ {
doLast {
println 'taskZ'
}
}
Output:
$ gradle -b create_project.gradle createProject
> Task :taskZ
taskZ
> Task :copyTemplate
first copy ?
last copy ?
> Task :createProject
createProject
BUILD SUCCESSFUL in 1s
3 actionable tasks: 3 executed
Could someone explain me why in "non copy typed" tasks, doLast and doFirst are considered as actions (or at least are actually printed) but not for the "copy typed" task, that seems to need the from and into instructios ?

Stop execution of finalizedBy task, or only execute follow-up task on a condition

I'm using the com.google.cloud.tools.appengine gradle plugin, which has a task appengineDeploy.
I have two tasks that configure the appengineDeploy task before executing it. My current solution looks something like that:
task deployTest() {
doFirst {
appengine.deploy {
version = 'test'
...
}
}
finalizedBy appengineDeploy
}
task deployProduction() {
doFirst {
appengine.deploy {
version = '7'
...
}
}
finalizedBy appengineDeploy
}
Now I wanted to add a security question before the deployProduction task is executed, like this:
println "Are you sure? (y/n)"
def response = System.in.newReader().readLine()
if (response != 'y') {
throw new GradleException('Task execution stopped')
}
The problem is, by defintion the finalizedBy task is executed even if my task throws an exception, and that is exactly the opposite of what I want.
I can't change it to appengineDeploy dependsOn deployTest and call appengineDeploy as I have two tasks with different configuration.
And I can't change the appengineDeploy task as it comes from a plugin.
Is there any other way I can either stop the execution of appengineDeploy, or use something other than finalizedBy to execute that task after my deploy task?
One option is to leverage onlyIf to decide whether to execute the task, for example by examining a project property.
Here's a litte demo, given that task appengineDeploy is a task contributed by a plugin (see comment for details):
plugins {
id 'base'
}
ext {
set('doDeploy', false)
}
appengineDeploy.configure {
onlyIf {
project.ext.doDeploy
}
}
task deployTest() {
doFirst {
println 'deployTest()'
project.ext.doDeploy = true
}
finalizedBy appengineDeploy
}
task deployProduction() {
doFirst {
println 'deployProduction()'
println "Are you sure? (y/n)"
def response = System.in.newReader().readLine()
if (response == 'y') {
project.ext.doDeploy = true
}
}
finalizedBy appengineDeploy
}
Another option is to disable the task, which goes like this:
task deployProduction() {
doFirst {
println 'deployProduction()'
println "Are you sure? (y/n)"
def response = System.in.newReader().readLine()
if (response != 'y') {
project.tasks.appengineDeploy.enabled = false
}
}
finalizedBy appengineDeploy
}
I modified the answer from thokuest a bit (thanks for the help!), to prevent executing any tasks inbetween.
I created it as extension method since I needed it more than once:
ext.securityQuestion = { project, task ->
println "Are you sure you want to execute ${project.name}:${task.name}? (y/n)"
def response = System.in.newReader().readLine()
if (response != 'y') {
project.tasks.each {
if (it != task)
it.enabled = false
}
throw new GradleException("Execution of ${project.name}:${task.name} aborted")
}
}
and my task now looks like this:
task deployProduction() { task ->
doFirst {
securityQuestion(this, task)
}
finalizedBy appengineDeploy
}

Why gradle runs all JavaExec tasks?

I defined two tasks in my build.gradle
task a(type: JavaExec) {
}
task b(type: JavaExec) {
}
When I execute task a, b also runs. Is this normal?
gradle a
I'm sharing my own experience for others.
I am a newbie on groovy/gradle.
What I tried to achieve was using a shared function for getting project properties.
def projectProperty = {
if (!project.hasProperty(it)) {
throw new Exception...
}
return project.getProperty(it);
}
task a(type: JavaExec) {
do some with projectProperty(a);
}
task b(type: JavaExec) {
do some with projectProperty(b);
}
And I changed like this.
task a(type: JavaExec) {
if (project.hasProperty('a')) {
do some with projectProperty('a');
}
}
task b(type: JavaExec) {
if (project.hasProperty('b')) {
do some with projectProperty('b');
}
}

Execute task.dependsOn only on a Condition in Gradle

I have two tasks Task-A and Task-B
This is my Task-A
task Task-A () {
doLast {
def fileName = _.property('fileName')
if (fileName !=null) {
println 'success'
}
}
}
My Task-B is dependent on Task-A and I should make it dependent only on the Condition that _.property('fileName') should exist and should not be null
So I wrote my Task-B this way
task Task-B () {
doFirst {
def fileName = _.property('fileName')
if (fileName !=null) {
dependsOn 'Task-A'
}
}
}
It throws an Error
Cannot call Task.dependsOn(Object...) on task ':Task-B' after task has started execution.
How to execute dependsOn on a condition ?
You must set dependsOn directives during the configuration phase
try :
task Task-B () {
def fileName = _.property('fileName')
if (fileName !=null) {
dependsOn 'Task-A'
}
}

gradle pass parameter to dependsOn task

I have 3 gradle tasks: A, B, C.
B dependsOn A.
C dependsOn A.
If have an if check in A that I want to be true when B runs, false when C runs.
How do I do that?
For clarity, the real tasks are:
war { // task A
webAppDirName = 'src/main/webapp'
if (flag) {
rootSpec.exclude("**/*.json")
rootSpec.exclude("**/*.xml")
}
}
ospackage { // task B
buildRpm {
dependsOn war
}
}
task localTomcat { // task C
dependsOn war
}
I tried setting war.flag, war.ext.flag before dependsOn, in a doFirst action, but nothing...
I found a solution using a dependsOn chain and mustRunAfter.
Code:
task war4pkg {
doLast {
war.rootSpec.exclude("**/*.json")
war.rootSpec.exclude("**/*.xml")
}
}
war {
webAppDirName = 'src/main/webapp'
}
ospackage {
buildRpm {
dependsOn war4pkg, war # order doesn't matter
war.mustRunAfter war4pkg # order set here
}
}
task localTomcat {
dependsOn war # nothing here.
}

Resources