How to order amongst the group of dependsOn tasks?


(steve) #1

I am trying to develop a “release” task within a multi-project build. This task needs to coordinate the execution of many tasks across all the projects. Essentially I want clean to be the very first task run across all the projects. But thats not what happens. Adding each project’s clean task executes clean in a non-intuative way. For example:

:hibernate-c3p0:clean
:hibernate-c3p0:generatePomFileForMavenJavaPublication
:hibernate-core:generateGrammarSource UP-TO-DATE
:hibernate-core:jaxb UP-TO-DATE
:hibernate-core:generateMainLoggingClasses UP-TO-DATE
:hibernate-core:compileJava UP-TO-DATE
:hibernate-core:processResources UP-TO-DATE
:hibernate-core:classes UP-TO-DATE
:hibernate-core:jar UP-TO-DATE
:hibernate-c3p0:generateMainLoggingClasses
:hibernate-c3p0:compileJava
:hibernate-c3p0:processResources
:hibernate-c3p0:classes
:hibernate-c3p0:jar
:hibernate-c3p0:sourcesJar
:hibernate-c3p0:publishMavenJavaPublicationToJboss-snapshots-repositoryRepository
...
:hibernate-c3p0:publish
:hibernate-testing:generateMainLoggingClasses UP-TO-DATE
:hibernate-testing:compileJava UP-TO-DATE
:hibernate-testing:processResources UP-TO-DATE
:hibernate-testing:classes UP-TO-DATE
:hibernate-testing:jar UP-TO-DATE
:hibernate-c3p0:compileTestJava
:hibernate-c3p0:processTestResources
:hibernate-c3p0:testClasses
:hibernate-c3p0:test
:hibernate-core:clean
:hibernate-core:generatePomFileForMavenJavaPublication
:hibernate-core:sourcesJar
:hibernate-core:publishMavenJavaPublicationToJboss-snapshots-repositoryRepository

Essentially, the jar for the hibernate-core module is “built” (really its just skipped because clean happens later), then hibernate-core is cleaned before Gradle finally tries to publish the artifact it just cleaned.

The “release task” itself is very simple:

task performRelease(type: Task) {
    description = "Perform a full set of release steps (sans VCS handling)"
}

All the interesting bits are handled through task dependepncies:

performRelease.dependsOn rootProject.subprojects.findAll{ p -> p.tasks.findByPath("clean") }.tasks.clean
performRelease.dependsOn rootProject.subprojects.findAll{ p -> p.tasks.findByPath("test") }.tasks.test
performRelease.dependsOn rootProject.subprojects.findAll{ p -> p.tasks.findByPath("publish") }.tasks.publish
performRelease.dependsOn uploadDocs
performRelease.dependsOn uploadBundles

But as you can see above from output, this leads to undesireable ordering amongst the dependency tasks.

Perhaps this is related to the recent discussions on the dev mailing list wrt task ordering?


(Matt Khan) #2

fwiw I have implemented something like this via brute force, i.e. make every task that isn’t called clean depend on clean

project.tasks.matching { !it.name.equals('clean') && !it.name.startsWith('cleanprotoc') }.all { it.dependsOn project.tasks.clean }

(steve) #3

Thanks for the reply Matt,

But that means clean is run anytime I want to run those other tasks. So if I run ‘gradle test’ its going to clean every time. I’d prefer to not go that route.


(Peter Niederwieser) #4

Have a look at the new ‘mustRunAfter’ feature in 1.6 (see release notes). Alternatively you could check if ‘gradle.startParameter.taskNames’ contains ‘performRelease’ and insert a ‘clean’ in front. However this has some limitations (e.g. only works if ‘performRelease’ is contained in initial task names).


(Matt Khan) #5

you do need to guard it with some property based condition, e.g. either explicitly activate or deactivate the addition of the clean dependency based on the value or presence of some property (not a task unless you rely on the start params as Peter says)


(steve) #6

Thanks for the pointer about mustRunAfter Peter. I think that is ultimately the way to go. I’ll play around with it