envied 0.9.1 → 0.9.2.rc1

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
- SHA1:
3
- metadata.gz: 1eae6e996d1e0a70624b7c24167eccd631a5d9a0
4
- data.tar.gz: d9df438b52137f7a22592b468a44895f7cd5a99d
2
+ SHA256:
3
+ metadata.gz: 13dbc94c996f024f24f78d106973b051c90c83231a79a5f78e190f17c31c431b
4
+ data.tar.gz: '0836c6bb61eb65228beaa6ee0100d9229f7557b52d663a68914b641528d37d6f'
5
5
  SHA512:
6
- metadata.gz: 6e770306eb9e9fb37130e5a3fb69be59d3c25443bbd1c36ab09303a9575ad884f0f4569755827f7e0f1362e05621d0c7ac6455d2eb438b620b2bd48e4f6ac3fb
7
- data.tar.gz: 6a49f0e90abb416a73e3199961df26b4cdef5e83fa8c0b60e9053f46f4ed18cec7608faddb9b82fdaa726a9329922981135eb05c6a85043ae4052ca34ddff7bb
6
+ metadata.gz: 85fc118a868a8b78e22c9e1160fe842e2a4a173f86c39f740cdaa8f26cc3ba2d383f4ab2c6606ee422a60e914b30a8b6f5db109532051831430be52b8e1f030c
7
+ data.tar.gz: 96f37d724c1d660e1530360782c01d704562ded183c4f19fc3e9821c2a8ac6bab319434210d15c9e7f40d8e80c686bbdd61f73df20c66af549b109ec3a31f9f3
data/.gitignore CHANGED
@@ -1,18 +1,14 @@
1
- *.gem
2
- *.rbc
3
- .bundle
4
- .config
5
- .yardoc
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /spec/examples.txt
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+
6
14
  Gemfile.lock
7
- InstalledFiles
8
- _yardoc
9
- coverage
10
- doc/
11
- lib/bundler/man
12
- pkg
13
- rdoc
14
- spec/reports
15
- test/tmp
16
- test/version_tmp
17
- tmp
18
- bin
data/.rspec CHANGED
@@ -1,3 +1,2 @@
1
- --warnings
2
- --format progress
3
1
  --color
2
+ --require spec_helper
@@ -1,16 +1,15 @@
1
1
  language: ruby
2
2
 
3
3
  before_install:
4
+ - "echo 'gem: --no-document' > ~/.gemrc"
4
5
  - gem update --system
5
6
  - gem install bundler
6
7
 
7
8
  rvm:
8
- - 2.1.10
9
- - 2.2.7
10
- - 2.3.4
11
- - 2.4.1
12
- - jruby-9.1.12.0
13
- - jruby-head
9
+ - 2.4.5
10
+ - 2.5.5
11
+ - 2.6.2
12
+ - jruby-9.2.6.0
14
13
 
15
14
  cache: bundler
16
15
  sudo: false
@@ -1,3 +1,8 @@
1
+ ## master / unreleased
2
+
3
+ * Now requiring Ruby 2.4+ [#48], [#51]
4
+ * Removed `coercible` dependency as now all coercion functionality is implemented locally. This is a backwards compatible change. [#49]
5
+
1
6
  ## 0.9.1 / 2017-07-06
2
7
 
3
8
  * Updates `envied check:heroku` to support multiline ENV variables [#42](../../pull/42)
data/Gemfile CHANGED
@@ -2,6 +2,3 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in envied.gemspec
4
4
  gemspec
5
-
6
- gem 'pry'
7
- gem 'benchmark-ips'
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # ENVied [![Build Status](https://travis-ci.org/eval/envied.svg?branch=master)](https://travis-ci.org/eval/envied)
1
+ # ENVied [![Build Status](https://travis-ci.org/eval/envied.svg?branch=master)](https://travis-ci.org/eval/envied) [![project chat](https://img.shields.io/badge/zulip-join_chat-brightgreen.svg)](https://envied-rb.zulipchat.com/)
2
2
 
3
3
  ### TL;DR ensure presence and type of your app's ENV-variables.
4
4
 
@@ -19,7 +19,6 @@ For the rationale behind this project, see this [blogpost](http://www.gertgoet.c
19
19
  * [Groups](#groups)
20
20
  * [Defaults](#defaults)
21
21
  * [More examples](#more-examples)
22
- * [Rails](#rails--spring)
23
22
  * [Command-line interface](#command-line-interface)
24
23
  * [How do I...?](#how-do-i)
25
24
  * [Testing](#testing)
@@ -91,11 +90,11 @@ The following types are supported:
91
90
  * `:time` (e.g. '14:00')
92
91
  * `:hash` (e.g. 'a=1&b=2' becomes `{'a' => '1', 'b' => '2'}`)
93
92
  * `:array` (e.g. 'tag1,tag2' becomes `['tag1', 'tag2']`)
94
- * `:uri` (e.g. 'http://www.google.com' becomes `URI.parse('http://www.google.com')`
93
+ * `:uri` (e.g. 'http://www.google.com' becomes result of `URI.parse('http://www.google.com')`)
95
94
 
96
95
  ### Groups
97
96
 
98
- Groups give you more flexibility to define when variables are needed.
97
+ Groups give you more flexibility to define when variables are needed.
99
98
  It's similar to groups in a Gemfile:
100
99
 
101
100
  ```ruby
@@ -147,7 +146,7 @@ variable :FORCE_SSL, :boolean, default: 'false'
147
146
  variable :PORT, :integer, default: proc {|envied| envied.FORCE_SSL ? 443 : 80 }
148
147
  ```
149
148
 
150
- Please remember that ENVied only **reads** from ENV; it doesn't mutate ENV.
149
+ Please remember that ENVied only **reads** from ENV; it doesn't mutate ENV.
151
150
  Don't let setting a default for, say `RAILS_ENV`, give you the impression that `ENV['RAILS_ENV']` is set.
152
151
  As a rule of thumb you should only use defaults:
153
152
  * for local development
@@ -220,7 +219,7 @@ bundle exec rspec
220
219
  ## Developing
221
220
 
222
221
  ```bash
223
- bundle exec pry --gem
222
+ bin/console
224
223
  ```
225
224
 
226
225
  ## Contributing
data/Rakefile CHANGED
@@ -1,10 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
- require 'rspec/core/rake_task'
2
+ require "rspec/core/rake_task"
3
3
 
4
- RSpec::Core::RakeTask.new(:spec) do |s|
5
- s.ruby_opts = %w(-w)
6
- s.rspec_opts = '--format progress'
7
- end
4
+ RSpec::Core::RakeTask.new(:spec)
8
5
 
9
- desc "Run the specs"
10
6
  task default: :spec
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "envied"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+ require 'envied'
3
+
4
+ ENVied::Cli.start
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -18,10 +18,11 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.required_ruby_version = ">= 2.1.9"
22
- spec.add_dependency "coercible", "~> 1.0"
21
+ spec.required_ruby_version = ">= 2.4"
22
+
23
23
  spec.add_dependency "thor", "~> 0.15"
24
- spec.add_development_dependency "bundler", "~> 1.5"
25
- spec.add_development_dependency "rake"
24
+
25
+ spec.add_development_dependency "bundler", "~> 2.0"
26
+ spec.add_development_dependency "rake", "~> 12.0"
26
27
  spec.add_development_dependency "rspec", "~> 3.0"
27
28
  end
@@ -12,8 +12,7 @@ class ENVied
12
12
  alias_method :required?, :env
13
13
  end
14
14
 
15
- def self.require(*args)
16
- options = args.last.is_a?(Hash) ? args.pop : {}
15
+ def self.require(*args, **options)
17
16
  requested_groups = (args && !args.empty?) ? args : ENV['ENVIED_GROUPS']
18
17
  env!(requested_groups, options)
19
18
  error_on_missing_variables!(options)
@@ -22,26 +21,23 @@ class ENVied
22
21
  ensure_spring_after_fork_require(args, options)
23
22
  end
24
23
 
25
- def self.env!(requested_groups, options = {})
26
- @env = begin
27
- @config = options.fetch(:config) { Configuration.load }
28
- groups = required_groups(*requested_groups)
29
- EnvProxy.new(@config, groups: groups)
30
- end
24
+ def self.env!(requested_groups, **options)
25
+ @config = options.fetch(:config) { Configuration.load }
26
+ @env = EnvProxy.new(@config, groups: required_groups(*requested_groups))
31
27
  end
32
28
 
33
- def self.error_on_missing_variables!(options = {})
29
+ def self.error_on_missing_variables!(**options)
34
30
  names = env.missing_variables.map(&:name)
35
31
  if names.any?
36
- msg = "The following environment variables should be set: #{names * ', '}."
32
+ msg = "The following environment variables should be set: #{names.join(', ')}."
37
33
  msg << "\nPlease make sure to stop Spring before retrying." if spring_enabled? && !options[:via_spring]
38
34
  raise msg
39
35
  end
40
36
  end
41
37
 
42
- def self.error_on_uncoercible_variables!(options = {})
38
+ def self.error_on_uncoercible_variables!(**options)
43
39
  errors = env.uncoercible_variables.map do |v|
44
- "%{name} ('%{value}' can't be coerced to %{type})" % {name: v.name, value: env.value_to_coerce(v), type: v.type }
40
+ format("%{name} with %{value} (%{type})", name: v.name, value: env.value_to_coerce(v).inspect, type: v.type)
45
41
  end
46
42
  if errors.any?
47
43
  msg = "The following environment variables are not coercible: #{errors.join(", ")}."
@@ -56,17 +52,18 @@ class ENVied
56
52
  result.any? ? result.map(&:to_sym) : [:default]
57
53
  end
58
54
 
59
- def self.ensure_spring_after_fork_require(args, options = {})
55
+ def self.ensure_spring_after_fork_require(args, **options)
60
56
  if spring_enabled? && !options[:via_spring]
61
- Spring.after_fork { ENVied.require(args, options.merge(:via_spring => true)) }
57
+ Spring.after_fork { ENVied.require(args, options.merge(via_spring: true)) }
62
58
  end
63
59
  end
64
60
 
65
61
  def self.springify(&block)
66
62
  if defined?(ActiveSupport::Deprecation.warn) && !required?
67
- ActiveSupport::Deprecation.warn(<<-MSG)
68
- It's no longer recommended to `ENVied.require` within ENVied.springify's block. Please re-run `envied init:rails` to upgrade.
69
- MSG
63
+ ActiveSupport::Deprecation.warn(<<~MSG)
64
+ It's no longer recommended to `ENVied.require` within ENVied.springify's
65
+ block. Please re-run `envied init:rails` to upgrade.
66
+ MSG
70
67
  end
71
68
  if spring_enabled?
72
69
  Spring.after_fork(&block)
@@ -43,10 +43,8 @@ class ENVied
43
43
  puts "Writing Envfile to #{File.expand_path('Envfile')}"
44
44
  template("Envfile.tt")
45
45
 
46
- puts <<-INIT
47
- Add the following snippet (or similar) to your app's initialization:
48
- ENVied.require(*ENV['ENVIED_GROUPS'] || [:default, ENV['RACK_ENV']])
49
- INIT
46
+ puts "Add the following snippet (or similar) to your app's initialization:"
47
+ puts "ENVied.require(*ENV['ENVIED_GROUPS'] || [:default, ENV['RACK_ENV']])"
50
48
  end
51
49
 
52
50
  desc "init:rails", "Generate all files needed for a Rails project"
@@ -79,7 +77,6 @@ INIT
79
77
  end
80
78
 
81
79
  desc "check:heroku", "Checks whether a Heroku config contains required variables"
82
-
83
80
  long_desc <<-LONG
84
81
  Checks the config of your Heroku app against the local Envfile.
85
82
 
@@ -96,14 +93,11 @@ INIT
96
93
  option :quiet, type: :boolean, desc: 'Communicate success of the check only via the exit status.'
97
94
  define_method "check:heroku" do
98
95
  if STDIN.tty?
99
- error <<-ERR
100
- Please pipe the contents of `heroku config --json` to this task.
101
- I.e. `heroku config --json | bundle exec envied check:heroku`"
102
- ERR
96
+ error "Please pipe to this task i.e. `heroku config --json | bundle exec envied check:heroku`"
103
97
  exit 1
104
98
  end
105
99
  heroku_env = JSON.parse(STDIN.read)
106
- ENV.replace({}).update(heroku_env)
100
+ ENV.replace(heroku_env)
107
101
 
108
102
  requested_groups = ENV['ENVIED_GROUPS'] || options[:groups]
109
103
  ENVied.require(*requested_groups)
@@ -117,7 +111,6 @@ ERR
117
111
  Generates a shell script to check the Heroku config against the local Envfile.
118
112
 
119
113
  The same as the check:heroku-task, but all in one script (no need to pipe `heroku config --json` to it etc.).
120
-
121
114
  LONG
122
115
  option :dest, banner: "where to put the script", desc: "Default: bin/<app>-env-check or bin/heroku-env-check"
123
116
  option :app, banner: "name of Heroku app", desc: "uses ENV['HEROKU_APP'] as default if present", default: ENV['HEROKU_APP']
@@ -1,7 +1,8 @@
1
- require 'coercible'
2
-
3
1
  # Responsible for all string to type coercions.
4
2
  class ENVied::Coercer
3
+
4
+ UnsupportedCoercion = Class.new(StandardError)
5
+
5
6
  # Coerce strings to specific type.
6
7
  #
7
8
  # @param string [String] the string to be coerced
@@ -14,14 +15,9 @@ class ENVied::Coercer
14
15
  # @return [type] the coerced string.
15
16
  def coerce(string, type)
16
17
  unless supported_type?(type)
17
- raise ArgumentError, "#{type.inspect} is not supported type"
18
+ raise ArgumentError, "The type `#{type.inspect}` is not supported."
18
19
  end
19
- coerce_method_for(type.to_sym)[string]
20
- end
21
-
22
- def coerce_method_for(type)
23
- return nil unless supported_type?(type)
24
- coercer.method("to_#{type.downcase}")
20
+ coercer.public_send("to_#{type.downcase}", string)
25
21
  end
26
22
 
27
23
  def self.supported_types
@@ -52,7 +48,7 @@ class ENVied::Coercer
52
48
  end
53
49
 
54
50
  def coercer
55
- @coercer ||= Coercible::Coercer.new[ENViedString]
51
+ @coercer ||= ENViedString.new
56
52
  end
57
53
 
58
54
  def coerced?(value)
@@ -63,7 +59,7 @@ class ENVied::Coercer
63
59
  return false unless supported_type?(type)
64
60
  coerce(string, type)
65
61
  true
66
- rescue Coercible::UnsupportedCoercion
62
+ rescue UnsupportedCoercion
67
63
  false
68
64
  end
69
65
  end
@@ -1,15 +1,55 @@
1
- require 'coercible'
1
+ class ENVied::Coercer::ENViedString
2
+ TRUE_VALUES = %w[1 on t true y yes].freeze
3
+ FALSE_VALUES = %w[0 off f false n no].freeze
4
+ BOOLEAN_MAP = (TRUE_VALUES.product([ true ]) + FALSE_VALUES.product([ false ])).to_h.freeze
2
5
 
3
- class ENVied::Coercer::ENViedString < Coercible::Coercer::String
4
6
  def to_array(str)
5
7
  str.split(/(?<!\\),/).map{|i| i.gsub(/\\,/,',') }
6
8
  end
7
9
 
10
+ def to_boolean(str)
11
+ BOOLEAN_MAP.fetch(str&.downcase) do
12
+ raise_unsupported_coercion(str, __method__)
13
+ end
14
+ end
15
+
16
+ def to_date(str)
17
+ require 'date'
18
+ ::Date.parse(str)
19
+ rescue ArgumentError
20
+ raise_unsupported_coercion(str, __method__)
21
+ end
22
+
23
+ def to_float(str)
24
+ Float(str)
25
+ rescue ArgumentError
26
+ raise_unsupported_coercion(str, __method__)
27
+ end
28
+
8
29
  def to_hash(str)
9
30
  require 'cgi'
10
31
  ::CGI.parse(str).map { |key, values| [key, values[0]] }.to_h
11
32
  end
12
33
 
34
+ def to_string(str)
35
+ if str.respond_to?(:to_str)
36
+ str.public_send(:to_str)
37
+ else
38
+ raise_unsupported_coercion(str, __method__)
39
+ end
40
+ end
41
+
42
+ def to_symbol(str)
43
+ str.to_sym
44
+ end
45
+
46
+ def to_time(str)
47
+ require 'time'
48
+ ::Time.parse(str)
49
+ rescue ArgumentError
50
+ raise_unsupported_coercion(str, __method__)
51
+ end
52
+
13
53
  def to_uri(str)
14
54
  require 'uri'
15
55
  ::URI.parse(str)
@@ -20,4 +60,13 @@ class ENVied::Coercer::ENViedString < Coercible::Coercer::String
20
60
  rescue ArgumentError
21
61
  raise_unsupported_coercion(str, __method__)
22
62
  end
63
+
64
+ private
65
+
66
+ def raise_unsupported_coercion(value, method)
67
+ raise(
68
+ ENVied::Coercer::UnsupportedCoercion,
69
+ "#{self.class}##{method} doesn't know how to coerce #{value.inspect}"
70
+ )
71
+ end
23
72
  end
@@ -2,21 +2,13 @@ class ENVied
2
2
  class Configuration
3
3
  attr_reader :current_group, :defaults_enabled, :coercer
4
4
 
5
- def initialize(options = {}, &block)
5
+ def initialize(**options, &block)
6
6
  @coercer = options.fetch(:coercer, Coercer.new)
7
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
-
19
- def self.load(options = {})
11
+ def self.load(**options)
20
12
  envfile = File.expand_path('Envfile')
21
13
  new(options).tap do |v|
22
14
  v.instance_eval(File.read(envfile), envfile)
@@ -33,13 +25,9 @@ class ENVied
33
25
  @defaults_enabled
34
26
  end
35
27
 
36
- def variable(name, *args)
37
- options = args.last.is_a?(Hash) ? args.pop : {}
38
- type = args.first || :string
39
-
28
+ def variable(name, type = :string, **options)
40
29
  unless coercer.supported_type?(type)
41
- raise ArgumentError,
42
- "Variable type (of #{name}) should be one of #{coercer.supported_types}"
30
+ raise ArgumentError, "#{type.inspect} is not a supported type. Should be one of #{coercer.supported_types}"
43
31
  end
44
32
  options[:group] = current_group if current_group
45
33
  variables << ENVied::Variable.new(name, type, options)
@@ -57,6 +45,15 @@ class ENVied
57
45
  def variables
58
46
  @variables ||= []
59
47
  end
60
- end
61
48
 
49
+ private
50
+
51
+ def defaults_enabled_default
52
+ if ENV['ENVIED_ENABLE_DEFAULTS'].nil?
53
+ false
54
+ else
55
+ @coercer.coerce(ENV['ENVIED_ENABLE_DEFAULTS'], :boolean)
56
+ end
57
+ end
58
+ end
62
59
  end