skip to content

What does the --dry-run flag do when you run a Gradle build, and when would you use it?

level: juniorimportance: must knowfreq 60%

answer

  1. prints task graph, executes nothing
  2. alias -m
  3. tasks shown as SKIPPED in real order
  4. configuration still runs, actions don't
  5. preview before slow/destructive goal

basics

~10 s

--dry-run makes Gradle print the ordered list of tasks it WOULD run for your requested goal, without actually executing any of them. It's a safe way to preview the task graph.

solid answer

~30 s

`--dry-run` (alias `-m`) runs Gradle's configuration phase normally, builds the full task execution graph for the requested tasks, then prints each task in execution order with a `SKIPPED` marker instead of executing it. No task actions, no outputs, no side effects. It's useful to (1) verify which tasks a goal like `build` actually pulls in via `dependsOn`/`finalizedBy`, (2) confirm task ordering before a destructive or slow operation, and (3) sanity-check a wiring change without paying execution cost. Note it still *configures* the build, so configuration-time logic and any `doFirst`/`doLast` are NOT triggered, but plugin configuration and lazy task registration still happen.

code

bash · 4 lines
bash
# Preview what 'build' actually runs, without executing anything
./gradlew build --dry-run
# Short alias
./gradlew build -m

go deeper

for a junior

Know it previews the ordered task list without executing, and shows tasks as SKIPPED.

for a middle

Explain the phase model: configuration still runs, only execution is replaced; name the alias -m.

for a senior

Discuss precise semantics — what is and isn't triggered — and practical uses (auditing wiring, previewing destructive goals).

for a principal

Position it within a measurement toolkit: --dry-run for graph shape, separate tools for timing/cache; caution that it won't catch slow or side-effecting configuration.

## What a Gradle build does in phases Every Gradle invocation runs three phases: 1. **Initialization** — decides which projects participate (reads `settings.gradle(.kts)`). 2. **Configuration** — evaluates every build script needed, registers/configures tasks, and builds the **task graph** (a directed acyclic graph of task dependencies from `dependsOn`, `mustRunAfter`, `finalizedBy`, and input/output wiring). 3. **Execution** — runs the selected tasks' actions in dependency order. ## What --dry-run changes `--dry-run` (short form `-m`) runs **initialization and configuration normally** but **replaces execution with a print-out**. For each task that *would* run, Gradle prints the task path followed by `SKIPPED`: ``` :compileJava SKIPPED :processResources SKIPPED :classes SKIPPED :jar SKIPPED :assemble SKIPPED ``` The order shown is the real planned execution order, so it's an accurate preview of the task graph for the requested goal. ## What it does and does NOT trigger - **Triggered:** project evaluation, plugin application, task *registration* and *configuration* closures, and graph construction. Anything in a configuration block (e.g. `tasks.register("x") { ... }`) runs. - **NOT triggered:** the task *actions* themselves — `doFirst`, `doLast`, `@TaskAction` methods, the work the task performs. No files are written, no tests run, no artifacts published. ## When to reach for it - Auditing what a high-level goal expands to (`./gradlew build --dry-run`). - Verifying a wiring change (`finalizedBy`, `dependsOn`) produced the ordering you intended. - Previewing before something expensive or irreversible (a `publish`, a `flywayClean`). - Teaching/onboarding: showing newcomers the shape of the graph. ## Caveats Because configuration still runs, `--dry-run` is **not** a way to test that configuration is fast or side-effect-free — it can still be slow if configuration is heavy, and configuration-time side effects (eager work outside task actions) still happen. It also does not evaluate task up-to-date / cache state in a way you can act on, since nothing executes.

  • Does --dry-run run the configuration phase?
    Yes. Initialization and configuration run normally — only the execution phase is replaced by the SKIPPED print-out. So task registration and configuration closures execute, but task actions do not.
  • Will a doLast block run under --dry-run?
    No. doFirst/doLast/@TaskAction are part of execution and are skipped. Only configuration-time code runs.

saying these in an interview costs you the question

  • Claiming --dry-run skips the configuration phase (it doesn't — only execution is skipped).
  • Saying it shows up-to-date / cache hit info for each task (nothing executes, so it can't).

context