How can task dependencies which are only valid when a particular task has been executed, be declared?

(Using gradle 1.8) I have a set of tasks, which build, deploy, configure, startup & perform some more configuration (which can only be done after startup) on a piece of software.

I’ve tried to lay out the tasks & dependencies between those tasks that I must declare to do a full build, below:

task createBaseInstall ...
  task prepareA
task deployA ( dependsOn: [ prepareA, createBaseInstall ] ) ...
  .
.
.
  task prepareN
task deployN ( dependsOn: [ prepareN , createBaseInstall ] ) ...
  task startUp ( dependsOn : [ deployA , ... deployN ] ) ...
  task doPostStartTask1 ( dependsOn: startUp ) ...
task doPostStartTask2 ( dependsOn: startUp ) ...
  task fullBuild ( dependsOn: [ doPostStartTask1 , doPostStartTask2 ] ) ...

By executing the ‘fullBuild’ task I get the desired end result.

However, it is the case that each of the tasks that ‘fullBuild’ depends on - either directly or transitively - are useful to execute in isolation. For example the task ‘startUp’ could be executed if ever my newly built software crashed.

The dependencies declared between (1) ‘startUp’ & ‘deployA … deployN’;(2) ‘doPostStartTask1’ & ‘startUp’;(3) ‘doPostStartTask2’ & ‘startUp’ are useful only if the ‘fullBuild’ task has been executed.

I’m aware that I can use the ‘-x’ switch when invoking gradle on the command line to stop tasks from being executed - but (for example) to execute the ‘startUp’ task in isolation from all other tasks, the number of ‘-x’ switches required will (1) be many & (2) vary over time as more tasks are added to the build process - meaning more time required to document how to invoke particular tasks without invoking their dependents.

The best that I’ve been able to come up with, in order to dynamically influence which tasks will execute, based on whether or not the ‘fullBuild’ task has been executed, is code which looks like this:

gradle.taskGraph.whenReady {
    graph -> if ( ! graph.hasTask ( fullBuild ) ) {
                   if ( graph.hasTask ( deployA ) ) {
                     createBaseInstall.enabled = false
                 }
                   .
                 .
                 .
                   if ( graph.hasTask ( deployN ) ) {
                     createBaseInstall.enabled = false
                 }
                     if ( graph.hasTask ( startUp ) ) {
                      graph.getAllTasks().each {
                          task -> task.enabled = false
                      }
                      startUp.enabled = true
                 }
                   if ( graph.hasTask ( doPostStartTask1 ) ) {
                      graph.getAllTasks().each {
                          task -> task.enabled = false
                      }
                      doPostStartTask1.enabled = true
                 }
                   if ( graph.hasTask ( doPostStartTask2 ) ) {
                      graph.getAllTasks().each {
                          task -> task.enabled = false
                      }
                      doPostStartTask2.enabled = true
                 }
             }
}

which works - unless I try to invoke two tasks via the same command: e.g.

gradle doPostStartTask1 doPostStartTask2

now, ‘doPostStartTask2’ will be executed, but ‘doPostStartTask1’ will be skipped.

I don’t think that my approach is correct - it seems to me that the declaration of dependencies which are valid within the context of a task should be declared within that task, but I don’t now how to do that!

If it is possible - could anyone provide an example? & if not - is there a better way - a better approach to this problem situation that I can use?

Thanks,

Andrew.

You could make (only) ‘fullBuild’ depend on all the tasks, and control order between individual tasks via ‘mustRunAfter’ rather than ‘dependsOn’. That would allow you to run tasks independently. Or you could make tasks incremental by declaring their inputs/outputs and using ‘outputs.upToDateWhen { … }’, so that they only run if the desired state isn’t present.