Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/eval/envied
Ensures presence and type of your app's ENV-variables (mirror)
https://github.com/eval/envied
environment-variables heroku rails ruby
Last synced: 4 days ago
JSON representation
Ensures presence and type of your app's ENV-variables (mirror)
- Host: GitHub
- URL: https://github.com/eval/envied
- Owner: eval
- License: mit
- Created: 2014-03-08T23:13:11.000Z (almost 11 years ago)
- Default Branch: master
- Last Pushed: 2022-05-19T16:04:06.000Z (over 2 years ago)
- Last Synced: 2025-01-15T06:59:13.430Z (11 days ago)
- Topics: environment-variables, heroku, rails, ruby
- Language: Ruby
- Homepage: https://gitlab.com/envied/envied/tree/master#envied
- Size: 238 KB
- Stars: 330
- Watchers: 6
- Forks: 42
- Open Issues: 8
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE.txt
Awesome Lists containing this project
- awesome-ruby - ENVied - ensure presence and type of your app's ENV-variables (Configuration)
README
# ENVied [![pipeline status](https://gitlab.com/envied/envied/badges/master/pipeline.svg)](https://gitlab.com/envied/envied/commits/master) [![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://envied-rb.zulipchat.com/)
_Canonical Repository:_ https://gitlab.com/envied/envied/tree/master#envied
### TL;DR ensure presence and type of your app's ENV-variables.
For the rationale behind this project, see this [blogpost](https://www.gertgoet.com/2014/10/14/envied-or-how-i-stopped-worrying-about-ruby-s-env.html).
## Features
* 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## Non-features
* provide or load ENV-values
## Contents
* [Quickstart](#quickstart)
* [Installation](#installation)
* [Configuration](#configuration)
* [Types](#types)
* [Key alias](#key-alias-unreleased)
* [env-type](#env-type-unreleased)
* [Groups](#groups)
* [Command-line interface](#command-line-interface)
* [Best Practices](#best-practices)
* [FAQ](#faq)
* [Testing](#testing)
* [Development](#development)
* [Contributing](#contributing)## Quickstart
### 1) Configure
After [successful installation](#installation), define some variables in `Envfile`:
```ruby
# file: Envfile
variable :FORCE_SSL, :boolean
variable :PORT, :integer
```### 2) Check for presence and coercibility
```ruby
# during initialization
ENVied.require
```This will throw an error if:
* one of `ENV['FORCE_SSL']`, `ENV['PORT']` is absent.
* or: their values *cannot* be coerced (resp. to boolean and integer).### 3) Use coerced variables
Variables accessed via ENVied are of the correct type:
```ruby
ENVied.PORT # => 3001
ENVied.FORCE_SSL # => false
```## Installation
Add this line to your application's Gemfile:
gem 'envied'
...then bundle:
$ bundle
...then for Rails applications:
$ bundle exec envied init:rails
...or for non-Rails applications:
$ bundle exec envied init
## Configuration
### Types
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 - see [Key alias](#key-alias-unreleased) 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 of `URI.parse('http://www.google.com')`)### Key alias (unreleased)
By default the value for variable `FOO` should be provided by `ENV['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 where `REDIS_URL` differs between the development and test environment. Normally you'd prepare different shells with different values for `REDIS_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 both `REDIS_URL_TEST` and `REDIS_URL_DEVELOPMENT` and the right value will be used for test and development.
Full example:
```
# file: Envfile
key_alias! { Rails.env }variable :REDIS_URL, :uri
```Source the following in your environment:
```
# file: .envrc
export REDIS_URL_DEVELOPMENT=redis://localhost:6379/0
export REDIS_URL_TEST=redis://localhost:6379/1
```
Now commands like `rails console` and `rails test` automatically point to the right redis database.Note that `ENV['REDIS_URL']` is still considered but `REDIS_URL_` takes precedence.
Also: any truthy value provided as key_alias is converted to an upcased string.
Finally: this setting is optional.#### env-type (unreleased)
Variables of type `:env` take the key alias into account when accessing `ENV['FOO']`.
Say, your application uses `ENV['DATABASE_URL']` (wich you can't change to `ENVied.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:
```shell
$ DATABASE_URL_DEVELOPMENT=postgres://localhost/blog_development rails runner "p ENV['DATABASE_URL']"
"postgres://localhost/blog_development"
```Note: this also works for `ENV.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 for `DATABASE_URL_DEVELOPMENT` and `DATABASE_URL_TEST`, you no longer need a `config/database.yml`.
### Groups
Groups give you more flexibility to define when variables are needed.
It's similar to groups in a Gemfile:```ruby
# file: Envfile
variable :FORCE_SSL, :booleangroup :production do
variable :SECRET_KEY_BASE
endgroup :development, :staging do
variable :DEV_KEY
end
``````ruby
# 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/rails server# BTW the following are equivalent:
ENVied.require
ENVied.require(:default)
ENVied.require('default')
ENVied.require(nil)
```## Command-line interface
For help on a specific command, use `envied help `.
```bash
$ envied help
Commands:
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
envied help [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
```## Best Practices
Some best practices when using ENVied or working with env-configurable applications in general.
### include a .envrc.sample
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-dashboard
export DEPLOY_TOKEN=1234-ABC-5678
```### let [direnv](https://direnv.net/) manage your environment
[direnv](https://direnv.net/) will auto-(un)load values from `.envrc` when you switch folders.
As a bonus it has some powerful commands in it's [stdlib](https://direnv.net/#man/direnv-stdlib.1).
For example:
```
# this adds the project's bin-folder to $PATH
PATH_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 defaults
if [ -f .envrc.sample ]; then
source_env .envrc.sample
fi
...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/.envrc
source_up .envrc
export DATABASE_URL=the-test-db-url
```## FAQ
### How to find all ENV-variables my app is currently using?
```
$ bundle exec envied extract
```This comes in handy when you're not using ENVied yet. It will find all `ENV['KEY']` and `ENV.fetch('KEY')` statements in your project.
It assumes a standard project layout (see the default value for the globs-option).
### How to check the config of a Heroku app?
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 running `envied 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
```### What happened to default values??
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 (see [Best Practices](#best-practices)).
- made the code quite complex.As an alternative include a file `.envrc.sample` in the root of your project containing default values (ie `export FOO=bar`) that users can source in their shell. See also [Best Practices](#best-practices).
## Development
```bash
$ ./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 with [direnv](http://direnv.net/).
## Contributing
To suggest a new feature, [open an Issue](https://gitlab.com/envied/envied/issues/new) before opening a PR.
1. Fork it: https://gitlab.com/envied/envied/-/forks/new
2. Create your feature branch: `git checkout -b my-new-feature`
3. Commit your changes: `git commit -am 'Add some feature'`
4. Push to the branch: `git push origin my-new-feature`
5. Create a new pull request for your feature branch