Skip to content

Instantly share code, notes, and snippets.

@d-t-w
Created June 24, 2021 06:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save d-t-w/6cbdfb13d2d30d0059abe26447d5becb to your computer and use it in GitHub Desktop.
Save d-t-w/6cbdfb13d2d30d0059abe26447d5becb to your computer and use it in GitHub Desktop.
Leiningen Release Me!

I work on a Macbook Pro.

I use Leiningen for project automation and Git-Flow (AVH) for a sane Git branching model.

I do not sign my releases, I don't need to for our internal projects.

An Unexpected Party

My misadventure began when I upgraded Leiningen.

$ brew upgrade leiningen

All I wanted was have tests in .cljc files recognized by the test runner. The wheels fell off.

Leiningen has always had the ability to sign releases. I don't use it.

 :repositories [["releases" {:sign-releases false

The new Leiningen release process signs tags. This requires a series of tools to be installed and configured correctly, can't be hard.

My first thought was 'bugger that I don't want to sign tags', turns out I'm not the only one. Trumpets sound, our hero arrives. Turns out it's my old colleague Daniel Compton with a patch to Leiningen that disables the signing of tags. Good man.

Short quest that. Unfortunately the ability to --no-sign tags requires explicitly defining the release tasks for each project. I choose not to do that and forge onwards.

A Series of Holes

The Leiningen GPG guide gives perfectly good advice on installing gnupg, on creating a key-pair, and on configuring the public key for signing releases.

$ brew install gnupg

Done! I run my release process and it prompts me to enter my passphrase, easy beans. But wait, no input is accepted from the command-line but the enter-key? I repeatedly fail to enter my passphrase and sulk.

I climb from my hole to find some assistance within the Leiningen Deploy guide:

Due to a bug in gpg you currently need to use gpg-agent and have already unlocked your key

$ brew install gpg-agent

Done! With a little configuration (see: below) gpg-agent is configured and running.

Wait, gpg-agent isn't working? After configuring the error logs I note that it can't launch pinentry, after some digging I find that GPG-TTY must be set.

Done! Nearly. It turns out that the reason Leiningen requires gpg-agent is there is a bug that makes it hard to enter credentials via the same terminal window the release task is running in (I did manage it once).

At this point I verged off on a misadventure starting gpg-agent in a lenient mode and presetting the password (so that I would never be prompted, no pinentry required).

$ eval $(gpg-agent --daemon --allow-preset-passphrase)
$ /usr/local/opt/gpg-agent/libexec/gpg-preset-passphrase --passphrase my-passphrase --preset 81440C12501230BFDC9728FC3BFD789684305A6EE76

That works, but it's quite unpleasant. A better solution is to install pinentry-mac (which launches an application window) and configure gpg-agent to use that instead.

brew install pinentry-mac

Done! Now I am successfully signing tags as I release. Unfortunately at this point my release process failed because Leiningen and Git Flow were both generating tags that conflicted with each other, fortunately there's a straight forward solution to that (again, below).

TL;DR, Save Your Tears

Install gnupg, gpg-agent, pinentry-mac.

$ brew install gnupg
$ brew install gpg-agent
$ brew install pinentry-mac

Configure gnupg to use an agent (remove the leading #).

$ vi ~/.gnupg/gpg.conf

---

# We support the old experimental passphrase agent protocol as well as
# the new Assuan based one (currently available in the "newpg" package
# at ftp.gnupg.org/gcrypt/alpha/aegypten/).  To make use of the agent,
# you have to run an agent as daemon and use the option
#
use-agent

Configure the gpg-agent, most importantly to use pinentry-mac

$ vi ~/.gnupg/gpg-agent.conf

--- 

default-cache-ttl 600
max-cache-ttl 7200
pinentry-program /usr/local/bin/pinentry-mac
write-env-file /Users/derek/.gnupg/gpg-agent-info
log-file /Users/derek/.gnupg/gpg-agent.log

Create your key-per as per the Leiningen guide, configure your key per project if required.

Start the agent

$ eval $(gpg-agent --daemon)

Confirm you are in a happy place (a mac window will pop up asking for your password)

% echo "test" | gpg -ase                                                                                                                                                                           !10003

You need a passphrase to unlock the secret key for
user: "Derek Troy-West <derek@troywest.com>"
2048-bit RSA key, ID 55A6EE76, created 2016-04-15

At this point Leiningen will happily release, signing your tags (and more) via gnupg using gpg-agent.

The latest version of the Leiningen release task creates tags that conflict with Git Flow Release, you can configure Leiningen to prefix tags, or name Git Flow tags differently, but who wants to tag a release twice?

A better solution, provided by my colleague Mark Derricut, is to tell Git Flow to release without a tag.

$ git flow release start 1.0.18
$ lein release
$ git flow release finish -n
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment