Regression in task dependency graph in 1.7+ that breaks -x flag

Some of our developers noticed that once they upgrade to Gradle 1.7 or higher they could no longer exclude the test task from executing. This doesn’t happen in the vanilla Java plugin, but it surfaces due to a test results aggregation task we place in one of our plugins. After a lot of digging, here’s what I’ve found.

Take a sample build, such as this:

settings.gradle

include 'sub'

build.gradle

allprojects {
 task check
 task build(dependsOn: check)
}
    task aggregateTest
check.dependsOn aggregateTest
  project(':sub') {
 task test << { println 'This should not run' }
 check.dependsOn test
 rootProject.aggregateTest.dependsOn test
}

Running it against Gradle 1.6 gives you this:

C:\Temp\exclude-example>gradlew build -x test
:aggregateTest
:check
:build
:sub:check
:sub:build
  BUILD SUCCESSFUL
  Total time: 0.877 secs

Running it against Gradle 1.7 or higher gives you this: (note the test task executing)

C:\Temp\exclude-example>gradlew build -x test
:sub:test
This should not run
:aggregateTest
:check
:build
:sub:check
:sub:build
  BUILD SUCCESSFUL
  Total time: 1.615 secs

I bisected through all of the changes between 1.6 and 1.7 and got to this commit that touched the task graph during the implementation of finalizers.

I’m not very familiar with that part of the codebase, so I can’t really parse out what specifically is the issue. I added some logging statements to TaskInfo in a Gradle built from that commit to get a better picture of what is happening. Here’s that same sample build I used above with the logging statements printing. Note, that :sub:test is first marked required, then not required, and back to required. Seems to be a symptom of excluding a task that has two others that depend on it and are included in the graph.

C:\Temp\exclude-example>gradlew build -x test
require: :build
require: :sub:build
adding hard successor :build to :check
require: :check
adding hard successor :check to :aggregateTest
require: :aggregateTest
adding hard successor :aggregateTest to :sub:test
require: :sub:test
doNotRequire: :sub:test
adding hard successor :sub:build to :sub:check
require: :sub:check
adding hard successor :sub:check to :sub:test
require: :sub:test
Starting execution of: :sub:test
:sub:test
This should not run
Finishing execution of: :sub:test
Starting execution of: :aggregateTest
:aggregateTest
Finishing execution of: :aggregateTest
Starting execution of: :check
:check
Finishing execution of: :check
Starting execution of: :build
:build
Finishing execution of: :build
Starting execution of: :sub:check
:sub:check
Finishing execution of: :sub:check
Starting execution of: :sub:build
:sub:build
Finishing execution of: :sub:build
  BUILD SUCCESSFUL
  Total time: 2.02 secs

Can anyone familiar with the task graph help debug/patch this?

Thanks for the detailed analysis and report: I’ve raised GRADLE-3031 for this issue.

I’m guessing that this is related to GRADLE-2974, which was also reported for 1.7.

Agreed. That looks like the same issue.

Fixed in 1.12.

Thanks!