What is the difference between an ordering rule (mustRunAfter/shouldRunAfter) and a task dependency in Gradle?
answer
- dependency = pull in + run first
- ordering = sequence only IF both scheduled
- ordering never adds to graph
- run integTest alone vs with test
- decoupling sequencing from requirement
basics
~20 sAn ordering rule only fixes the relative order of two tasks IF both already end up in the task graph. It never adds a task to the graph or forces it to run, unlike a dependency, which both pulls a task in and runs it first.
solid answer
~40 sA dependency (`dependsOn`) does two things: it adds the dependency task to the execution graph and guarantees it runs before the dependent task. An **ordering rule** (`mustRunAfter` / `shouldRunAfter`) does only one thing: it constrains relative order *if and only if* both tasks are already scheduled to run in the same build. If the other task is not in the graph (not requested, up-to-date-skipped, or excluded with `-x`), the ordering rule is simply ignored — nothing is added and nothing fails. The classic use case: you want `integTest` to run after `test` *when a user asks for both*, but you still want to be able to run `integTest` alone. `dependsOn` would force `test` to run every time; `mustRunAfter` gives you ordering without coupling. Ordering rules express *sequencing*, dependencies express *requirement*.
code
kotlin · 7 lines// Ordering without coupling: integTest runs after test ONLY when both are requested
tasks.named("integTest") {
mustRunAfter(tasks.named("test"))
}
// vs. a dependency, which would force test to run every time integTest runs:
// tasks.named("integTest") { dependsOn("test") }go deeper
Be able to state that ordering controls sequence only, while a dependency pulls a task in and forces it to run.
Give the integTest-after-test example and explain the 'run alone vs run together' behavior.
Discuss why decoupling sequencing from requirement keeps builds flexible and avoids over-pulling tasks; mention interaction with -x and up-to-date.
Frame ordering rules as a tool for shaping shared task-graph conventions across many modules without forcing unnecessary work, and the maintainability tradeoffs.
## The two distinct concepts Gradle's task graph (a directed acyclic graph) is built from two independent kinds of edges: 1. **Dependency edges** — created by `dependsOn`, by consuming another task's output (inferred), or by `finalizedBy`. A dependency edge says *"this task requires that task to be present and to have executed first."* It pulls the task **into** the graph. 2. **Ordering edges** — created by `mustRunAfter` and `shouldRunAfter`. An ordering edge says *"IF both of these tasks are already going to run, run them in this order."* It does **not** pull anything into the graph and does **not** force execution. ## Why the distinction matters Consider: ```kotlin tasks.named("integTest") { mustRunAfter("test") } ``` - Run `gradle test integTest` → both are scheduled, so `test` runs first, then `integTest`. - Run `gradle integTest` alone → `test` is **not** in the graph, so the rule is inert; `integTest` runs by itself. If you had instead written `dependsOn("test")`, running `integTest` alone would *always* drag `test` along — usually not what you want for a sequencing concern. ## Key properties of ordering rules - They are **conditional**: only effective when both tasks are in the same build's graph. - They are **non-additive**: they never add a task to the graph. - They interact with `--continue`, exclusions (`-x`), and up-to-date checks: if the predecessor is excluded or filtered out, ordering simply doesn't apply. ## Summary table | Feature | `dependsOn` | `mustRunAfter` / `shouldRunAfter` | |---|---|---| | Adds task to graph? | Yes | No | | Forces execution? | Yes | No | | Controls order? | Yes | Yes (if both scheduled) | Think of dependencies as *"I need this done"* and ordering rules as *"if we're both doing it, you go first."*
- If you declare `integTest.mustRunAfter(test)` and run only `gradle integTest`, does `test` execute?No. `mustRunAfter` only orders tasks that are already in the graph. Since `test` was not requested, it is not added and does not run; `integTest` runs alone.
- Can an ordering rule alone guarantee a task is built before another in a CI pipeline?No — because it doesn't pull the task into the graph. You need a dependency (or to request both tasks) to guarantee presence; ordering only sequences them once both are present.
A dependency is "you must eat dinner before dessert" (dinner is mandatory). An ordering rule is "if you happen to have both dinner and dessert tonight, eat dinner first" — but skipping dinner entirely is fine.
saying these in an interview costs you the question
- Claiming mustRunAfter forces the predecessor to run (it does not).
- Saying ordering rules and dependencies are interchangeable.