Marcin Erdmann

Groovy, Grails, Geb...

New in Gradle 1.6: task ordering

Recently Gradle 1.6 has been released. I was lucky enough to get a lot of support from the Gradle team in the means of implementation guidance and code reviews for contributing a new feature: task ordering. Currently it's an icubating feature (see here what it means) and only "must run after" ordering is supported, though it's highly likely that other rules, like for example "should run after" with a slightly less restrictive contract, are coming.

Let's look at a trivial example:

task a
task b {
    mustRunAfter a
}

Executing gradle b will only execute b but executing gradle b a will first execute a and then b. So if both a and b are in the task graph for a given build run then b will run after a (just like if b depended on a) but requesting to run b won't pull a into the task graph (contrary to what would happen if b depended on a).

"Must run after" ordering is useful if you want to specify an ordering between two tasks but only if both of them are in the graph - the fact that the task that must run after another task is in the graph doesn't automatically mean that the task it must run after will be. This comes handy for example when you want to run unit tests before integration tests as there is usually no point in running integration tests if unit tests fail, but still being able to run integration tests on their own. Luke Daley came up with a more sophisticated use case - running all verifications (e.g. checkstyle, tests) on all projects (if they are to be executed in this build) before uploading anything. e.g. gradle clean build uploadArchives will only upload after all projects have been built and tested, but gradle uploadArchives will upload archives without running the tests:

allprojects {
    tasks.withType(Upload) {
        allprojects {
            mustRunAfter tasks.matching { it instanceof VerificationTask }
        }
    }
}

To specify "must run after" ordering between tasks you should use the Task.mustRunAfter() method which accepts a task instance, a task name or any other input from this list.