skip to content

Walk me through configuring `signing { sign(publishing.publications["maven"]) }`. What gets signed, and how do the signatures end up published?

level: middleimportance: must knowfreq 50%

answer

  1. signs jars + generated POM
  2. registers .asc onto publication
  3. signMavenPublication task
  4. publish depends on Sign
  5. publication must exist first

basics

~20 s

Inside the signing { } block you call sign(...) passing the publication. That signs every artifact in that publication — jars and POM — and adds each .asc to the publication so publish uploads them.

solid answer

~40 s

You apply both `maven-publish` and `signing`, then reference the publication you defined under `publishing.publications`. The call `sign(publishing.publications["maven"])` tells the signing plugin: *for the publication named `maven`, create a detached signature for each of its artifacts and register those `.asc` files back onto the same publication.* Behind the scenes Gradle creates a `Sign` task (`signMavenPublication`) and makes the publication's publish/upload tasks depend on it, so signatures always exist before upload. Crucially, signing a **publication** (rather than individual files) keeps the wiring declarative: as you add a sources jar or javadoc jar to the publication via `artifact(...)`, they're automatically signed too. The key material itself is configured elsewhere (`gradle.properties` or in-memory). One common pitfall is ordering — the publication must be **defined** before you call `sign(...)` against it, otherwise the lookup fails.

code

kotlin · 14 lines
kotlin
publishing {
  publications {
    create<MavenPublication>("maven") {
      from(components["java"])
      artifact(tasks["sourcesJar"])
      artifact(tasks["javadocJar"])
    }
  }
}

signing {
  sign(publishing.publications["maven"])
}
// -> creates task signMavenPublication; publish depends on it

go deeper

for a junior

Know the one-liner sign(publishing.publications["maven"]) and that it signs the publication.

for a middle

Explain that it iterates artifacts, attaches .asc, and creates signMavenPublication that publish depends on.

for a senior

Discuss the overloads (Publication vs File/Configuration), why publication-level is preferred, and the config-time ordering pitfall.

for a principal

Standardize the pattern in convention plugins so every module publishes consistently signed.

## The pieces involved Two plugins cooperate. `maven-publish` defines **publications** — named bundles of artifacts plus a generated POM, under `publishing { publications { } }`. The `signing` plugin signs them. ```kotlin plugins { `maven-publish` signing } publishing { publications { create<MavenPublication>("maven") { from(components["java"]) artifact(sourcesJar) artifact(javadocJar) } } } signing { sign(publishing.publications["maven"]) } ``` ## What `sign(publication)` actually does It is an overload of `SigningExtension.sign(...)`. Given a `Publication`, it: 1. iterates every artifact the publication contains (main jar from `components.java`, the extra `sources`/`javadoc` jars, and the POM that `maven-publish` generates); 2. for each, registers a signing operation that runs GPG/PGP to produce a detached `.asc`; 3. **adds each `.asc` back to the publication as an additional artifact**, so it travels with the publication everywhere it's published. ## Task wiring The plugin creates a `Sign` task named after the publication — `signMavenPublication`. `maven-publish`'s `publishMavenPublicationTo<Repo>Repository` and `publishToMavenLocal` tasks are made to **depend on** that `Sign` task. So `./gradlew publish` order is: build artifacts → sign them → upload originals + `.asc`. You can run signing in isolation with `./gradlew signMavenPublication`; outputs land alongside the artifacts (e.g. `build/libs/*.asc`, and a signed POM under `build/publications/maven/`). ## Why sign the publication, not files `sign(...)` is overloaded — it accepts `Publication`, `Configuration`, `Task`, or arbitrary `File`s. Signing the **publication** is preferred for Maven Central because it guarantees *every* member artifact (including the auto-generated POM and any later-added jars) is covered, with the `.asc` files correctly attached for upload. Signing loose files would not register them onto the publication and you'd risk missing the POM signature, which Central requires. ## Ordering pitfall `publishing.publications["maven"]` is a **lookup by name at configuration time**. The publication must already be created. If your `signing` block runs before the publication is declared, you get a 'publication with name maven not found' error. Declaring the publication earlier in the script, or using `publishing.publications.withType<MavenPublication>().configureEach { ... }` patterns, avoids it.

  • What's the name of the task created by `sign(publishing.publications["maven"])`?
    `signMavenPublication` — the `Sign` task is named `sign` + the publication name capitalized. The publish tasks depend on it.
  • Is the generated POM signed too?
    Yes. Signing a publication covers all its artifacts including the POM that `maven-publish` generates, which is exactly what Maven Central requires.
  • Why might `sign` fail with 'publication not found'?
    Because `publications["maven"]` is resolved at configuration time; the publication must be declared before the `signing` block references it by name.

saying these in an interview costs you the question

  • Signing individual files instead of the publication, then wondering why the POM isn't signed.
  • Calling `sign(...)` before the publication is created and not understanding the name-lookup failure.

context