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.
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
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:
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.