Walk through the Gradle tasks the publish-plugin contributes and the order you'd invoke them to ship a release.
answer
- initialize → publishToSonatype → close → release
- task names embed repo name
- closeAndRelease chains both
- staging id in build state — run same invocation
- close/release poll the API
basics
~10 sRun publishToSonatype to create the staging repo and upload artifacts, then closeAndReleaseSonatypeStagingRepository to validate and promote to Central. Often combined: ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository.
solid answer
~40 sThe plugin derives task names from the repository name you configure (`sonatype` → `...Sonatype...`). The pipeline is: 1. `initializeSonatypeStagingRepository` — opens a fresh staging repo and remembers its server id. 2. `publishToSonatype` — runs your `maven-publish` `publishAllPublicationsToSonatypeRepository`, uploading every artifact + signature into that staging repo. 3. `closeSonatypeStagingRepository` — closes it, triggering Sonatype's validation. 4. `releaseSonatypeStagingRepository` — promotes the closed repo to Central. The convenience task `closeAndReleaseSonatypeStagingRepository` runs 3 and 4 together. A typical CI invocation is `./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository`. Because the staging-repo id is shared via build state, you must run these in the **same Gradle invocation** (or persist the id) so close/release act on the repo you just published to.
code
bash · 3 lines# One invocation so the staging-repo id is shared across tasks
./gradlew clean publishToSonatype \
closeAndReleaseSonatypeStagingRepository --no-configuration-cachego deeper
Recall the happy-path command: publishToSonatype then closeAndReleaseSonatypeStagingRepository.
Name each task, explain the order, and that task names mirror the configured repo name.
Explain the shared-staging-id build-state constraint and the polling/timeout behaviour for async close/release.
Design the CI topology (single job vs. split with persisted id), failure recovery (drop on failed close), and timeout governance for flaky Central days.
## Task naming Every task name embeds the repository name you set inside `nexusPublishing { repositories { sonatype { } } }`. Configure a repo named `sonatype` and you get `publishToSonatype`, `closeSonatypeStagingRepository`, etc. Name it `myNexus` and the tasks become `publishToMyNexus`, `closeMyNexusStagingRepository`. This matters because you can configure multiple Nexus targets. ## The full ordered flow 1. **initialize** — `initializeSonatypeStagingRepository` calls the staging API to **open** a new repository and captures its id (e.g. `comexample-1042`). This id is held in build state for the rest of the invocation. 2. **upload** — `publishToSonatype` is an alias that depends on `publishAllPublicationsToSonatypeRepository` from `maven-publish`; the plugin has injected the staging URL so artifacts land in the just-opened repo. This is where signing matters: each artifact needs a `.asc`. 3. **close** — `closeSonatypeStagingRepository` closes the repo; Sonatype validates. The task **polls** the API until the transition finishes or times out. 4. **release** — `releaseSonatypeStagingRepository` promotes; it also polls. 5. **closeAndRelease** — `closeAndReleaseSonatypeStagingRepository` chains close then release. ## Why same-invocation matters The opened staging-repo id lives in **in-memory build state**. If you run `publishToSonatype` in one `gradle` call and `closeAndReleaseSonatypeStagingRepository` in a separate call, the second call has no id and will fail (or scan for repos). Either run them together, or pass `-Pio.github.gradle-nexus...stagingRepositoryId=...` to target a specific repo explicitly. ## Practical CI line ```bash ./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository \ -PsonatypeUsername=$SONATYPE_USER -PsonatypePassword=$SONATYPE_PW ``` ## Timeouts Close and release are asynchronous on Sonatype's side, so the plugin polls. Slow Central days may need a longer `clientTimeout`/`numberOfRetries` in `nexusPublishing { }`.
- Why can splitting publish and close into two Gradle invocations fail?The opened staging-repo id is kept in in-memory build state; a second invocation has lost it, so close/release have no target unless you pass the id explicitly.
- How does the plugin know when a close has finished, given it's asynchronous?It polls the Nexus staging API on an interval up to a configurable timeout/retry count before succeeding or failing.
- Where do task names like 'publishToSonatype' come from?From the repository name you declare inside nexusPublishing; rename it and every task name changes accordingly.
saying these in an interview costs you the question
- Claiming you can publish in one CI job and close in a totally separate job without persisting the staging-repo id.
- Forgetting that artifacts must be signed before close, or close validation fails.