envied 0.8.0 → 0.8.1

Sign up to get free protection for your applications and to get access to all the features.
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