How do you make a Gradle task always run (never be considered up-to-date), and when would you do that?
answer
- outputs.upToDateWhen { false }
- always out of date
- Spec<Task> predicate
- untrackable side effects
- escape hatch not default
basics
~20 sAdd outputs.upToDateWhen { false } to the task. The predicate always returns false, so Gradle never treats the task as up-to-date and runs it every build. Useful for tasks with side effects Gradle can't track.
solid answer
~40 sGradle skips a task when its declared inputs and outputs are unchanged. To force a task to always execute, register an up-to-date predicate that always returns false: ```kotlin tasks.named("deploy") { outputs.upToDateWhen { false } } ``` This tells Gradle the task is never up-to-date, so it runs on every invocation. You'd use it for tasks whose real effects Gradle cannot see — calling an external service, deploying, printing live status, or reading a value that changes outside the build (timestamps, remote state). Note it disables incremental skipping but the task can still be `cacheable` only if no `cacheIf` says otherwise; in practice you usually also want it not cached. Prefer declaring proper inputs/outputs when the effect *is* trackable — `upToDateWhen { false }` is the escape hatch, not the default.
code
kotlin · 5 linestasks.register("deploy") {
// Gradle can't see the remote server, so never skip this task
outputs.upToDateWhen { false }
doLast { println("deploying...") }
}go deeper
Recall the one-liner outputs.upToDateWhen { false } and that it forces the task to run every build.
Explain WHY (untrackable side effects), that it's a Spec<Task> predicate, and that predicates are AND-ed.
Contrast with declaring proper inputs/outputs, note it sacrifices incremental performance, and distinguish from cache behavior.
Frame it as an escape hatch policy: prefer modeled inputs/outputs for cacheability across the team/CI; flag overuse as a build-performance smell.
## Up-to-date checking, briefly Gradle is an incremental build tool. Before running a task it computes a fingerprint of the task's **declared inputs** (files, properties) and **declared outputs**. If neither changed since the last successful run, the task is reported `UP-TO-DATE` and skipped. This is what makes repeated builds fast. ## The `upToDateWhen` escape hatch Sometimes a task has effects Gradle cannot model as files/properties — it deploys to a server, queries a remote API, or its result depends on the wall clock. For those, you override the decision with a predicate: ```kotlin tasks.register("reportStatus") { outputs.upToDateWhen { false } // always out of date -> always runs doLast { println("live status...") } } ``` `outputs.upToDateWhen { spec }` registers a `Spec<? super Task>`. Gradle considers the task up-to-date **only if** all registered predicates return `true` AND the input/output fingerprints match. Returning `false` short-circuits the whole thing, forcing execution. ## Important subtleties - It does **not** add `@Outputs`; a task with no outputs at all is also always out of date, but a predicate is the explicit, readable way. - Multiple `upToDateWhen` calls are **AND-ed** — any `false` wins. - The predicate receives the task instance, so you can make the decision conditional: `outputs.upToDateWhen { !project.hasProperty("force") }`. - This affects only the *up-to-date* decision. Build-cache reuse is governed separately by `outputs.cacheIf`/`@CacheableTask`. ## When NOT to use it If the effect *is* trackable, declare real inputs/outputs (`inputs.file`, `outputs.dir`) instead. Forcing a rerun throws away incremental performance and parallelism benefits, so reserve it for genuinely untrackable side effects.
- Does `upToDateWhen { false }` also prevent build-cache reuse?Not directly. Up-to-date and cache are separate decisions. A task forced never-up-to-date will rerun, but if it's `@CacheableTask`/`cacheIf` it could still pull outputs from the cache. For a hard 'always do real work' task, also avoid caching it.
- What if you register two `upToDateWhen` predicates?They're combined with logical AND. The task is up-to-date only if every predicate returns true (and fingerprints match); a single `false` forces a rerun.
saying these in an interview costs you the question
- Claiming `upToDateWhen { false }` clears the build cache or deletes outputs — it only affects the up-to-date decision.
- Using it as the default for ordinary file-producing tasks instead of declaring inputs/outputs.