Skip to content

Instantly share code, notes, and snippets.

@wavejumper
Last active Jun 27, 2021
Embed
What would you like to do?
lein.md

Deploying to Maven Central with Clojure+Leiningen

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

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, so this blog post documents the steps needed to get deploying!

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

ticket template

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 do this is to create a TXT entry inside of your domain.

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 to 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

Close

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/

References

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment