Odinodin
Odinodin

Reputation: 2177

Aggregate tasks in Gradle

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

Answers (3)

Vidya
Vidya

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

rundis
rundis

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

Perryn Fowler
Perryn Fowler

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

Related Questions