What's the difference between making signing conditional via `isRequired` versus disabling the Sign task with `onlyIf { ... }` or `enabled = false`? When would you use each?
answer
- isRequired = failure policy (still signs if key present)
- onlyIf/enabled=false = skip the task entirely
- onlyIf shows SKIPPED in output
- combine for require-on-release + guaranteed-skip-elsewhere
- wrong tool => silently unsigned releases
basics
~20 sisRequired controls whether a missing signature fails the build but still signs when a key exists. onlyIf/enabled=false skips the Sign task entirely — no signature produced even with a key. Use isRequired to relax failure; use onlyIf to truly skip signing.
solid answer
~50 sThese solve different problems. `isRequired = false` says 'don't *fail* if you can't sign' — but if a key is present the `Sign` task still runs and produces `.asc` files. `onlyIf { predicate }` and `enabled = false` operate at the **task-execution** level: when the predicate is false the `Sign` task is skipped outright, so **no signature is produced even if a key exists**. So: use `isRequired` (conditionally) when you want releases to *demand* signatures but local/snapshot builds to merely tolerate their absence — the common case. Use `onlyIf`/`enabled=false` when you want to *guarantee no signing happens* in certain contexts (e.g. a deliberately unsigned internal artifact, or to keep snapshots unsigned even if a key leaks into that job). They compose: `isRequired` for the failure policy plus `onlyIf` to gate execution. Note `onlyIf` shows as SKIPPED, which is clearer in build output than a silently-not-required task.
code
kotlin · 4 linesval isRelease = !version.toString().endsWith("-SNAPSHOT")
signing { isRequired = gradle.taskGraph.hasTask("publish") && isRelease }
// Guarantee snapshots are never signed, even if a key leaks in:
tasks.withType<Sign>().configureEach { onlyIf { isRelease } }go deeper
Know isRequired changes failure behavior; onlyIf/enabled actually skip the task.
Explain that isRequired still signs with a key present, while onlyIf guarantees no signature.
Choose the right layer per intent and combine them for require-on-release plus guaranteed-skip-elsewhere.
Standardize the pattern in a convention plugin and document why mismatching the tool risks unsigned releases.
## Two different layers Signing conditionality can be expressed at two levels: ### 1. `isRequired` — *failure policy* - `true`: cannot-sign → build fails. - `false`: cannot-sign → warn + skip, **but signs anyway if a key is present**. - It does **not** prevent signing; it only changes what happens when signing is impossible. ### 2. `onlyIf { }` / `enabled = false` — *execution gating* - These are generic Gradle task controls. The `Sign` task is a normal task. - When `onlyIf` returns false (or `enabled = false`), the task is **skipped** — it reports `SKIPPED` and produces **no signature**, regardless of whether a key is available. ## Concrete contrast ```kotlin // (A) Failure policy only: signs whenever a key exists signing { isRequired = gradle.taskGraph.hasTask("publish") && isRelease } // (B) Execution gating: never signs for snapshots, even with a key tasks.withType<Sign>().configureEach { onlyIf { isRelease } // SKIPPED entirely when not a release } ``` With (A) alone, a key accidentally present in snapshot CI would sign snapshots. With (B), snapshots are *guaranteed* unsigned. ## When to use which - **Use `isRequired` (conditionally)** for the standard release-safety pattern: require signatures for releases, tolerate their absence elsewhere. This is the canonical answer to this leaf's topic. - **Use `onlyIf` / `enabled = false`** when you must *guarantee* no signature is produced in a context, or to make the skip explicit and visible in logs. - **Combine** them when you want both a hard requirement for releases and a guaranteed skip for everything else. ## Output-clarity nuance `onlyIf` produces a visible `> Task :signX SKIPPED`, which is easier to reason about during incident triage than discovering after the fact that `isRequired` happened to be false. Many setups therefore pair them. ## Pitfall Don't reach for `enabled = false` unconditionally to 'turn off signing' if you actually want releases signed — you'd silently ship unsigned releases. Match the tool to the intent: *failure tolerance* → `isRequired`; *guaranteed skip* → `onlyIf`.
- With `isRequired = false` and a key present, is a signature produced?Yes — isRequired only governs the cannot-sign failure. To prevent signing outright you must skip the task via onlyIf or enabled=false.
- Which approach shows up as SKIPPED in the build log?onlyIf (and enabled=false) skip the task, reporting SKIPPED. A not-required signing run that simply has no key warns rather than cleanly showing SKIPPED.
saying these in an interview costs you the question
- Claiming isRequired=false prevents signing — it doesn't if a key exists.
- Using enabled=false to 'make signing conditional' when you actually want releases signed — that ships unsigned releases.