Deploy Clojure Projects to Maven Central with Leiningen

Wednesday, June 30th 2021 by Thomas Crowley

This article dives into deploying Clojure projects to Maven.

Maven Central and Clojure =========================

We have just released our first open-source consumable: kpow-streams-agent, a monitoring tool for Kafka Streams, to Maven Central.

The Kpow Streams Agent integrates your Kafka Streams topologies with Kpow, offering near-realtime monitoring and visualisation of your streaming compute:

We intend for this software to be used by the wider JVM ecosystem (eg, Java, Kotlin, Scala), so would like our library to be available on Maven Central.

There weren't many resources online documenting anyone's experience deploying Clojure-centric software to Maven Central and the few resources that I came across were out of date with the current requirements (as of June 2021).

This blog post documents the steps needed to make your Clojure code available to a wider audience.

Create a Sonatype account


The entire process for claiming your own namespace on Maven Central starts with creating a JIRA ticket. This seemed a bit archaic to us, coming from Clojars, NPM, and Crates.io backgrounds. Certainly, with these modern package managers, the integration between language/ecosystem/registry seems a lot more streamlined, thus publishing software much easier.

We weren't sure if this would be an automated process or if we would have to wait for a human to manually approve our request. We were relieved that it was indeed somewhat automated, with a bot automatically approving each step.

Sign up to JIRA


The first step is to create an account on the Sonatype JIRA.

The credentials you provide here will also be the same credentials you use to deploy, so keep that in mind as you proceed

Create a new ticket


Once you have signed up for the JIRA, create a new ticket and choose the issue type "New Project".

This is where you claim your group.id on Maven Central. This must be related to a website domain you own. For us, we claimed io.operatr as our companies domain is operatr.io. You will need to prove ownership of your domain for the next section.
Creating a Sonatype JIRA ticket

Add a TXT entry to your domain


Once you have submitted your JIRA ticket, a bot should automatically reply to your issue within a few minutes asking for verification of your domain. The simplest way to verify your domain is to create a TXT entry.

For example, if you use Cloudflare to manage your DNS records you could follow these steps to add a TXT entry to your domain.

You will need to create a TXT entry containing the Jira issue ID of your ticket (for example OSSRH-70400)

Once you have added the TXT entry to your domain, the bot should automatically reply and confirm that your group.id has been prepared

Deploy Requirements


You will now be granted the ability to deploy snapshot and release artifacts to s01.oss.sonatype.org for the group.id you have just registered.

All artifacts you deploy here are staged and can only be promoted to Maven Central if they meet the requirements.

This section will document how you can configure your project.clj to meet the Sonatype requirements

GPG Keys

Firstly, we want to create a GPG key to sign our release. Lein's GPG Guide is a good starting place on how you can do that.

Once you have created your GPG key you will need to upload your public key to a keyserver, such as https://keyserver.ubuntu.com/

In order to do this, you can export your GPG public key with the following command:

gpg --armor --export $MY_EMAIL

Credentials

Next, you will need to update your ~/.lein/credentials.clj file to include your Sonatype credentials:

{#"https://s01.oss.sonatype.org/.*" {:username "JIRA_USERNAME" :password "JIRA_PASSWORD"}}

Once you have created credentials.clj you will need to encrypt it:

gpg --default-recipient-self -e \
    ~/.lein/credentials.clj > ~/.lein/credentials.clj.gpg

Finally, you will need to setup the correct :deploy-repositories within your project's project.clj:

  :deploy-repositories [["releases" {:url   "https://s01.oss.sonatype.org/service/local/staging/deploy/maven2/"
                                     :creds :gpg}
                         "snapshots" {:url   "https://s01.oss.sonatype.org/content/repositories/snapshots/"
                                      :creds :gpg}]]

Source and Javadoc Jars

It is a requirement to include both a -sources.jar and -javadoc.jar jar as part of your deployment.

These requirements are tailored more towards Java codebases than Clojure:

If, for some reason (for example, license issue or it's a Scala project), you can not provide -sources.jar or -javadoc.jar , please make fake -sources.jar or -javadoc.jar with simple README inside to pass the checking

You can create -sources.jar and -javadoc.jar jars by using a :classifiers key in lein:

  :classifiers [["sources" {:source-paths      ^:replace []
                            :java-source-paths ^:replace ["src/java"]
                            :resource-paths    ^:replace []}]
                ["javadoc" {:source-paths      ^:replace []
                            :java-source-paths ^:replace []
                            :resource-paths    ^:replace ["javadoc"]}]]

This specific example will bundle Java source code in the sources jar, and Java docs in the javadoc jar.

If you intend to create "fake" source jars, you could leave the source paths and resource paths empty.

Project Details

In order to meet the Project name, description and URL requirements, you will need to correctly populate the following keys in project.clj:

  :description "A Clojure project deployed to Maven"
  :url "https://github.com/org/repo"

License Information

In order to meet the License information requirement you will need to correctly populate the :license key in project.clj:

  :license {:name         "Apache-2.0 License"
            :url          "https://www.apache.org/licenses/LICENSE-2.0"
            :distribution :repo
            :comments     "same as Kafka"}

Developer Information

In order to meet the Developer Information requirement you will need to correctly structure your :pom-additions key in project.clj like so:

  :pom-addition ([:developers
                  [:developer
                   [:id "johnsmith"]
                   [:name "John Smith"]
                   [:url "https://mycorp.org"]
                   [:roles
                    [:role "developer"]
                    [:role "maintainer"]]]])

SCM Information

In order to meet the SCM Information requirement, you will need to correctly populate the :scm key in project.clj like so:

:scm {:name "git" :url "https://github.com/org/repo"}

Deploying to Central


If you have followed all of the steps from the previous section, you should have a lein project that meets all Sonatype requirements and is ready to be deployed!

You can do this via a regular:

lein deploy

Once you have deployed your artifacts, the next step is to log in to the Nexus Repository Manager at https://s01.oss.sonatype.org/. Again, your JIRA credentials from before are used to log in.

Once inside the, navigate to "Staging Repositories" - you should see an entry labeled XXX-1000.

Click on this item and verify that the contents you wish to deploy to Central are present.

If everything looks good, click the "Close" button. This will trigger the requirements check
The Nexus Repository Manager

If the requirements check passes, you will be able to press the "Release" button. Once you press this button, your release will shortly be synced with Maven Central!

Note : It can take up to 4 hours for the sync with https://search.maven.org/

Further Reading and References

The following resources might be useful for more information about deployments:


Enjoy this article?

Sign-up to the mailing list for operatr.io news, product updates and Kafka insights.

[activecampaign form=30]


Manage, Monitor and Learn Apache Kafka with Kpow by Factor House.

We know how easy Apache Kafka® can be with the right tools. We built Kpow to make the developer experience with Kafka simple and enjoyable, and to save businesses time and money while growing their Kafka expertise. A single Docker container or JAR file that installs in minutes, Kpow's unique Kafka UI gives you instant visibility of your clusters and immediate access to your data.

Kpow is compatible with Apache Kafka+1.0, Red Hat AMQ Streams, Amazon MSK, Instaclustr, Aiven, Vectorized, Azure Event Hubs, Confluent Platform, and Confluent Cloud.

Start with a free 30-day trial and solve your Kafka issues within minutes.


<br />

Tags:

Clojure
Maven