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.