envied 0.8.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3da0d6e67da927a774c498a1042d5ee27b3ee3f9
4
- data.tar.gz: 9dadd80c4f668ddb1990d0f8837b730db4ecd54c
3
+ metadata.gz: d25c3d2c51229b8d12b11c07e31924a88114d2d1
4
+ data.tar.gz: 051c4d8bf0056995e60bfcf79e727d5263b72812
5
5
  SHA512:
6
- metadata.gz: c2ef13db6f79e0590da7a86217c5b5b50b4b72b993f4a6b7711feffbccf8a285e9ec20743b2fd7859e901bc495dc13623b8068446ac0664e954687eba1b6f0fd
7
- data.tar.gz: d5eaf03debc9c15d30360d8ee7c2fd75dae3cbac6d92d8cd72e9adc82c8be477a8a661532e24a54d435998da5de128a013c8c1a2af38f9cd49f9f8813b97623d
6
+ metadata.gz: e1e84ad9166cd60b9f024f042ad9d77fcb5ebedbfa3cc1263a9f7f611dc7d943458ac974fe57d8f05201279a7a091a839c10ca21597b7e1f9e0ff382c17d1ffd
7
+ data.tar.gz: 8cf40ec2c6baf773b65eb3e447cb97ec5896e5731a3a33a86b19734bd6e6fe239dc59b89c709dc504803fe41d4d570ef2dfa045ab1074cf5df75eadd115d8186
@@ -1,3 +1,14 @@
1
+ ## unreleased
2
+
3
+ ### Added
4
+
5
+ * the `check` task uses ENV['ENVIED_GROUPS'] as default groups-option if present
6
+
7
+ ### Fixed
8
+
9
+ * running `check:heroku` takes Heroku's value of ENVIED_GROUPS into account
10
+ * calling `enable_defaults!` without arguments now does what it says
11
+
1
12
  ## 0.8.0 / 2014-10-04
2
13
 
3
14
  ### Added
data/README.md CHANGED
@@ -2,11 +2,13 @@
2
2
 
3
3
  ### TL;DR ensure presence and type of your app's ENV-variables.
4
4
 
5
+ For the rationale behind this project, see this [blogpost](http://www.gertgoet.com/2014/10/14/envied-or-how-i-stopped-worrying-about-ruby-s-env.html).
6
+
5
7
  ## Features:
6
8
 
7
9
  * check for presence and correctness of ENV-variables
8
10
  * access to typed ENV-variables (integers, booleans etc. instead of just strings)
9
- * check the presence and correctness of Heroku config
11
+ * check the presence and correctness of a Heroku config
10
12
 
11
13
  ## Contents
12
14
 
@@ -19,6 +21,7 @@
19
21
  * [More examples](#more-examples)
20
22
  * [Rails](#rails--spring)
21
23
  * [Command-line interface](#command-line-interface)
24
+ * [How do I...?](#how-do-i)
22
25
  * [Testing](#testing)
23
26
  * [Developing](#developing)
24
27
  * [Contributing](#contributing)
@@ -151,46 +154,15 @@ As a rule of thumb you should only use defaults:
151
154
 
152
155
  ## Rails & Spring
153
156
 
154
- **tl;dr** use the `init:rails`-task to generate the necessary files for a Rails app (see [installation](#installation)).
155
- Remember: the environment as seen by Spring is not up-to-date until *after* initialization - this is good enough for checking the environment, but too late to use it to configure your app.
156
-
157
- ---
158
-
159
- With the [Spring](https://github.com/rails/spring) preloader (which is part of the default Rails setup nowadays) it's a bit tricky when to do `ENVied.require`.
160
-
161
- The first time you execute a command (say `bin/rails console`), Spring will start the server from which subsequent commands fork from.
162
- Currently [a bug in Spring](https://github.com/rails/spring/pull/267#issue-28580171) causes the initialization of the forked process to use the server's `ENV` instead of the actual `ENV`.
163
-
164
- So if your `ENV` is not valid the first time you start Spring...:
165
-
166
- # spring server *not* running
167
- $ bin/rails console
168
- # spring server started
169
- # error raised: Please set the following ENV-variables: FORCE_SSL (RuntimeError)
170
-
171
- ...it won't be valid for subsequent commands (even when you provide the correct variables):
172
-
173
- # spring server still running
174
- # FORCE_SSL=1 bin/rails console
175
- # error raised: Please set the following ENV-variables: FORCE_SSL (RuntimeError)
176
-
177
- So while doing a `ENVied.require` in `config/application.rb` would seem perfectly fine, it won't work in the default 'springified' Rails setup.
157
+ Long story short: Checking the presence of ENV variables using `ENVied.require` *will* work (use the `init:rails`-task and you're all set).
158
+ What won't work: relying on values from `ENV` (and thus `ENVied`) somewhere in `config/**/*.rb` **if these values vary between environments**.
178
159
 
179
- The workaround (which the `init:rails`-task will generate) is to move the `ENVied.require` to Spring's `after_fork`-callback.
180
- If you want to change Rails' config based on ENV-variables you should put this in an `after_fork`-callback as well:
181
-
182
- ```ruby
183
- # config/initializers/envied.rb as generated by 'bundle exec envied init:rails'
184
- ENVied.springify do
185
- ENVied.require(*ENV['ENVIED_GROUPS'] || Rails.groups)
186
-
187
- # Put any initialization based on ENV-variables below, e.g.:
188
- # Rails.configuration.force_ssl = ENVied.FORCE_SSL
189
- end
190
- ```
160
+ See this [wiki-page](https://github.com/eval/envied/wiki/Spring-gotchas) for more background info.
191
161
 
192
162
  ## Command-line interface
193
163
 
164
+ For help on a specific command, use `envied help <command>`.
165
+
194
166
  ```bash
195
167
  $ envied help
196
168
  Commands:
@@ -204,6 +176,41 @@ Commands:
204
176
  envied version, --version, -v # Shows version number
205
177
  ```
206
178
 
179
+ ## How do I
180
+
181
+ ### ...find all ENV-variables my app is currently using?
182
+
183
+ ```
184
+ $ bundle exec envied extract
185
+ ```
186
+
187
+ This comes in handy when you're not using ENVied yet. It will find all `ENV['EKY']` and `ENV.fetch('KEY')` statements in your project.
188
+
189
+ It assumes a standard project layout (see the default value for the globs-option).
190
+
191
+ ### ...check the config of a Heroku app?
192
+
193
+ The easiest/quickest is to run:
194
+
195
+ ```
196
+ $ heroku config | bundle exec envied check:heroku
197
+ ```
198
+
199
+ This is equivalent to having the heroku config as your local environment and running `envied check --groups default production`.
200
+
201
+ 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.
202
+
203
+ You can turn the above into a handy binstub like so:
204
+ ```
205
+ $ bundle exec envied check:heroku:binstub
206
+ # created bin/heroku-env-check
207
+ ```
208
+
209
+ This way you can do stuff like:
210
+ ```
211
+ $ ./bin/heroku-env-check && git push live master
212
+ ```
213
+
207
214
  ## Testing
208
215
 
209
216
  ```bash
@@ -8,33 +8,45 @@ require 'envied/configuration'
8
8
  class ENVied
9
9
  class << self
10
10
  attr_reader :env, :config
11
+ alias_method :required?, :env
11
12
  end
12
13
 
13
14
  def self.require(*args)
14
- env!(*args)
15
- error_on_missing_variables!
16
- error_on_uncoercible_variables!
15
+ options = args.last.is_a?(Hash) ? args.pop : {}
16
+ requested_groups = (args && !args.empty?) ? args : ENV['ENVIED_GROUPS']
17
+ env!(requested_groups, options)
18
+ error_on_missing_variables!(options)
19
+ error_on_uncoercible_variables!(options)
20
+
21
+ ensure_spring_after_fork_require(args, options)
17
22
  end
18
23
 
19
- def self.env!(*args)
24
+ def self.env!(requested_groups, options = {})
20
25
  @env = begin
21
- options = args.last.is_a?(Hash) ? args.pop : {}
22
26
  config = options.fetch(:config) { Configuration.load }
23
- groups = required_groups(*args)
27
+ groups = required_groups(*requested_groups)
24
28
  EnvProxy.new(config, groups: groups)
25
29
  end
26
30
  end
27
31
 
28
- def self.error_on_missing_variables!
32
+ def self.error_on_missing_variables!(options = {})
29
33
  names = env.missing_variables.map(&:name)
30
- raise "The following environment variables should be set: #{names * ', '}" if names.any?
34
+ if names.any?
35
+ msg = "The following environment variables should be set: #{names * ', '}."
36
+ msg << "\nPlease make sure to stop Spring before retrying." if spring_enabled? && !options[:via_spring]
37
+ raise msg
38
+ end
31
39
  end
32
40
 
33
- def self.error_on_uncoercible_variables!
41
+ def self.error_on_uncoercible_variables!(options = {})
34
42
  errors = env.uncoercible_variables.map do |v|
35
43
  "%{name} ('%{value}' can't be coerced to %{type})" % {name: v.name, value: env.value_to_coerce(v), type: v.type }
36
44
  end
37
- raise "The following environment variables are not coercible: #{errors.join(", ")}" if errors.any?
45
+ if errors.any?
46
+ msg = "The following environment variables are not coercible: #{errors.join(", ")}."
47
+ msg << "\nPlease make sure to stop Spring before retrying." if spring_enabled? && !options[:via_spring]
48
+ raise msg
49
+ end
38
50
  end
39
51
 
40
52
  def self.required_groups(*groups)
@@ -43,7 +55,18 @@ class ENVied
43
55
  result.any? ? result.map(&:to_sym) : [:default]
44
56
  end
45
57
 
58
+ def self.ensure_spring_after_fork_require(args, options = {})
59
+ if spring_enabled? && !options[:via_spring]
60
+ Spring.after_fork { ENVied.require(args, options.merge(:via_spring => true)) }
61
+ end
62
+ end
63
+
46
64
  def self.springify(&block)
65
+ if defined?(ActiveSupport::Deprecation.warn) && !required?
66
+ ActiveSupport::Deprecation.warn(<<-MSG)
67
+ It's no longer recommended to `ENVied.require` within ENVied.springify's block. Please re-run `envied init:rails` to upgrade.
68
+ MSG
69
+ end
47
70
  if spring_enabled?
48
71
  Spring.after_fork(&block)
49
72
  else
@@ -52,8 +52,13 @@ INIT
52
52
  define_method "init:rails" do
53
53
  puts "Writing Envfile to #{File.expand_path('Envfile')}"
54
54
  template("Envfile.tt")
55
-
56
- template("rails-initializer.tt", 'config/initializers/envied.rb')
55
+ inject_into_file "config/application.rb", "\nENVied.require(*ENV['ENVIED_GROUPS'] || Rails.groups)", after: /^ *Bundler.require.+$/
56
+ legacy_initializer = Dir['config/initializers/*envied*.rb'].first
57
+ if legacy_initializer && File.exists?(legacy_initializer)
58
+ puts "Removing 'ENVied.require' from #{legacy_initializer.inspect}."
59
+ puts "(you might want to remove the whole file)"
60
+ comment_lines legacy_initializer, /ENVied.require/
61
+ end
57
62
  end
58
63
 
59
64
  desc "check", "Checks whether you environment contains required variables"
@@ -63,7 +68,7 @@ INIT
63
68
  On success the process will exit with status 0.
64
69
  Else the missing/invalid variables will be shown, and the process will exit with status 1.
65
70
  LONG
66
- option :groups, type: :array, default: %w(default), banner: 'default production'
71
+ option :groups, type: :array, desc: "uses ENV['ENVIED_GROUPS'] as default if present", default: ENV['ENVIED_GROUPS'] || %w(default), banner: 'default production'
67
72
  option :quiet, type: :boolean, desc: 'Communicate success of the check only via the exit status.'
68
73
  def check
69
74
  ENVied.require(*options[:groups])
@@ -100,10 +105,13 @@ ERR
100
105
  heroku_env = Hash[config.split("\n")[1..-1].each_with_object([]) do |i, res|
101
106
  res << i.split(":", 2).map(&:strip)
102
107
  end]
108
+
103
109
  ENV.replace({}).update(heroku_env)
104
- ENVied.require(*options[:groups])
110
+
111
+ requested_groups = ENV['ENVIED_GROUPS'] || options[:groups]
112
+ ENVied.require(*requested_groups)
105
113
  unless options[:quiet]
106
- puts "All variables for group(s) #{options[:groups]} are present and valid in your Heroku app"
114
+ puts "All variables for group(s) #{requested_groups} are present and valid in your Heroku app"
107
115
  end
108
116
  end
109
117
 
@@ -3,11 +3,19 @@ class ENVied
3
3
  attr_reader :current_group, :defaults_enabled, :coercer
4
4
 
5
5
  def initialize(options = {}, &block)
6
- @defaults_enabled = options.fetch(:enable_defaults, false)
7
6
  @coercer = options.fetch(:coercer, Coercer.new)
7
+ @defaults_enabled = options.fetch(:enable_defaults, defaults_enabled_default)
8
8
  instance_eval(&block) if block_given?
9
9
  end
10
10
 
11
+ def defaults_enabled_default
12
+ if ENV['ENVIED_ENABLE_DEFAULTS'].nil?
13
+ false
14
+ else
15
+ @coercer.coerce(ENV['ENVIED_ENABLE_DEFAULTS'], :boolean)
16
+ end
17
+ end
18
+
11
19
  def self.load(options = {})
12
20
  envfile = File.expand_path('Envfile')
13
21
  new(options).tap do |v|
@@ -15,8 +23,8 @@ class ENVied
15
23
  end
16
24
  end
17
25
 
18
- def enable_defaults!(value = nil, &block)
19
- @defaults_enabled = (value.nil? ? block : value)
26
+ def enable_defaults!(value = true, &block)
27
+ @defaults_enabled = block_given? ? block.call : value
20
28
  end
21
29
 
22
30
  def defaults_enabled?
@@ -1,3 +1,3 @@
1
1
  class ENVied
2
- VERSION = '0.8.0'
2
+ VERSION = '0.8.1'
3
3
  end
@@ -128,6 +128,13 @@ describe ENVied do
128
128
  expect(subject.defaults_enabled?).to_not be
129
129
  end
130
130
 
131
+ it 'yields ENV["ENVIED_ENABLE_DEFAULTS"] if not set otherwise' do
132
+ stub_const("ENV", {'ENVIED_ENABLE_DEFAULTS' => '1'})
133
+ configure
134
+
135
+ expect(subject.defaults_enabled?).to be
136
+ end
137
+
131
138
  it 'can be enabled via #configure' do
132
139
  configure(enable_defaults: true){ }
133
140
 
@@ -135,7 +142,7 @@ describe ENVied do
135
142
  end
136
143
 
137
144
  it 'can be enabled via a configure-block' do
138
- configure { self.enable_defaults!(true) }
145
+ configure { self.enable_defaults! }
139
146
 
140
147
  expect(subject.defaults_enabled?).to be
141
148
  end
@@ -197,13 +204,28 @@ describe ENVied do
197
204
  end
198
205
  end
199
206
 
207
+ describe "::required?" do
208
+ it 'yields true-ish when ::require is called' do
209
+ expect {
210
+ envied_require
211
+ }.to change { ENVied.required? }.from(nil).to(anything)
212
+ end
213
+ end
214
+
200
215
  describe "groups" do
201
216
  describe 'requiring' do
217
+
202
218
  it 'yields :default when nothing passed to require' do
203
219
  envied_require
204
220
  expect(ENVied.env.groups).to eq [:default]
205
221
  end
206
222
 
223
+ it 'takes ENV["ENVIED_GROUPS"] into account when nothing passed to require' do
224
+ and_ENV('ENVIED_GROUPS' => 'baz')
225
+ envied_require
226
+ expect(ENVied.env.groups).to eq [:baz]
227
+ end
228
+
207
229
  it 'yields groupnames passed to it as string' do
208
230
  envied_require('bar')
209
231
  expect(ENVied.env.groups).to eq [:bar]
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: envied
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.0
4
+ version: 0.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gert Goet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-10-04 00:00:00.000000000 Z
11
+ date: 2014-10-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coercible
@@ -121,7 +121,6 @@ files:
121
121
  - lib/envied/env_var_extractor.rb
122
122
  - lib/envied/templates/Envfile.tt
123
123
  - lib/envied/templates/heroku-env-check.tt
124
- - lib/envied/templates/rails-initializer.tt
125
124
  - lib/envied/variable.rb
126
125
  - lib/envied/version.rb
127
126
  - spec/coercer_spec.rb
@@ -1,6 +0,0 @@
1
- ENVied.springify do
2
- ENVied.require(*ENV['ENVIED_GROUPS'] || Rails.groups)
3
-
4
- # Put any initialization based on ENV-variables below, e.g.:
5
- # Rails.configuration.force_ssl = ENVied.FORCE_SSL
6
- end