Gradle custom task which runs multiple tasks

Gradle

Gradle Problem Overview


I wanna run multiple gradle tasks as one. So instead of

./gradlew clean build publish

I want to have a custom task

./gradlew cleanBuildPublish

that executes clean build and publish in order.

How's that possible?

This does not work

task cleanBuildPublish {
    dependsOn 'clean'
    dependsOn 'build'
    dependsOn 'publish'
}

Gradle Solutions


Solution 1 - Gradle

If you need to execute some tasks in predefined order, then you need to not only set dependsOn, but also to set mustRunAfter property for this tasks, like in the following code:

task cleanBuildPublish {
    dependsOn 'clean'
    dependsOn 'build'
    dependsOn 'publish'
    tasks.findByName('build').mustRunAfter 'clean'
    tasks.findByName('publish').mustRunAfter 'build'
}

dependsOn doesn't define an order of tasks execution, it just make one task dependent from another, while mustRunAfter does.

Solution 2 - Gradle

You can also use the task base class called GradleBuild

Here how you can do that with GradleBuild

Groovy DSL:

task cleanBuildPublish(type: GradleBuild) {
     tasks = ['clean', 'build', 'publish']
}

Kotlin DSL:

tasks.register<GradleBuild>("cleanBuildPublish") {
    tasks = listOf("clean", "build", "publish")
}

Solution 3 - Gradle

My approach is

task cleanBuildPublish (type: GradleBuild, dependsOn: ['clean', 'build', 'publish']) { 
}

This works for me.

Solution 4 - Gradle

Try below way to make cleanBuildPublish depend on other tasks

build.gradle

task clean{
	println "lets clean"
}

task build {
	println "lets build"
}

task publish {
	println "lets publish"
}

task cleanBuildPublish{
	println 'lets do all'
}


cleanBuildPublish.dependsOn clean
cleanBuildPublish.dependsOn build
cleanBuildPublish.dependsOn publish

Output

$ gradle cleanBuildPublish
lets clean
lets build
lets publish
lets do all
:build UP-TO-DATE
:clean UP-TO-DATE
:publish UP-TO-DATE
:cleanBuildPublish UP-TO-DATE

BUILD SUCCESSFUL

Total time: 2.738 secs

check https://docs.gradle.org/current/userguide/more_about_tasks.html#addDependencyUsingTask for more details

Solution 5 - Gradle

If publish task is in a sub project named subProjectName,

...
tasks.findByPath(':subProjectName:publish').mustRunAfter 'build'
...

Solution 6 - Gradle

A generic way to get it, would be the following:

task cleanBuildPublish {
  def containedTasks = [clean, build, publish]
  dependsOn containedTasks
  placeTasksInOrder(containedTasks)
}

def placeTasksInOrder(List tasks) {
  for (int i=0; i < tasks.size() -1; i++) {
    def earlierTask = tasks.get(i)
    def laterTask   = tasks.get(i +1)
    laterTask.mustRunAfter(earlierTask)
  }
}

dependsOn causes the other tasks to run when cleanBuildPublish is run and the helper function placeTasksInOrder place the tasks in order by calling mustRunAfter

When executing gradlew cleanBuildPublish somethingElse the order will be clean, build, publish, somethingElse


Beware:
The following solution does NOT work if you have nested gradle calls

task cleanBuildPublish(type: GradleBuild) {
     tasks = ['clean', 'build', 'publish']
}

When executing gradlew cleanBuildPublish somethingElse, then it could happen, that somethingElsewill be called first.
So one should better use the mustRunAfterconfiguration.

Solution 7 - Gradle

Here is how I did it, with Kotlin scripting, using both dependsOn and mustRunAfter. Here is an example of running two tasks, one (custom registered "importUnicodeFiles" task) that is in "this" project and one (predefined "run" task) that is in a sibling project named ":unicode":

tasks.register("rebuildUnicodeFiles") {
    description = "Force the rebuild of the `./src/main/resources/text` data"
    val make = project(":unicode").tasks["run"]
    val copy = tasks["importUnicodeFiles"]
    dependsOn(make)
    dependsOn(copy)
    copy.mustRunAfter(make)
}

The Gradle developers generally advise against this approach (they say that forcing ordering is bad, and that executing tasks from other projects is bad), and are working on a way to publish results between projects; see: https://docs.gradle.org/current/userguide/cross_project_publications.html

Solution 8 - Gradle

My solution is as follows and it works for me.

task cleanBuildPublish {

    task _clean {
        dependsOn 'clean'
    }

    task _build {
        dependsOn '_clean'
        dependsOn 'build'
    }

    dependsOn '_build'
    dependsOn 'publish'
}

Solution 9 - Gradle

Try adding defaultTasks in build.gradle. For eg. defaultTasks 'clean', 'build', 'publish'

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNiklasView Question on Stackoverflow
Solution 1 - GradleStanislavView Answer on Stackoverflow
Solution 2 - GradletasomaniacView Answer on Stackoverflow
Solution 3 - GradleCodevView Answer on Stackoverflow
Solution 4 - GradleSantosh GokakView Answer on Stackoverflow
Solution 5 - GradleAsankaView Answer on Stackoverflow
Solution 6 - GradleKeKruView Answer on Stackoverflow
Solution 7 - GradlecpurdyView Answer on Stackoverflow
Solution 8 - GradleKen WuView Answer on Stackoverflow
Solution 9 - GradleSumit Pal SinghView Answer on Stackoverflow