3

Gradle generally determines task order itself, which is often fine, but sometimes you need task ordering.

Based on the the User Guide and other discussion here it appears there are two basic ways to order tasks:

  • Using dependencies, i.e. taskB depends on taskA, so taskA will execute first.
  • Adding a new parent task, and using mustRunAfter as a constraint to sequence the subtasks.

However there are some situations where both approaches seem troublesome.

Example 1: In in daily task run by some continuous build system, you might have a sequence:

setupTask1 setupTask2 build test sendReport

Now, you can actually script this sequence externally, by passing these tasks on the gradle command line, i.e.

gradle setupTask1 setupTask2 build test sendReport

But if you want to write (and document) this sequence in the build file itself (rather than externally), are you required to create a new task, then add four new ordering constraints?

Example 2: Now imagine we have

startServer1 startServer2 integrationTest tearDownServer2 tearDownServer1

In this case, we want sequencing, but also control over failures, since if integrationTest fails, you still want the teardown steps to occur. Then we not only need mustRunAfter, we also have to add finalizedBy. And do we add the finalizer on integrationTest? What about if we add more tests that need such a harness? What if we want tearDownServer1 to be sequenced relative to tearDownServer2?

In summary, sequencing seems very clumsy, at least to a Gradle novice. In some cases, it might be more elegant simply to sequence things directly in a more imperative way. Am I missing something? Is there a better approach here?

Community
  • 1
  • 1
jlevy
  • 2,958
  • 2
  • 16
  • 11
  • If you need strict ordering of tasks in a CI system only, I'd imagine that a good way to do that is to let the CI system handle it. For example, a Jenkins job might consist of running several Gradle commands in sequence. – Jolta Mar 20 '15 at 08:52
  • For sure, this is one approach. But I think it _should_ be possible to handle this in your build system. And that's often preferable. For example, if you do, you can document these tasks in your build.gradle in version control, do code review on them, etc. All of which is impossible if it's embedded in CI configs. – jlevy Mar 20 '15 at 18:19
  • @jlevy Have you had any luck with this yet? – HELOX Jun 15 '15 at 06:42
  • 1
    @HELOX Not directly. Basically, we've tried to move such flows outside of Gradle, either above (in the CI system) or below (calling into scripts). Doing orchestration of tasks like this in Gradle seems attractive in theory, but in practice it may not be worth the complexity and maintenance costs. In particular, for scenarios like Example 2, doing the orchestration carefully in Bash or Python seems to be easier to test and use in isolation and for non-Gradle experts to understand. – jlevy Jun 15 '15 at 22:23

1 Answers1

2

It is (highly) advised to use the (already named) solutions to use dependsOn and mustRunAfter.

If you are fine with invoking tasks rather than depending on tasks, you could try the following possible solution for example one. Create a task that executes the tasks in sequence. You would get something like this:

task dailyCIJob << {
    [setupTask1, setupTask2, build, test, sendReport].each {
        it.execute()
    }
}

There are two, both not satisfying, solutions for example two:

  1. Use the --continue Gradle commanline argument. This will make Gradle continue if a task fails.
  2. Also you seem to be able to set a ignoreFailures boolean property per (test) task.
Community
  • 1
  • 1
HELOX
  • 529
  • 2
  • 13