Introducing Env Lint
We've been following the
12 factor approach of configuring our
Rails apps through environment variables. Tweaking options through
env:set task provided by
recap feels much more light weight
than manually fiddling with
yml files on the server. Moreover, the
dotenv gem makes controlling
your development environment very comfortable. While the
itself is not checked into version control, there is a
file which acts as a starting point for new developers and documents
the available options.
Still, there were some pain points left:
Whenever new variables were added to the app's configuration, the process of updating the staging and production environments turned out to be rather error prone. Even having carefully compared the lists of defined variables, only after booting the newly deployed app could one be sure that nothing was missing.
This was even harder as small spelling errors in variable names either in the code or on the command line were easy to miss.
.env.examplefile would quickly become outdated, incomplete or simply incorrect.
To resolve all of these issues we came up with the env_lint gem, which is comprised of three components:
A wrapper around
LintedEnvwhich fails loudly whenever variables are not defined or misspelled variable names are used.
A capistrano task to verify all required environment variables are defined on the production machine --- even before deploying a new revision of the app.
A rake task which helps developers make sure that their local environment is in shape.
For all of this the application's
.env.example file becomes the
primary source of truth. Only variables explained there can be used in
the code or passed to tasks like
env:set. The gem also parses the
description comments to generate helpful error messages. A typical
.env.example file looks like this:
# Host name used in absolute urls HOST_NAME=my.app.com # Redirect users to the https site # ENFORCE_SSL=true
Commented out assignments signify optional variables.
makes sure you always supply a default value when fetching one of
linted_env.fetch(:enforce_ssl) # => raises an error telling you to supply a default
All in all, it's almost impossible for your example file to rot. And when it's time to deploy, a simple
$ cap production env:lint
makes sure your app won't crash after restart only because an environment variable is missing.
More details can be found in the README.
is nice addition to this team, letting you define a
which contains a concrete, version controlled configuration which is
verified in your continuous integration runs.