How to Publish Your Open Source Library to Maven Central

Author, Scott Alexander-Bown

Author, Scott Alexander-Bown

by Scott Alexander-Bown

Introduction

Have you created a great (or at least useful) Java/Android open source project that you want to enable other developers use in their projects easily? Have you wondered how to publish your library to Maven Central? then this is the article for you!

One of the biggest wins when switching from Eclipse to Android Studio is the Gradle build system support, in particular dependency management is a lot easier. After including other developer’s libraries with a one line dependency it seems such an effort to go back to cloning or using submodules and then adding module to Android Studio. I even caught myself discounting good libraries if they I couldn’t include with a one line dependency and figured others might think the same for my libraries.

Example gradle dependencies block:

dependencies {

compile 'com.google.android.gms:play-services-wearable:6.5.+'

compile 'com.android.support:support-v13:21.0.+'

compile 'com.google.android.support:wearable:1.1.+'

}

Much of this article is based on the great work of Chris Banes, his blog post and gradle script and some help from @chrisjenx and using his successful Calligraphy library as a guide. I’m using two of my own small open source libraries as examples in this article https://github.com/scottyab/AESCrypt-Android and applying the similar steps to https://github.com/scottyab/secure-preferences.

JITPACK.IO

But wait! Before you start there could be a quick win if you already use releases in your github repo. You can avoid all this registering and publishing and use a new service that’s still in beta called jitpack.io  – I found this after I’d written this article – typically wink

 

Step 1. Add the JitPack repository to your build file

repositories {

maven {

url "https://jitpack.io"

}

}

 

Step 2. Add the dependency in the form

dependencies {

compile 'com.github.User:Repo:Tag'

}

That’s it! The first time you request a project JitPack checks out the code, builds it and sends the Jar files back to you.

Let’s begin…

1. GRADLE PROJECT THAT BUILDS OK

This assumes you have an open source* gradle based project that builds successfully. 

*I say open source as that’s a requirement for the free hosting. Commercial host is also available at bintray.com. Alternatively here’s some guides on host on Amazon S3 or Github pages.

 

2. SETUP

There are a few accounts and keys to set up the first time through this, but once it’s done you can upload a new version from the ‘uploadArchives’ gradle task. Also adding additional libraries is simple assuming you’re ok with the same groupId.

Tip: make your groupId generic, I used com.scottyab so I could reuse for several of my open source projects, I think this is allowed/standard.

 

CREATE SONATYPE.ORG ACCOUNT

Register account with https://issues.sonatype.org/secure/Signup!default.jspa and add your username and password info to your ~/.gradle/gradle.properties file as shown below

#sonatype login

NEXUS_USERNAME=scottyab

NEXUS_PASSWORD=mypassword

We add it to  ~/.gradle/gradle.properties as this is a local file that it visible to your gradle projects but crucially it cannot be accidently checked in to source control. I’d also make a backup of your login details in your favourite password manager like1Password.

NEW GROUP JIRA TICKET

Create a ticket for your new open source library on sonatype’s JIRA board. In the ticket define groupId, name, details, repo url, website url etc. I chose com.scottyab as mentioned above in the introduction so I can use for other projects. They responded and created mine within a couple of hours. Once created you should see in the ticket details your snapshot and release repos:

Add these to your ~/.gradle/gradle.properties file

SNAPSHOT_REPOSITORY_URL=https://oss.sonatype.org/content/repositories/snapshots

RELEASE_REPOSITORY_URL=https://oss.sonatype.org/service/local/staging/deploy/maven2

CREATE A NEW PGP KEY

To release an open source lib to Maven central it will need to be signed and subsequent releases will need to be signed with the same key. Useful guide from sonatype here explains all the steps in more detail.

$gpg2 --new-key

Enter your email (same as the account you registered with sonatype.org) and other details gpg prompts for. Once complete gpg will print the new key’s details.

*Updated* Orhan Obut kindly pointed out that you may have to manually export the secring.gpg file.

 gpg2 --export-secret-keys > secring.gpg

ADD KEY DETAILS TO GRADLE.PROPERTIES

You can list your current  keys:

$gpg2 --list-keys me@mydomain.com

Sample output

ub   2048R/A2AAD1B1 2015-03-05

uid                  Name (comment) <me@mydomain.com>

sub   2048R/A2AAD1B2 2015-03-05

The part you want is “A2AAD1B1” the key id. Add this info to your  ~/.gradle/gradle.properties together with password and link to secring.gpg file (typically ~/.gnupg/secring.gpg). Note this is the gradle.properties file in your home directory and should not be pushed to source control. That said you should have a backup of the file/directory in case of disk failure or some other disaster.

For example:

#Artifact signing key

signing.keyId=A2AAD1B1

signing.password=your pgp key password

signing.secretKeyRingFile=/Users/<username>/.gnupg/secring.gpg

 

SEND KEY TO KEY SERVERS

To enable the sonatype servers to verify the key, the public key needs to be sent to the standard key servers. Remember to use your key ID that you created above.

gpg2 --keyserver pgp.mit.edu  --send-keys A2AAD1B1

 

3. CHANGES TO YOUR PROJECT

Now we’re gonna add/tweak some of the build config files in your project. This is detailed in the readme of Chris Banes’gradle-mvn-push project.

PROJECT ROOT LEVEL

gradle.properties

Create a gradle.properties at the root level of project, that contains

VERSION_NAME=1.0.0-SNAPSHOT

VERSION_CODE=2

GROUP=com.scottyab

As well as POM details with links to your repo source and web pages.

build.gradle

Add the following as I have here

def isReleaseBuild() {

return version.contains("SNAPSHOT") == false

}

allprojects {

version = VERSION_NAME

group = GROUP

repositories {

mavenCentral()

}

}

MODULE LEVEL

gradle.properties

In your each app/lib module create another gradle.properties

build.gradle

Add the following to each module you wish to upload as shown here

apply from: 'https://raw.github.com/chrisbanes/gradle-mvn-push/master/gradle-mvn-push.gradle'

 

4. UPLOADING A SNAPSHOT (OPTIONAL)

In the terminal change to the root of your project and run the following

$./gradlew clean build uploadArchives

The terminal will show a bunch of build output messages. You should see the uploadArchives task print out the url and progress of uploads.

Example output:

:aes-crypto:uploadArchives

Uploading: com/scottyab/aescrypt/0.0.1-SNAPSHOT/aescrypt-0.0.1-20150311.140631-1.aar to repository remote at https://oss.sonatype.org/content/repositories/snapshots

Transferring 13K from remote

Uploaded 13K

You can also check everything went ok by browsing to the location. i.e https://oss.sonatype.org/content/groups/public/com/scottyab/aescrypt/0.0.1-SNAPSHOT/

TESTING

You can and should test the snapshot by including the snapshot repo by adding the snapshot build to a dependent project. To do this add the following to your build.gradle file

repositories {

mavenCentral()

maven {

url "https://oss.sonatype.org/content/repositories/snapshots"

}

}

Then in your dependencies reference the snapshot version.

dependencies {

compile fileTree(dir: 'libs', include: '*.jar')

...

compile 'com.scottyab:aescrypt:0.0.1-SNAPSHOT'

}

Build app, run tests etc and if everything works a-ok then move to release.

 

5. UPLOADING A RELEASE

 

Once again ensure your release repo is set (this is noted in the jira ticket)

RELEASE_REPOSITORY_URL=https://oss.sonatype.org/service/local/staging/deploy/maven2

Change the VERSION_NAME in the root/gradle.properties file to not include the “SNAPSHOT”, i changed to 0.0.1.

Then run the same command as before:

$./gradlew clean build uploadArchives

Again you should see messages in the console saying each of the artifacts uploaded ok.

 

6. MOVING TO RELEASE

The previous step uploads the release to the staging area now it’s time to flag it in sonatype.org’s system to allow it to be moved to release. You aren’t granted direct access to upload to releases. The official documentation for this step ishere.  Login to https://oss.sonatype.org

Search for your library name and scroll down the stagingRepositories until you see your library. In my case aescrypt-1000 –https://oss.sonatype.org/index.html#stagingRepositories

Select it and click the close option. You should get an email from Nexus Repository Manager  to say “staging complete”

Hit refresh, once it’s refreshed and shows as closed you can select the ‘release’ button.

Once it’s successfully released you should get an email from Nexus Repository Manager  to say “Promotion Completed”

Once the guys at sonatype.org have activated the sync, you should be able to search on maven central like thishttps://search.maven.org/#search%7Cga%7C1%7Caescrypt.

It should also be available using the handy tool http://gradleplease.appspot.com/

 

UPDATE YOUR README

After all this hard work you should let your library users know by updating your readme with the new dependency options.

DON’T FORGET

If you are releasing the first time, do not forget to comment on the Jira tracker ticket, letting sonatype know that you have completed a release. This is for them to activate some kind of sync process. I totally missed this at first and wondered why I couldn’t see the published version.

 

ALL DONE!

That’s it you’re done you can bask in the glory of knowing not only have you made an open source library but you are enabling fellow developers to integrate your library with a one liner. e.g compile ‘com.scottyab:aescrypt:0.0.1’

You Rock!

 

The following two tabs change content below.
Scott is a senior Android developer at Intohand and co-author of the Android Security Cookbook. He is also the founder of SWmobile, a mobile developer-focused Meetup group which runs tech talks, networking and hacking events.

Latest posts by Scott Alexander-Bown (see all)

Related posts

4 Comments

  1. Denis Kniazhev said:

    Nice article. Not sure what pgp2 version are you using, there is no `–new-key` option in 2.0.22. Should it be `–gen-key`?
    Also, you suggest registering on oss.sonatype.org, but there is no “Register” button there. What user needs is to register on Jira and use his/her Jira account to log into oss.sonatype.org. Same Jira credentials should be used in ~/.gradle/build.gradle

    • Scott Alexander-Bown said:

      Yes, you are correct, gpg2 version 2.1+ you have to use –gen-key and also there is no longer secring.gpg file, in order to create this, it must be exported. Thanks This was noted by Orhan Obut on the original posting on intohand.com.

      -> gpg2 –gen-key // create a new key
      -> gpg2 –export-secret-keys > secring.gpg

*

Top