- Notifications
You must be signed in to change notification settings - Fork42
Ensures presence and type of your app's ENV-variables (mirror)
License
eval/envied
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
Seehttps://github.com/eval/nero for a modern replacement.
For the rationale behind this project, see thisblogpost.
- check for presence and correctness of ENV-variables
- access to typed ENV-variables (integers, booleans etc. instead of just strings)
- check the presence and correctness of a Heroku config
- provide or load ENV-values
- Quickstart
- Installation
- Configuration
- Command-line interface
- Best Practices
- FAQ
- Testing
- Development
- Contributing
Aftersuccessful installation, define some variables inEnvfile
:
# file: Envfilevariable:FORCE_SSL,:booleanvariable:PORT,:integer
# during initializationENVied.require
This will throw an error if:
- one of
ENV['FORCE_SSL']
,ENV['PORT']
is absent. - or: their valuescannot be coerced (resp. to boolean and integer).
Variables accessed via ENVied are of the correct type:
ENVied.PORT# => 3001ENVied.FORCE_SSL# => false
The following types are supported:
:array
(e.g. 'tag1,tag2' becomes['tag1', 'tag2']
):boolean
(e.g. '0'/'1', 'f'/'t', 'false'/'true', 'off'/'on', 'no'/'yes' for resp. false and true):date
(e.g. '2014-3-26'):env
(similar to:string
, but accessible via ENV - seeKey alias for details):float
:hash
(e.g. 'a=1&b=2' becomes{'a' => '1', 'b' => '2'}
):integer
:string
(implied):symbol
:time
(e.g. '14:00'):uri
(e.g. 'http://www.google.com' becomes result ofURI.parse('http://www.google.com')
)
By default the value for variableFOO
should be provided byENV['FOO']
. Sometimes though it's convenient to let a different key provide the value, based on some runtime condition. A key-alias will let you do this.
Consider for example local development whereREDIS_URL
differs between the development and test environment. Normally you'd prepare different shells with different values forREDIS_URL
: one shell you can run tests in, and other shells where you'd run the console/server etc. This is cumbersome and easy to get wrong.
With a key alias that's calculated at runtime (e.g.Rails.env
) you'd set values for bothREDIS_URL_TEST
andREDIS_URL_DEVELOPMENT
and the right value will be used for test and development.
Full example:
# file: Envfilekey_alias! { Rails.env }variable :REDIS_URL, :uri
Source the following in your environment:
# file: .envrcexport REDIS_URL_DEVELOPMENT=redis://localhost:6379/0export REDIS_URL_TEST=redis://localhost:6379/1
Now commands likerails console
andrails test
automatically point to the right redis database.
Note thatENV['REDIS_URL']
is still considered butREDIS_URL_<key_alias>
takes precedence.
Also: any truthy value provided as key_alias is converted to an upcased string.
Finally: this setting is optional.
Variables of type:env
take the key alias into account when accessingENV['FOO']
.
Say, your application usesENV['DATABASE_URL']
(wich you can't change toENVied.DATABASE_URL
). Normally this would mean that the key alias has no effect. For env-type variables however, the key alias is taken into account:
# file: Envfilekey_alias! { Rails.env }variable :DATABASE_URL, :env
The following now works:
$ DATABASE_URL_DEVELOPMENT=postgres://localhost/blog_development rails runner"p ENV['DATABASE_URL']""postgres://localhost/blog_development"
Note: this also works forENV.fetch('FOO')
.
Also: no coercion is done (like you would expect when accessing ENV-values directly).
This means that for Rails applications when you set values forDATABASE_URL_DEVELOPMENT
andDATABASE_URL_TEST
, you no longer need aconfig/database.yml
.
Groups give you more flexibility to define when variables are needed.It's similar to groups in a Gemfile:
# file: Envfilevariable:FORCE_SSL,:booleangroup:productiondovariable:SECRET_KEY_BASEendgroup:development,:stagingdovariable:DEV_KEYend
# For local development you would typically do:ENVied.require(:default)#=> Only ENV['FORCE_SSL'] is required# On the production server:ENVied.require(:default,:production)#=> ...also ENV['SECRET_KEY_BASE'] is required# You can also pass it a string with the groups separated by comma's:ENVied.require('default, production')# This allows for easily requiring groups using the ENV:ENVied.require(ENV['ENVIED_GROUPS'])# ...then from the prompt:$ENVIED_GROUPS='default,production'bin/railsserver# BTW the following are equivalent:ENVied.requireENVied.require(:default)ENVied.require('default')ENVied.require(nil)
For help on a specific command, useenvied help <command>
.
$ enviedhelpCommands: envied check# Checks whether you environment contains required variables envied check:heroku# Checks whether a Heroku config contains required variables envied check:heroku:binstub# Generates a shell script for the check:heroku-task envied extract# Grep code to find ENV-variables enviedhelp [COMMAND]# Describe available commands or one specific command envied init# Generates a default Envfile in the current working directory envied init:rails# Generate all files needed for a Rails project envied version, --version, -v# Shows version number
Some best practices when using ENVied or working with env-configurable applications in general.
While ENVied will warn you when you start an application that is 'under-configured', it won't tell users what good default values are. To solve this add a file to the root of your project that contains sane defaults and instructions:
# file: .envrc.sample# copy this file to .envrc and adjust values if needed# then do `source .envrc` to loadexport DATABASE_URL=postgres://localhost/blog_development# export FORCE_SSL=true # only needed for production# you can find this token on the Heroku-dashboardexport DEPLOY_TOKEN=1234-ABC-5678
letdirenv manage your environment
direnv will auto-(un)load values from.envrc
when you switch folders.
As a bonus it has some powerful commands in it'sstdlib.
For example:
# this adds the project's bin-folder to $PATHPATH_add bin# so instead of `./bin/rails -h` you can do `rails -h` from anywhere (deep) in the project# the following will use the .envrc.sample as a basis# when new variables are introduced upstream, you'll automatically use these defaultsif [ -f .envrc.sample ]; then source_env .envrc.samplefi...your overrides# a variant of this is source_up# an .envrc in a subfolder can load the .envrc from the root of the project and override specific values# this would allow e.g. for a specific test-environment in the subfolder:# in my-project/test/.envrcsource_up .envrcexport DATABASE_URL=the-test-db-url
$ bundle exec envied extract
This comes in handy when you're not using ENVied yet. It will find allENV['KEY']
andENV.fetch('KEY')
statements in your project.
It assumes a standard project layout (see the default value for the globs-option).
The easiest/quickest is to run:
$ heroku config --json | bundle exec envied check:heroku
This is equivalent to having the heroku config as your local environment and runningenvied check:heroku --groups default production
.
You want to run this right before a deploy to Heroku. This prevents that your app will crash during bootup because ENV-variables are missing from heroku config.
You can turn the above into a handy binstub like so:
$ bundle exec envied check:heroku:binstub# created bin/heroku-env-check
This way you can do stuff like:
$ ./bin/heroku-env-check && git push live master
The short version: simplicity, i.e. the best tool for the job.
In the early days of ENVied it was possible to provide default values for a variable.
While convenient, it had several drawbacks:
- it would introduce a value for ENVied.FOO, while ENV['FOO'] was nil: confusing and a potential source of bugs.
- it hides the fact that an application can actually be configged via the environment.
- it creates an in-process environment which is hard to inspect (as opposed to doing
printenv FOO
in a shell, after or before starting the application). - there are better ways: e.g. a sample file in a project with a bunch of exports (ie
export FOO=sane-default # and even some documentation
) that someone can source in their shell (seeBest Practices). - made the code quite complex.
As an alternative include a file.envrc.sample
in the root of your project containing default values (ieexport FOO=bar
) that users can source in their shell. See alsoBest Practices.
$ ./bin/setup# run tests$ ./bin/rspec# hack with pry$ ./bin/console# run CLI:$ ./bin/envied
There's a.envrc.sample
included that can be used in combination withdirenv.
To suggest a new feature,open an Issue before opening a PR.
- Fork it:https://gitlab.com/envied/envied/-/forks/new
- Create your feature branch:
git checkout -b my-new-feature
- Commit your changes:
git commit -am 'Add some feature'
- Push to the branch:
git push origin my-new-feature
- Create a new pull request for your feature branch
About
Ensures presence and type of your app's ENV-variables (mirror)