As a counterbalance to an imminent JCenter shutdown, get know the unified (and united) power of releasing to Maven Central with a brand new Gradle Nexus Publish Plugin. A migration guide from the old plugins is included.
2 big things in Q1 2021
The beginning of 2021 electrified the JVM ecosystem by an unexpected decision of the fast upcoming shutdown of JCenter , a quite popular place to keep FOSS projects’ binary artifacts. Business is for making money, not for supporting the community that helped the company got to the successful IPO a few months earlier, so the need “to streamline the productivity of the JFrog Platform” has to be understood.
As a (positive) side effect, I and Marc Phillip streamlined our focus to release a stable version of our unified Gradle plugin for publishing projects to Maven Central. 1.0.0 hit the repository soon after. That version provides an initial set of functionality which should allow the majority of the Gradle projects to publish artifacts to Maven Central (aka The Central Repository).
A story of three plugins
In 2015, I
created gradle-nexus-staging-plugin
which was providing - not available earlier for the Gradle users - an ability to close and release staging repositories in Nexus repository manager without touching Nexus UI. It opened an opportunity to manage releasing Gradle projects to Maven Central completely from code (also using a CI server). Over the years, it has been adopted by the various projects and companies across the globe
, however there was a small problem. Due to technical limitations in the publishing process in Gradle, it was required to use heuristics to track implicitly created staging repositories, what often failed for multiple repositories in a given state. The situation became even worse when Travis changed its network architecture in late 2019 and the majority of releases started to fail.
Here, Marc Philipp
entered the stage who created Nexus Publish Plugin
which was enriching the publishing mechanism in Gradle to explicitly create staging repositories and publish (upload) artifacts directly to it.
Those two plugins nicely worked together, providing a reliable way to handle publishing artifacts to Maven Central (and to other Nexus instances in general). However, the need of using two plugins was very often confusing for users. As a result, an idea to create one plugin mixing the aforementioned capabilities emerged. It took us some time, but sunsetting JCenter motivated us to intensify work and Gradle Nexus Publish Plugin 1.0.0 has been released in February 2021 as joint effort.
Migration guide
The new plugin was intended as a natural successor of the aforementioned two plugins. We tried to keep the syntax unchanged where feasible. As a result a migration guide - in the majority of cases - is straightforward.
Plugins
Let’s start with the plugins declaration.
plugins { //old
id "io.codearte.nexus-staging" version "0.22.0"
id "de.marcphilipp.nexus-publish" version "0.4.0"
}
The old two has to be replaced with the new one:
|
|
Configuration - simple case
If only default plugins settings were used:
nexusStaging { //old
packageGroup = "com.example.mycompany.myproject"
stagingProfileId = "yourStagingProfileId"
}
nexusPublishing {
repositories {
sonatype()
}
}
packageGroup
and stagingProfileId
have to be moved to the nexusPublishing
section:
|
|
Due to the improved support for releasing to multiple Nexus instances in one project, the credentials configuration has changed in non-backward compatible way. gradle-nexus-staging-plugin by default was using nexusUsername
and nexusPassword
project properties which could be reused by nexus-publish-plugin. With the new plugin it has been unified to sonatypeUsername
and sonatypePassword
, where a prefix reflects a name of a configured repository (here sonatype
).
Configuration - more customizations
Having more customizations in place:
//majority of the properties is optional, you might just don't have them in your project //old
nexusStaging {
packageGroup = "com.example.mycompany.myproject"
stagingProfileId = "yourStagingProfileId"
//by default project properties 'nexusUsername' and 'nexusPassword' are used
username = project.findProperty("...")
password = project.findProperty("...")
numberOfRetries = 40
delayBetweenRetriesInMillis = 3000
}
nexusPublishing {
repositories {
sonatype {
//by default value from above 'nexusStaging' closure is used (alternative project properties 'sonatypeUsername' and 'sonatypePassword')
username = project.findProperty("...")
password = project.findProperty("...")
}
}
clientTimeout = Duration.ofSeconds(300)
connectTimeout = Duration.ofSeconds(60)
}
they also have to be moved to the nexusPublishing
closure:
|
|
It is worth to mention - in addition to changed default project properties to read credentials from - that the configuration of retries during the close and release attempts has been renamed to transitionCheckOptions
with more modern duration types.
Tasks - simple case
At the task level - due to support for multiple repositories - the following common execution:
./gradlew publish closeAndReleaseRepository //old
has to be enhanced with a repository name:
./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository
To short the second task name slightly, there is still a simplified variant closeAndReleaseStagingRepository
which closes and releases the staging repositories in all configured Nexus instances (one by default).
Summary
For the new projects, using gradle-nexus-publish-plugin is the only logical choice. The main authors’ effort will be put in its development. The whole process of onboarding to Soantype Nexus (together with a sample project) is nicely described by Rob Winch .
For the projects migrating from releasing from JCenter to Maven Central - I plan to cover it in a separate blog post - it also holds.
I hope this short blog post clearly showed that migration - in the majority of cases - from the old due-solution should be trouble-free. All the projects should - eventually - migrate to the new plugin.
For existing projects, temporary staying with the already working (old) duo-solution also is an acceptable choice. The migration might wait for the next big configuration change in the project (e.g. a migration to Gradle 7). The new plugin is less mature and there might be some features missing. In that case, however, please let us know !
Lead photo by TheDigitalArtist, published in Pixabay, Pixabay License.