Publish Your First Artifact to Maven Central Using GitHub Actions

A step-by-step guide to the process of publishing artifacts in Maven Central

Anurag Ashok
5 min readFeb 26, 2021
a
Photo by Ferenc Almasi on Unsplash

I recently published a post on how to record response time with wiremock. Later, I created a java library out of it and published it on Github.

I wanted to go a step further and publish the build artifacts to maven central. Fellow developers can then use them without building from source code. Some changes were needed for the project to be accepted to maven central. This post summarizes these changes and the process of automation using Github Actions.

Overall Process

The artifacts cannot be pushed to maven central directly. They first need to be deployed to the Sonatype OSSRH (OSS Repository Hosting) staging repository. Releasing from OSSRH to the maven central can then be initiated manually or via a maven plugin (more on that later). Before release, various checks are done against the project and artifacts to ensure they meet the standards of maven central. The artifacts are synced to maven central only if all the checks pass.

The detailed steps for meeting the standard and publishing are as follows.

1. Create a project and request access to maven central.

Most importantly, you need an account, a project, and permission to publish to OSJRH. You will need to create an account on Sonatype JIRA and then request to create your project via a new JIRA ticket. You can also clone, edit and submit the Jira ticket I created — OSSRH-64328.

The group-id should follow Maven naming conventions and be the reverse of a domain you own. For projects hosted on GitHub, it can start with com.github or io.github.

The folks at sonatype were very quick in their responses and asked to create a repository on GitHub with the Jira ID as the name to verify ownership of the GitHub account. Once ownership was verified, they quickly prepared the group for publishing and deployment to the staging repository.

2. Signing Artifacts / GPG setup

One of the requirements is that the artifacts are signed with GPG. To do this, you first need to create a GPG key using the command `gpg — gen-key` or tools like GnuPG. You will need to enter a few details and a passphrase to remember.

Once the keys are created, you need to sync the public keys with popular gpg key servers. You can synchronize the keys by retrieving the public key and then sending it to the keyservers.

Example:

Once the public key is sent to one of the keyservers, it is automatically, but not immediately, synchronized with the other keyservers. You can also send it manually to the most common servers instead of waiting for synchronization. The most common servers are:

hkp://pool.sks-keyservers.net
https://pgp.key-server.io/
https://keyserver.ubuntu.com/
https://pgp.mit.edu/
http://keys.gnupg.net/

You can read more detailed instructions on the sonatype page on pgp signatures.

Once the GPG key is created, you need to add the following plugin to your pom to sign the artifacts.

The pinentry-mode=loopback specification is necessary for automated builds. It tells GPG not to ask for the passphrase to be entered manually. We’ll see how to provide the passphrase when we set up GitHub actions.

3. Adding metadata to the POM

Artifacts must have a minimal set of metadata before they are eligible for release to Maven Central. The metadata includes fields such as developer name, SCM URLs, licenses, etc. You can find the full list and details on the sonatype requirements page. You can also reference the pom of my project.

4. Generate JavaDoc and sources jar.

Maven central also requires us to generate the JavaDoc and sources jar for consumer use. This is mandatory for projects with a packaging type other than pom. You can generate this by adding and configuring their respective Maven plugins to your pom.

You can also see the plugins section in my project.

5. Prepare POM for deployment

You need to add the URL of the distribution repository to the pom of the project. In this case, we add the staging repository as the distribution repository.

By default, the staged artifacts must be manually from the sonatype next staging website. However, this can be automated by adding the nexus-staging-maven-plugin to the project pom.

After the artifact is deployed to the staging repository, the plugin attempts to release the artifact. If any of the checks/requirements for release are not met, the build also fails. The plugin also outputs the list of unmet requirements.

6. Automate deployment to staging and release using GitHub Actions

I use GitHub Actions as a CI CD tool. The workflow code is as follows.

This workflow is triggered when I push a new tag. The workflow then builds the artifact, creates a GitHub release, and then deploys it to the staging repository. The ‘nexus-staging-maven-plugin’ added in the pom automatically releases the staged artifact when all checks pass.

The workflow requires a few secrets to be provided via the repository settings. More details can be found on the GitHub action pages. The following secrets need to be added.

OSSRH_USERNAME : the username for the sonatype Jira login

OSSRH_PASSWORD: the password for the sonatype Jira login

OSSRH_GPG_SECRET_KEY: gpg private key ( gpg --armor --export-secret-keys YOUR_KEY_ID )

OSSRH_GPG_SECRET_KEY_PASSWORD : gpg passphrase

7. Enable synchronization after first release.

This step is only needed on the first release. You need to inform the sonatype team via a comment on the project creation JIRA ticket when you release your first artifact. The sonatype team then enabled sync to maven central for the project. Once that is done, the artifact appears in maven central in about 10 mins and on the search page in a couple of hours.

The entire process for publishing on Maven Central seems long and complex, but most of these steps are one-time. Automating the rest with a CI CD tool makes publishing subsequent versions trivial.

You can reference my project wiremock-extension-record-delay for the complete setup.

--

--

Anurag Ashok

building software @ Singapore Airlines | making code work for 8+ years | passionate about automation and “everything as code”.