Managing Local and Project-wide Development Parameters in Leiningen
Little tip. Long headline.
In any project there are often settings that are specific to the
context the project is run in (think of an
environment
parameter) and then there are parameters
that are specifc to the developer/workstation they're run on. This
is a guide to separate these two things nicely in Leiningen-based
Clojure projects.
So you have a project setup that uses
environ to
determine the context the project is run in (development
vs. production
).
; in project.clj:
(defproject your-app "0.1.0-SNAPSHOT"
; ...
:profiles {:dev {:env {:environment "development"}}})
Now you also want to use environment variables (or anything else
thats supported by environ) to store AWS credentials to access
Amazon S3. You don't want to commit these credentials into version
control, therefore you can't add them to project.clj
.
The way to go is to create a file profiles.clj
in
your project to store workstation specific information. Naively
this could look something like this
{:dev {:env {:aws-access-key "abc"
:aws-secret-key "xyz"
:s3-bucket "mybucket"}}}
If you run your project with this profiles.clj
you
will be able to access your AWS credentials. You might also notice
that `(environ/env :environment)` is nil.
That wasn't intended.
The problem here is that Leiningen will override keys in profiles
defined in project.clj
if
the same profile has also been defined in
profiles.clj
. To recursively merge Leiningen profiles
combine them like so:
;; in project.clj:
(defproject your-app "0.1.0-SNAPSHOT"
;; ...
:profiles {:dev [:project/dev :local/dev]
:project/dev {:env {:environment "development"}}})
;; in profiles.clj
{:local/dev {:env {:secret-key "xyz"}}}
Now both, :envrionment
and
:secret-key
should be defined when you retrieve them
using environ.
This is largely inspired by James Reeves' duct Leiningen template.