Reputation: 2177
I'm working on a gradle task that depends on other gradle tasks, i.e an aggregate task. The aggregate task required the other tasks to run in a certain linear order too.
Note: The other tasks must be able to run in isolation. The dependencies between the tasks ONLY makes sense when running the aggregate task.
My first attempt was to use someTask.execute(), but then I realized that this was not the Gradle way, i.e it is not a supported feature and that the internal API might change.
task aggregate() {
doFirst {
// Need to set properties required by other tasks
project.ext.somePropRequiredByTask1 = propertyX + "-" propertyY
}
doLast {
task1.execute()
task2.execute()
task3.execute()
}
}
After reading up on creating aggregate tasks, this is my current solution:
task aggregate() {
// Only configure task if the task is exlicitly run
if (gradle.startParamter.taskNames.contains("aggregate") {
project.ext.somePropRequiredByTask1 = propertyX + "-" propertyY
chainTaskDependencies([task1, task2, task3])
}
}
// Create a strict dependsOn dependency order for the tasks in the task list
def chainTaskDependencies(List<Task> tasks) {
def taskNames = tasks.collect { it.name}
println "Run tasks in this order: " taskNames.join " -> "
def reversed = tasks.reverse()
for (int i = 0; i< reversed.size() -1 ; i ++) {
reversed[i].dependsOn(reversed[i+1])
}
}
Is this the correct way to create an aggregate task dependency where the order between tasks is linear? How can it be improved?
Upvotes: 3
Views: 3464
Reputation: 30320
As Gradle team member and Spock inventor Peter Neiderweiser puts it here:
You can't, because a task (instance) will be executed at most once per build. Instead, the way to go is to declare multiple task instances. You could do this by putting the task declaration in a loop, putting it in a method and calling it multiple times, or by writing a task class and instantiating it multiple times. Then you'll add one other task that depends on all bulk tasks. Assuming the execution order between bulk tasks is irrelevant, that's it.
He also suggests using task rules for this purpose.
The OP also posts the solution he or she devised, so you can look at that as well.
Upvotes: 0
Reputation: 76
How about just extracting shutdownVM, waitForVMShutdown and rollback to functions/closures that your tasks call ? Then you are free to compose them in any which way you choose.
I've found this to be the most flexible option in similar cases.
Upvotes: 1
Reputation: 2232
B.mustRunAfter(A)
means that if both A and B run then B must run after A. B can be run by itself no problems.
So:
task A
task B
task C
task aggregate(dependsOn(['A', 'B', 'C'])
C.mustRunAfter(B)
B.mustRunAfter(A)
Upvotes: 0