gradle: how to remove task dependency

Viewed 1506

Gradle makes it easy to add task dependencies at runtime.

Is it also possible to remove a task dependency after it has been added?

As a use case, let's say we want to run checkstyle in a separate pipeline step, not as part of the main build. So, we apply the checkstyle plugin, but that adds some tasks that depend on check. I would like to break that dependency, so that checkstyle only runs when explicitly run, not as part of build (which depends on check, which depends on checkstyle*).

To accomplish the above, I could run the main pipeline step as build -x checkstyleMain -x checkstyleTest. Another workaround would be to set the enabled property of the checkstyle tasks to false.

But for this question, I am interested in a generic way to remove a task dependency so that the task graph is missing the edge between 2 tasks, like that dependency was never added. The problem is not an easy one because:

  • removing a dependency before it was added won't have any effect
  • trying to remove a dependency on gradle.taskGraph.whenReady will probably fail (since it's no longer allowed to change the task graph.

A good answer would also be that this is for sure not possible, in which case I could raise a feature request with the Gradle team.

Update 1

I tried to convert @Chriki's groovy to kotlin, like this:

project.afterEvaluate {
    tasks.check {
        dependsOn -= tasks.find {
            it.name.startsWith("checkstyle")
        }
    }
}

But this doesn't work. I get an error: "Removing a task dependency from a task instance is not supported."

1 Answers

Executing ./gradlew bar on the following self-contained build, will not run the foo task, even though it was declared as a dependency of bar (tested with Gradle 7.1):

task foo {
    doFirst {
        println 'foo'
    }
}


task bar {
    dependsOn foo
    doFirst {
        println 'bar'
    }
}

project.afterEvaluate {
    bar.dependsOn -= foo
}

In your case, you could hence add something like the following to your build.gradle to unconditionally remove the undesired Checkstyle task dependencies from the check task:

project.afterEvaluate {
    check.dependsOn -= checkstyleMain
    check.dependsOn -= checkstyleTest
}

Using the Kotlin DSL, the following works for my build script above:

project.afterEvaluate {
    val bar = tasks.findByPath("bar")
    if (bar != null) {
        bar.setDependsOn(bar.dependsOn - listOf(tasks.findByPath("foo"), "foo"))
    }
}

It’s important not to use the -= operator.

Please excuse the verbosity. I’m sure this can be written more concisely but I’m not fluent enough in Kotlin.

Related