OSSRH is being sunset in favor of the Central Portal. How does that migration affect a build using the gradle-nexus publish-plugin, and what are your options?
answer
- OSSRH (Nexus staging API) being sunset
- Central Portal = bundle upload, different API
- Portal OSSRH-compat endpoint bridges legacy tools
- new namespaces may be Portal-only
- isolate backend behind a convention plugin
basics
~20 sThe classic plugin targets the legacy OSSRH Nexus staging API. New Central Portal namespaces don't expose that API, so you either use OSSRH's Portal compatibility endpoint or switch to a Central-Portal-native plugin/publisher for newer setups.
solid answer
~50 sThe `gradle-nexus.publish-plugin` was built for **OSSRH**, Sonatype's Nexus-based staging service with a staging REST API (open/close/release). Sonatype announced OSSRH's end-of-life and is steering everyone to the **Central Portal**, which has a different publishing API. For builds and namespaces already on OSSRH, the existing plugin keeps working through the OSSRH service (and Sonatype provides a Portal **OSSRH compatibility** API so legacy tooling still functions during the transition). For **new** namespaces registered directly in the Central Portal, the old Nexus staging endpoints aren't available, so you move to a Central-Portal-native approach — e.g. the Portal publisher API (manual bundle upload), the `central-publishing-maven-plugin` for Maven, or a Gradle plugin/community plugin that targets the Portal. The decision hinges on **when your namespace was created** and Sonatype's published cutover dates; for CI, isolate the publishing logic behind a convention plugin so swapping the backend is a one-file change.
go deeper
Just be aware OSSRH is being replaced by the Central Portal and that publishing tooling is in flux.
Explain that the plugin targets OSSRH's Nexus staging API and that new namespaces may need a Portal-native tool.
Reason about the compatibility endpoint, when each backend applies, and isolating the backend behind a convention plugin.
Own the migration plan: namespace inventory, cutover timeline tracking, choosing the target publisher, and minimizing blast radius across many modules.
## Two services, two APIs - **OSSRH (legacy):** a hosted Nexus Repository Manager. Its **staging REST API** (open/close/release) is exactly what `gradle-nexus.publish-plugin` drives. This is the world the plugin was designed for. - **Central Portal (current):** Sonatype's replacement front end with a **different** publishing model — you push a **deployment bundle** and the Portal validates and publishes it. The classic Nexus staging endpoints are not the Portal's native interface. ## What the migration changes Sonatype set OSSRH on a deprecation path and asks projects to publish via the Central Portal. The practical impact: 1. **Existing OSSRH namespaces** continue to publish via the OSSRH service while it remains up, so the gradle-nexus plugin still works. To ease the gap, the Portal exposes an **OSSRH-compatibility staging API** that mimics the old endpoints, letting legacy tools keep functioning. 2. **Brand-new namespaces** are Portal-native and may **not** be reachable through the old Nexus staging API at all — so the gradle-nexus plugin can't drive them and you need a Portal-aware tool. ## Your options - **Stay on gradle-nexus + OSSRH (or its Portal-compat endpoint)** for namespaces that still support it. Lowest churn. - **Switch to a Central-Portal-native publisher:** upload a signed bundle to the Portal Publisher API, use the official `central-publishing-maven-plugin` (Maven), or a Gradle plugin/community integration that targets the Portal. These replace the open/close/release task set with a bundle-and-promote flow. - **Hybrid during transition:** keep `gradle-nexus` while watching Sonatype's announced cutover dates, and plan the swap. ## Designing for the swap Because the *consumer* surface (your `maven-publish` publications, signing, POM metadata) is identical regardless of backend, encapsulate the **release backend** in a single **convention/precompiled script plugin**. Then migrating from the gradle-nexus tasks to a Portal publisher is one localized change instead of edits across every module's build script. Pin plugin versions, and verify against Sonatype's current docs since dates and endpoints have moved during the transition. ## What to verify before a real release - When was the namespace registered? That decides which backend it uses. - Are the staging tasks (`closeAndReleaseSonatypeStagingRepository`) still resolving against a live endpoint? - Have you tested a snapshot/dry-run before the irreversible Central promotion?
- Why might a freshly registered namespace not work with the gradle-nexus plugin at all?New namespaces are Central-Portal-native and may not expose the old Nexus staging open/close/release endpoints the plugin depends on.
- How would you architect a build to make swapping the release backend cheap?Put all release/staging wiring in one convention (precompiled script) plugin so the publishing surface stays stable and only that file changes when the backend does.
- What's the role of the Portal's OSSRH compatibility API?It mimics the legacy Nexus staging endpoints so existing tooling like the gradle-nexus plugin keeps working during the migration window.
saying these in an interview costs you the question
- Claiming the gradle-nexus plugin works unchanged for every Central namespace forever — Portal-native namespaces differ.
- Assuming OSSRH endpoints are permanent; they're on a deprecation timeline.
- Quoting specific cutover dates from memory instead of checking Sonatype's current docs.