Deploying libraries with deps.edn

I’ve had a number of questions about uploading libraries to maven and clojars with pack. This is a tutorial on how to go about that.

Generate a pom.xml

Generate a pom.xml using clojure -Spom.

You must update this file with coordinates and an appropriate version. To update your coordinates in the pom.xml, you need to update the existing groupId, artifactId and version tags to match. This example is equivalent to {com.acme/anvil {:mvn/version "0.1.0"}} in deps.edn.

<groupId>com.acme</groupId>
<artifactId>anvil</artifactId>
<version>0.1.0</version>

You should add repository information. This will enable tools like https://cljdoc.org/ to generate documentation for your library. Put this inside the <project> tags and update the links.

Example from cljdoc’s documentation
<scm>
  <connection>scm:git:git://github.com/laforge49/aatree.git</connection>
  <developerConnection>scm:git:ssh://git@github.com/laforge49/aatree.git</developerConnection>
  <tag>edb7cefa9a01852b101ed742b278aaba8d832b02</tag>
  <url>https://github.com/laforge49/aatree</url>
</scm>

Install the pack alias

Run this command to add the pack alias to your deps.edn.

$ clojure -Sdeps '{:deps {pack/pack.alpha {:git/url "https://github.com/juxt/pack.alpha.git" :sha "dccf2134bcf03726a9465d2b9997c42e5cd91bff"}}}' -m mach.pack.alpha.inject 'd9023b24c3d589ba6ebc66c5a25c0826ed28ead5'

You may want to adjust the formatting afterwards.

Build your JAR

Pack provides a mode named "skinny jar". This was originally designed for companies who deploy by uploading their classpath separately from their project. But it has a flag to not output the classpath at all, just a jar containing your project files. This separation can be used to create a jar that is suitable for upload to clojars.

$ clojure -A:pack \ (1)
          mach.pack.alpha.skinny \ (2)
          --no-libs \ (3)
          --project-path anvil.jar \ (4)
1 Load the pack alias, which will run the selected pack mode
2 Select the skinny mode of pack
3 Don’t output libs
4 Specify the name of your jar. Here, I selected "anvil.jar".

Release the JAR

You have 2 options at this point, mvn or deps-deploy. mvn has a sometimes better story around encryption of credentials, and is well established. deps-deploy avoids having to install mvn, but is still very new.

mvn approach

You will need to set up your ~/.m2/settings.xml in order to add authentication information for your upload destination.

Example settings.xml for Clojars
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0
  https://maven.apache.org/xsd/settings-1.0.0.xsd">
  <servers>
    <server>
      <id>clojars</id>
      <username>wil_e_coyote</username>
      <password>r04drunn3R$</password>
    </server>
  </servers>
</settings>
The above example leaves your password in plaintext on your filesystem. I highly recommend utilising maven’s password encryption.

Now you are ready to upload your JAR and pom.xml to upstream using mvn deploy:deploy-file.

Upload to clojars
$ mvn deploy:deploy-file \
      -Dfile=anvil.jar \ (1)
      -DrepositoryId=clojars \
      -Durl=https://clojars.org/repo \
      -DpomFile=pom.xml

[INFO] Scanning for projects...
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] Building anvil 0.1.6
[INFO] ------------------------------------------------------------------------
[INFO]
[INFO] --- maven-deploy-plugin:2.7:deploy-file (default-cli) @ anvil ---
Uploading: https://clojars.org/repo/com/acme/anvil/0.1.6/anvil-0.1.6.jar
Uploaded: https://clojars.org/repo/com/acme/anvil/0.1.6/anvil-0.1.6.jar (780 B at 0.3 KB/sec)
Uploading: https://clojars.org/repo/com/acme/anvil/0.1.6/anvil-0.1.6.pom
Uploaded: https://clojars.org/repo/com/acme/anvil/0.1.6/anvil-0.1.6.pom (980 B at 0.4 KB/sec)
Downloading: https://clojars.org/repo/com/acme/anvil/maven-metadata.xml
Downloaded: https://clojars.org/repo/com/acme/anvil/maven-metadata.xml (439 B at 0.8 KB/sec)
Uploading: https://clojars.org/repo/com/acme/anvil/maven-metadata.xml
Uploaded: https://clojars.org/repo/com/acme/anvil/maven-metadata.xml (470 B at 0.2 KB/sec)
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 8.475 s
[INFO] Finished at: 2018-11-18T13:18:06+00:00
[INFO] Final Memory: 12M/317M
[INFO] ------------------------------------------------------------------------
1 Replace this with the name of your jar.

Deps Deploy

slipset has made a wonderful clojure library named deps-deploy.

You can add an alias for it in your deps.edn:

{:aliases
 {:pack {…}
  :deploy {:extra-deps {deps-deploy {:mvn/version "RELEASE"}}
           :main-opts ["-m" "deps-deploy.deps-deploy" "deploy" "anvil.jar"]}}

Then you can invoke it:

$ export HISTFILE=/dev/null (1)
$ CLOJARS_USERNAME=wil_e_coyote CLOJARS_PASSWORD='r04drunn3R$' clojure -A:deploy

SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
SLF4J: Defaulting to no-operation (NOP) logger implementation
SLF4J: See http://www.slf4j.org/codes.html#StaticLoggerBinder for further details.
Deploying com.acme/anvil-0.1.4 to clojars as Smeagol
done.
1 This is to disable history from storing your username & password in plaintext.

Example

There’s an example at https://github.com/SevereOverfl0w/super-duper-octo-barnacle. You can update the groupId in the pom.xml and deploy it as a test to your own groupId.

Published: 2018-11-27

Privacy policy

Speccing out routes fky
by Frankie Sardo
Published: 2016-07-27
Attending the ClojuTre conference jon
by Jon Pither
Published: 2015-09-18
A Clojure heavyweight jon
by Jon Pither
Published: 2016-09-22