Posts Tagged ‘maven-central’

Make your (automatic) releasing to Maven Central from Travis (and not only) more reliable thanks to the explicit staging repository creation feature set implemented at the edge of 2018 and 2019.


If you are only interested in getting information how to make your artifacts releasing more reliable from Travis, move forward to the another section.

Automatic artifacts releasing (using a staging repository and its promotion) from Gradle to Maven Central has been always tricky. The Nexus REST API related to those operations is very poorly documented. In addition, Gradle doesn’t natively support uploading artifacts to a dedicated staging repository even if it was already created explicitly. In the result a heuristic to determine which repository contains just uploaded artifacts has to be used, what brings some serious limitations. The apogee of the problems was to have Travis changes its architecture to more stateless in the late autumn of 2018. It caused the upload requests for particular artifacts to be routed via machines with different IP addresses, which resulted in multiple stating repositories created for a single gradle uploadArchives or gradle publish calls. That made automatic artifact releasing with Gradle from Travis completely broken. Up until now.



Two good things happened at the edge of the years. The first was the appearance of the new nexus-publish plugin by Marc Philipp. It creates an explicit staging repository using the Nexus API and enhance the Gradle publish task to use that repository. The second thing was an enhancement in my gradle-nexus-staging plugin which started to allow setting the staging repository ID which should be used during the release operation. That leaded to improve the reliability of releasing to Maven Central using Gradle.

Instead of relying on a heuristic to determine which repository should be used for release, the new staging repository is explicitly created. The artifacts are uploaded directly to it, it is closed and releasing. Thanks to that, everything works smother and it more error-proof. In addition, there is no problem with parallel releasing of different projects belonging to the same staging profile and it finally works properly back again with Travis.


This post assumes you have already configured uploading your artifacts to Maven Central (aka The Central Repository) using the maven-publish plugin. If not you may consult this link. This configuration will make your deployment and releasing more reliable without a need to do any manual operations in Nexus UI.

plugins {
    ... //other plugins used in your project
    id '' version '0.20.0'
    id '' version '0.2.0'

publishing {
    ... //your current publishing to Maven Central configuration

nexusStaging {
    packageGroup = "your-package-group-if-different-than-groupId"

nexusPublishing {
    //for custom configuration if needed - credentials
    //       are by default taken from nexus-staging
    //       or from properties nexusUsername and nexusPassword

Do you expect much more code (configuration) to write? Everything is hidden in the plugins which leverage each other. Just please remember to use nexus-staging 0.20.0+ and nexus-publish 0.2.0+.

After that artifacts uploading with releasing is a matter of one command:

./gradlew publish closeAndReleaseRepository

Calling the publish task (or publishToNexus for the older versions) creates a staging repository and memorized its ID. closeAndReleaseRepository closes and releases that one particular repository. After a few minutes your artifacts should be available in Maven Central.

Important. Bear in mind that publish (or publishToNexus) and closeAndReleaseRepository has to be used in the one Gradle execution to be able to leverage explicitly created staging repository.

Update 20190506. With nexus-publish 0.2.0+ calling just publish instead of publishToNexus is enough to trigger the logic, so the sample command was simplified.


Gradle is a very nice build tool where (almost) the sky is the limit. Unfortunately, there are still some long lasting issues which require using some hacks or writing custom plugins to overcome them. The promising is that with every release they are slowly fixed/implemented. To solve that particular problem a bottom-up work was required to bring releasing back for Travis and more reliable in general.

Please note. The presented approach works pretty well for using the (recently improved) publishing plugin. If you still use the old maven plugin (having the uploadArchives task instead of publish one) you need to migrate and/or put your comment in the corresponding issue.

The lead photo based on the Siala‘s work published in Pixabay, Pixabay License.

How to communicate with Maven Central/Nexus without using the password kept locally unencrypted (especially with Gradle, but not limited to it).


Unfortunately, Gradle (and many other build tools) does not provide any mechanism to locally keep passwords encrypted (or at least encoded). Without that even such a simple activity like showing your global Gradle configuration (~/.gradle/ to a colleague it uncomfortable, not to mention more serious risks associated with storing passwords on a disk in a plain-text form (see among others Sony Pictures Entertainment hack). It is Gradle, so with all Groovy magic under the hood it would be possible to implement an integration with a system keyring on Linux to fetch a password, but I’m not aware of any existing plugin/mechanism to do that and I would rather prefer not to write it.

Another issue is that nowadays, in the world of ubiquitous automation and cloud environments it is common to use API keys which allow to perform given operation(s). However, its lost doesn’t provide an attacker a possibility to hijack the account (e.g. token cannot be used neither to log into an administration panel nor to change of email or password which requires additional authentication).

It is very important if you need to keep valid credentials on a CI server to make automatic or even continuous releases. Thanks to my gradle-nexus-staging-plugin there is no need to do any manual steps in Nexus GUI to promote artifacts to Maven Central, so this was the next issue I wanted to deal with for my private and our FOSS projects in Codearte.

Nexus API key generation

Internet search for “maven central api key” wasn’t helpful, so I started digging into Nexus REST API documentation and I’ve found that in fact there is a (non widely known) way to generate and use an API key (aka an auth token).

0. Log into Nexus hosting Sonatype OSS Repository Hosting (or your own instance of Nexus).
1. Click on your login name in right-upper corner and choose “Profile”.
2. From the drop-down list with “Summary” text select “User Token”.
3. Click “Access User Token”.

Generating API key in Nexus

Generating API key in Nexus

5. Enter your password
6. Copy and paste your API username and API key (into your ~/.gradle/ file or a CI server configuration).
7. Work as usual with a little safer way.


It is good that using API keys is possible to deploy artifacts to Maven Central/Nexus and it is very easy to set it up. Someone could argue that the permission policy is coarse-grained (nothing or all operations except password/email change), but in my opinion it seems to be enough for the artifact repository system class. In addition, such an approach should work also with Sbt, Ivy, Leiningen and everything else that tries to upload artifacts into Maven Central (including Maven itself by removing limitations of the master password encryption with settings-security.xml). Hopefully, that post will make it widely known.

Quick tutorial how to promote/release artifacts in a Gradle project to Maven Central, without clicking in the Nexus GUI with Gradle Nexus Staging Plugin.


Maven Central (aka The Central Repository) is (probably) the world’s largest set of open source artifacts used by Java and JVM-based projects. It was founded by the creators of Apache Maven and it has been serving artifacts since 2002. Nowadays there are some alternatives (listed below), but for many users Maven Central is still the primary source of project dependencies (and sometimes the only one whitelisted in the corporations).

The Central Repository logo


To perform the release to The Central Repository, Maven users can use Nexus Staging Maven Plugin – free, but not fully open source plugin. But with Gradle it was required to login into Nexus GUI and manually invoke two actions (close repository and release/promote repository). Quite boring and in addition highly problematic with the Continuous Delivery approach. Luckily Nexus exposes REST API which with some work allows to do the same. Gradle Nexus Staging Plugin arose to do that job.

Quick start

Important. Please pay attention that the prerequisite is to have an active and configured account in Sonatype OSSRH (OSS Repository Hosting) as well as Gradle project configured to publish release artifacts to staging repository. If you don’t have it already please follow a separate section for Gradle in the official guide.

To setup automatic release/promotion in your project add gradle-nexus-staging-plugin to the buildscript dependencies in your build.gradle file for root project:

buildscript {
    repositories {
    dependencies {
        classpath ""

Apply the plugin:

apply plugin: ''

Configure it:

nexusStaging {
    packageGroup = "org.mycompany.myproject"
    stagingProfileId = "yourStagingProfileId" //when not defined will be got from server using "packageGroup"

After successful archives upload (with maven, maven-publish or nexus plugin) to Sonatype OSSRH call:

./gradlew closeRepository promoteRepository

to close staging repository and promote/release it and its artifacts. If a synchronization with Maven Central was enabled the artifacts should automatically appear into Maven Central within several minutes.


The plugin provides two main task:

  • closeRepository – closes the open repository with uploaded artifacts. There should be just one open repository available in the staging profile (possible old/broken repositories can be dropped with Nexus GUI)
  • promoteRepository – promotes/releases closed repository (required to put artifacts to Maven Central)

And one additional:

  • getStagingProfile – gets and displays staging profile id for a given package group. This is a diagnostic task to get the value and put it into the configuration closure as stagingProfileId. To see the result it is required to call gradle with --info switch.

It has to be mentioned that calling Nexus REST API ends immediately, but the closing operation takes a moment, so to make it possible to call closeRepository promoteRepository together there is a built-in retry mechanism.

The plugin is “upload mechanism agnostic” and can be used together with maven, maven-plugin or nexus plugins.

For more details and configuration parameters see project webpage or the working example in the plugin’s own release configuration.

Alternatives to Maven Central?

There is much younger, but promising alternative – Bintray which also allows to serve artifacts. It is free for open source projects and I personally had used it for some other projects and even created an automatic release mechanism for Bintray, Travis and Gradle. It works ok, but to put artifacts also to Maven Central it is required to store a private key used for singing on their servers and in addition provide Nexus credentials. It increases the risk to have them stolen and in Codearte we prefer to use private Jenkins instance to perform the release directly to Maven Central.


With Gradle Nexus Staging Plugin the whole release process to Maven Central can be performed with Gradle from a command line and with some additional work completely automatic from a CI server. No more buttons to push in Nexus GUI. In addition to Sonatype OSSRH the plugin can be also used with private Nexus instances with enabled staging repositories.

Btw, there possibly are many things that could be enhancement in the plugin. If you need something or found a bug feel free to use issue tracker to report that.

Thanks to Kuba Kubryński for motivation and help with analyzing the not very well documented Nexus REST API.

Update 20170904. The plugin is actively developed. Check the project webpage to read about new features added since version 0.5.1.