Bran van der Meer
Bran van der Meer

Reputation: 771

Clojure: how to make a leiningen build reproducible?

Introduction

As stated on reproducible-builds.org, it's a best-practice to be able to produce a build which can be re-created when given equal source code by anyone on any machine/os, at any time. How can I achieve this with a Clojure/Leiningen environment?

Example

Very basic example usage of creating a project and building a .jar file with Leiningen:

lein new app hello
cd hello
lein uberjar
sha256sum target/uberjar/hello-0.1.0-SNAPSHOT-standalone.jar

This outputs a certain sha256 hash, which contains non-determinism inside the .jar file. If you immediately re-run the build without changing any source files the checksum hash will be different anyway:

lein uberjar
sha256sum target/uberjar/hello-0.1.0-SNAPSHOT-standalone.jar

Question

How can I create a .jar file which results in the same checksum hash when run again, also for example on a different linux distro, somewhere in the future?

Upvotes: 2

Views: 262

Answers (2)

Bran van der Meer
Bran van der Meer

Reputation: 771

There's a package available for just this: strip-nondeterminism, it supports .jar files as well. It's available in debian and ubuntu (and probably other debian-based distro's), but you can always use it from source.

Install (debian/ubuntu/etc.):

sudo apt install strip-nondeterminism

Build:

lein uberjar
strip-nondeterminism -t jar target/uberjar/hello-0.1.0-SNAPSHOT-standalone.jar
sha256sum target/uberjar/hello-0.1.0-SNAPSHOT-standalone.jar

When the build is ran multiple times, this outputs the same checksum hash. It resets all file timestamps to a static value.

enter image description here

Upvotes: 1

akond
akond

Reputation: 16035

Jar file is not deterministic, but its content is. Try

unzip -c hello-0.1.0-SNAPSHOT-standalone.jar | md5sum

Upvotes: 4

Related Questions