Search code examples
gradle

mustRunAfter has no effect in Gradle multi-project


I have a multi-project build with Gradle 2.0, where I want to defer all publish tasks to run after all build tasks have completed successfully, so that either all or none of the projects get published. I tried to use mustRunAfter, but without success. Therefore I reduced my setup to a minimal one:

Let's assume a gradle multi-project build with two subprojects 'foo' and 'bar', each with a build.gradle like this:

task 'build'
task 'publish'(dependsOn: build)

This will execute as:

$ gradlew publish
:bar:build UP-TO-DATE
:bar:publish UP-TO-DATE
:foo:build UP-TO-DATE
:foo:publish UP-TO-DATE

Then I added the following build.gradle to the root project:

def allBuilds = task build

subprojects {
    afterEvaluate {
        allBuilds.dependsOn build
        publish.mustRunAfter allBuilds
    }
}

But this does not change the execution order.

If I, however, change mustRunAfter into dependsOn, the execution looks like this:

$ gradlew publish
:bar:build UP-TO-DATE
:foo:build UP-TO-DATE
:build UP-TO-DATE
:bar:publish UP-TO-DATE
:foo:publish UP-TO-DATE

The downside of course is, that I cannot execute any subproject's :publish without all other projects :build being invoked. Is this a bug with mustRunAfter for multi-projects, am I doing it wrong or is there a better alternative to achieve this?


Solution

  • The problem seems to be, that the :build task is not actually executed, therefore the mustRunAfter has no effect. Instead of one root build task, I had to declare dependencies between all projects individually:

    subprojects {
        afterEvaluate {
            publish.dependsOn assemble
            publish.mustRunAfter parent.subprojects*.assemble
        }
    }
    

    I used assemble instead of build to avoid running all tests, just like publish does.