Walk me through configuring `signing { sign(publishing.publications["maven"]) }`. What gets signed, and how do the signatures end up published?
answer
- signs jars + generated POM
- registers .asc onto publication
- signMavenPublication task
- publish depends on Sign
- publication must exist first
basics
~20 sInside 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 sYou 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 linespublishing {
publications {
create<MavenPublication>("maven") {
from(components["java"])
artifact(tasks["sourcesJar"])
artifact(tasks["javadocJar"])
}
}
}
signing {
sign(publishing.publications["maven"])
}
// -> creates task signMavenPublication; publish depends on itgo deeper
Know the one-liner sign(publishing.publications["maven"]) and that it signs the publication.
Explain that it iterates artifacts, attaches .asc, and creates signMavenPublication that publish depends on.
Discuss the overloads (Publication vs File/Configuration), why publication-level is preferred, and the config-time ordering pitfall.
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.