dotenv 2.5.0 → 2.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
- SHA1:
3
- metadata.gz: 2e64cd0a67971ea4a843e624a6362e89b623697c
4
- data.tar.gz: 7dd0bbd8488f581d5dbf1f4bfcdc5c3e97bdf623
2
+ SHA256:
3
+ metadata.gz: ac1a9e8e04f95f111da23bf2541070f2617864fc3c55ac4e11e6b91c78d11a9b
4
+ data.tar.gz: 24bf24be5be7020e72877e32d8cd2d9cf022a74b182569c77b2c81c0d482696b
5
5
  SHA512:
6
- metadata.gz: e7e8fcbb2f35999a5e3ccf1d6f37b97aa6d21ddffbb59235cad590b15d1e9e74356da50174393de20cde97395046fe4f48edf8a5aec59d5901117c21cb94f953
7
- data.tar.gz: fed27a558c70aa6d7b0f435f16b437c0be83a60c1525c6afe89add406e68ec94c3ebdffbc6698c3ae8952ce1cab576c2bab683e11e68ca2f40c5d16778ab2c97
6
+ metadata.gz: 1f8d6ae3bfd67c1b57bc4d72346d670c02570d07cee953930d6b7f9018cc053ac42624d1bc4d59dd112abe5ba711d551199ff92a2672d5434577356b0a24d0c0
7
+ data.tar.gz: 38488d0f24d6f6014f87415775f94969cd56236bcb848c77b5dd4d066285ec47993006f87f1ab1afb50a033db101fe206741ec8e561de602a88717ad6fff3bdf
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- # dotenv [![Build Status](https://secure.travis-ci.org/bkeepers/dotenv.png?branch=master)](https://travis-ci.org/bkeepers/dotenv) [![Gem Version](https://badge.fury.io/rb/dotenv.svg)](https://badge.fury.io/rb/dotenv) [![Join the chat at https://gitter.im/bkeepers/dotenv](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bkeepers/dotenv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
1
+ # dotenv [![Gem Version](https://badge.fury.io/rb/dotenv.svg)](https://badge.fury.io/rb/dotenv) [![Join the chat at https://gitter.im/bkeepers/dotenv](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/bkeepers/dotenv?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
2
2
 
3
3
  Shim to load environment variables from `.env` into `ENV` in *development*.
4
4
 
@@ -30,7 +30,10 @@ dotenv is initialized in your Rails app during the `before_configuration` callba
30
30
  # config/application.rb
31
31
  Bundler.require(*Rails.groups)
32
32
 
33
- Dotenv::Railtie.load
33
+ # Load dotenv only in development or test environment
34
+ if ['development', 'test'].include? ENV['RAILS_ENV']
35
+ Dotenv::Railtie.load
36
+ end
34
37
 
35
38
  HOSTNAME = ENV['HOSTNAME']
36
39
  ```
@@ -62,7 +65,7 @@ Dotenv.load
62
65
 
63
66
  By default, `load` will look for a file called `.env` in the current working directory. Pass in multiple files and they will be loaded in order. The first value set for a variable will win.
64
67
 
65
- ```
68
+ ```ruby
66
69
  require 'dotenv'
67
70
  Dotenv.load('file1.env', 'file2.env')
68
71
  ```
@@ -163,6 +166,31 @@ SECRET_KEY=YOURSECRETKEYGOESHERE # comment
163
166
  SECRET_HASH="something-with-a-#-hash"
164
167
  ```
165
168
 
169
+ ### Required Keys
170
+
171
+ If a particular configuration value is required but not set, it's appropriate to raise an error.
172
+
173
+ To require configuration keys:
174
+
175
+ ```ruby
176
+ # config/initializers/dotenv.rb
177
+
178
+ Dotenv.require_keys("SERVICE_APP_ID", "SERVICE_KEY", "SERVICE_SECRET")
179
+ ```
180
+
181
+ If any of the configuration keys above are not set, your application will raise an error during initialization. This method is preferred because it prevents runtime errors in a production application due to improper configuration.
182
+
183
+ ### Parsing
184
+
185
+ To parse a list of env files for programmatic inspection without modifying the ENV:
186
+
187
+ ```ruby
188
+ Dotenv.parse(".env.local", ".env")
189
+ # => {'S3_BUCKET' => 'YOURS3BUCKET', 'SECRET_KEY' => 'YOURSECRETKEYGOESHERE', ...}
190
+ ```
191
+
192
+ This method returns a hash of the ENV var name/value pairs.
193
+
166
194
  ## Frequently Answered Questions
167
195
 
168
196
  ### Can I use dotenv in production?
@@ -175,23 +203,58 @@ If you use this gem to handle env vars for multiple Rails environments (developm
175
203
 
176
204
  ### What other .env* files can I use?
177
205
 
178
- `dotenv-rails` will load the following files, starting from the bottom. The first value set (or those already defined in the environment) take precedence:
206
+ `dotenv-rails` will override in the following order (highest defined variable overrides lower):
207
+
208
+ | Hierarchy Priority | Filename | Environment | Should I `.gitignore`it? | Notes |
209
+ | ------------------ | ------------------------ | -------------------- | --------------------------------------------------- | ------------------------------------------------------------ |
210
+ | 1st (highest) | `.env.development.local` | Development | Yes! | Local overrides of environment-specific settings. |
211
+ | 1st | `.env.test.local` | Test | Yes! | Local overrides of environment-specific settings. |
212
+ | 1st | `.env.production.local` | Production | Yes! | Local overrides of environment-specific settings. |
213
+ | 2nd | `.env.local` | Wherever the file is | Definitely. | Local overrides. This file is loaded for all environments _except_ `test`. |
214
+ | 3rd | `.env.development` | Development | No. | Shared environment-specific settings |
215
+ | 3rd | `.env.test` | Test | No. | Shared environment-specific settings |
216
+ | 3rd | `.env.production` | Production | No. | Shared environment-specific settings |
217
+ | Last | `.env` | All Environments | Depends (See [below](#should-i-commit-my-env-file)) | The Original® |
179
218
 
180
- - `.env` - The Original®
181
- - `.env.development`, `.env.test`, `.env.production` - Environment-specific settings.
182
- - `.env.local` - Local overrides. This file is loaded for all environments _except_ `test`.
183
- - `.env.development.local`, `.env.test.local`, `.env.production.local` - Local overrides of environment-specific settings.
184
219
 
185
220
  ### Should I commit my .env file?
186
221
 
187
222
  Credentials should only be accessible on the machines that need access to them. Never commit sensitive information to a repository that is not needed by every development machine and server.
188
223
 
224
+
225
+ You can use the `-t` or `--template` flag on the dotenv cli to create a template of your `.env` file.
226
+ ```shell
227
+ $ dotenv -t .env
228
+ ```
229
+ A template will be created in your working directory named `{FINAME}.template`. So in the above example, it would create a `.env.template` file.
230
+
231
+ The template will contain all the environment variables in your `.env` file but with their values set to the variable names.
232
+
233
+ ```shell
234
+ # .env
235
+ S3_BUCKET=YOURS3BUCKET
236
+ SECRET_KEY=YOURSECRETKEYGOESHERE
237
+ ```
238
+
239
+ Would become
240
+
241
+ ```shell
242
+ # .env.template
243
+ S3_BUCKET=S3_BUCKET
244
+ SECRET_KEY=SECRET_KEY
245
+ ```
246
+
189
247
  Personally, I prefer to commit the `.env` file with development-only settings. This makes it easy for other developers to get started on the project without compromising credentials for other environments. If you follow this advice, make sure that all the credentials for your development environment are different from your other deployments and that the development credentials do not have access to any confidential data.
190
248
 
191
249
  ### Why is it not overriding existing `ENV` variables?
192
250
 
193
251
  By default, it **won't** overwrite existing environment variables as dotenv assumes the deployment environment has more knowledge about configuration than the application does. To overwrite existing environment variables you can use `Dotenv.overload`.
194
252
 
253
+ You can also use the `-o` or `--overload` flag on the dotenv cli to override existing `ENV` variables.
254
+ ```shell
255
+ $ dotenv -o -f ".env.local,.env"
256
+ ```
257
+
195
258
  ## Contributing
196
259
 
197
260
  If you want a better idea of how dotenv works, check out the [Ruby Rogues Code Reading of dotenv](https://www.youtube.com/watch?v=lKmY_0uY86s).
data/lib/dotenv/cli.rb CHANGED
@@ -1,36 +1,57 @@
1
1
  require "dotenv"
2
+ require "dotenv/version"
3
+ require "dotenv/template"
4
+ require "optparse"
2
5
 
3
6
  module Dotenv
4
- # The CLI is a class responsible of handling all the command line interface
5
- # logic.
6
- class CLI
7
- attr_reader :argv
7
+ # The command line interface
8
+ class CLI < OptionParser
9
+ attr_reader :argv, :filenames, :overload
8
10
 
9
11
  def initialize(argv = [])
10
12
  @argv = argv.dup
13
+ @filenames = []
14
+ @overload = false
15
+
16
+ super "Usage: dotenv [options]"
17
+ separator ""
18
+
19
+ on("-f FILES", Array, "List of env files to parse") do |list|
20
+ @filenames = list
21
+ end
22
+
23
+ on("-o", "--overload", "override existing ENV variables") do
24
+ @overload = true
25
+ end
26
+
27
+ on("-h", "--help", "Display help") do
28
+ puts self
29
+ exit
30
+ end
31
+
32
+ on("-v", "--version", "Show version") do
33
+ puts "dotenv #{Dotenv::VERSION}"
34
+ exit
35
+ end
36
+
37
+ on("-t", "--template=FILE", "Create a template env file") do |file|
38
+ template = Dotenv::EnvTemplate.new(file)
39
+ template.create_template
40
+ end
41
+
42
+ order!(@argv)
11
43
  end
12
44
 
13
45
  def run
14
- filenames = parse_filenames || []
15
- begin
16
- Dotenv.load!(*filenames)
17
- rescue Errno::ENOENT => e
18
- abort e.message
46
+ if @overload
47
+ Dotenv.overload!(*@filenames)
19
48
  else
20
- exec(*argv) unless argv.empty?
49
+ Dotenv.load!(*@filenames)
21
50
  end
22
- end
23
-
24
- private
25
-
26
- def parse_filenames
27
- pos = argv.index("-f")
28
- return nil unless pos
29
- # drop the -f
30
- argv.delete_at pos
31
- # parse one or more comma-separated .env files
32
- require "csv"
33
- CSV.parse_line argv.delete_at(pos)
51
+ rescue Errno::ENOENT => e
52
+ abort e.message
53
+ else
54
+ exec(*@argv) unless @argv.empty?
34
55
  end
35
56
  end
36
57
  end
@@ -0,0 +1,10 @@
1
+ module Dotenv
2
+ class Error < StandardError; end
3
+
4
+ class MissingKeys < Error # :nodoc:
5
+ def initialize(keys)
6
+ key_word = "key#{keys.size > 1 ? "s" : ""}"
7
+ super("Missing required configuration #{key_word}: #{keys.inspect}")
8
+ end
9
+ end
10
+ end
data/lib/dotenv/parser.rb CHANGED
@@ -12,21 +12,21 @@ module Dotenv
12
12
  [Dotenv::Substitutions::Variable, Dotenv::Substitutions::Command]
13
13
 
14
14
  LINE = /
15
- (?:^|\A) # beginning of line
16
- \s* # leading whitespace
17
- (?:export\s+)? # optional export
18
- ([\w\.]+) # key
19
- (?:\s*=\s*?|:\s+?) # separator
20
- ( # optional value begin
21
- '(?:\\'|[^'])*' # single quoted value
22
- | # or
23
- "(?:\\"|[^"])*" # double quoted value
24
- | # or
25
- [^\#\r\n]+ # unquoted value
26
- )? # value end
27
- \s* # trailing whitespace
28
- (?:\#.*)? # optional comment
29
- (?:$|\z) # end of line
15
+ (?:^|\A) # beginning of line
16
+ \s* # leading whitespace
17
+ (?:export\s+)? # optional export
18
+ ([\w.]+) # key
19
+ (?:\s*=\s*?|:\s+?) # separator
20
+ ( # optional value begin
21
+ \s*'(?:\\'|[^'])*' # single quoted value
22
+ | # or
23
+ \s*"(?:\\"|[^"])*" # double quoted value
24
+ | # or
25
+ [^\#\r\n]+ # unquoted value
26
+ )? # value end
27
+ \s* # trailing whitespace
28
+ (?:\#.*)? # optional comment
29
+ (?:$|\z) # end of line
30
30
  /x
31
31
 
32
32
  class << self
@@ -70,17 +70,9 @@ module Dotenv
70
70
  def parse_value(value)
71
71
  # Remove surrounding quotes
72
72
  value = value.strip.sub(/\A(['"])(.*)\1\z/m, '\2')
73
-
74
- if Regexp.last_match(1) == '"'
75
- value = unescape_characters(expand_newlines(value))
76
- end
77
-
78
- if Regexp.last_match(1) != "'"
79
- self.class.substitutions.each do |proc|
80
- value = proc.call(value, @hash, @is_load)
81
- end
82
- end
83
- value
73
+ maybe_quote = Regexp.last_match(1)
74
+ value = unescape_value(value, maybe_quote)
75
+ perform_substitutions(value, maybe_quote)
84
76
  end
85
77
 
86
78
  def unescape_characters(value)
@@ -94,5 +86,24 @@ module Dotenv
94
86
  def variable_not_set?(line)
95
87
  !line.split[1..-1].all? { |var| @hash.member?(var) }
96
88
  end
89
+
90
+ def unescape_value(value, maybe_quote)
91
+ if maybe_quote == '"'
92
+ unescape_characters(expand_newlines(value))
93
+ elsif maybe_quote.nil?
94
+ unescape_characters(value)
95
+ else
96
+ value
97
+ end
98
+ end
99
+
100
+ def perform_substitutions(value, maybe_quote)
101
+ if maybe_quote != "'"
102
+ self.class.substitutions.each do |proc|
103
+ value = proc.call(value, @hash, @is_load)
104
+ end
105
+ end
106
+ value
107
+ end
97
108
  end
98
109
  end
@@ -13,7 +13,7 @@ module Dotenv
13
13
  \$ # literal $
14
14
  (?<cmd> # collect command content for eval
15
15
  \( # require opening paren
16
- ([^()]|\g<cmd>)+ # allow any number of non-parens, or balanced
16
+ (?:[^()]|\g<cmd>)+ # allow any number of non-parens, or balanced
17
17
  # parens (by nesting the <cmd> expression
18
18
  # recursively)
19
19
  \) # require closing paren
@@ -19,11 +19,7 @@ module Dotenv
19
19
  /xi
20
20
 
21
21
  def call(value, env, is_load)
22
- combined_env = if is_load
23
- env.merge(ENV)
24
- else
25
- ENV.to_h.merge(env)
26
- end
22
+ combined_env = is_load ? env.merge(ENV) : ENV.to_h.merge(env)
27
23
  value.gsub(VARIABLE) do |variable|
28
24
  match = $LAST_MATCH_INFO
29
25
  substitute(match, variable, combined_env)
@@ -33,7 +29,7 @@ module Dotenv
33
29
  private
34
30
 
35
31
  def substitute(match, variable, env)
36
- if match[1] == '\\'
32
+ if match[1] == "\\"
37
33
  variable[1..-1]
38
34
  elsif match[3]
39
35
  env.fetch(match[3], "")
@@ -0,0 +1,26 @@
1
+ module Dotenv
2
+ EXPORT_COMMAND = "export ".freeze
3
+ # Class for creating a template from a env file
4
+ class EnvTemplate
5
+ def initialize(env_file)
6
+ @env_file = env_file
7
+ end
8
+
9
+ def create_template
10
+ File.open(@env_file, "r") do |env_file|
11
+ File.open("#{@env_file}.template", "w") do |env_template|
12
+ env_file.each do |line|
13
+ env_template.puts template_line(line)
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ def template_line(line)
20
+ var, value = line.split("=")
21
+ template = var.gsub(EXPORT_COMMAND, "")
22
+ is_a_comment = var.strip[0].eql?("#")
23
+ value.nil? || is_a_comment ? line : "#{var}=#{template}"
24
+ end
25
+ end
26
+ end
@@ -1,3 +1,3 @@
1
1
  module Dotenv
2
- VERSION = "2.5.0".freeze
2
+ VERSION = "2.8.1".freeze
3
3
  end
data/lib/dotenv.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "dotenv/parser"
2
2
  require "dotenv/environment"
3
+ require "dotenv/missing_keys"
3
4
 
4
5
  # The top level Dotenv module. The entrypoint for the application logic.
5
6
  module Dotenv
@@ -36,6 +37,23 @@ module Dotenv
36
37
  end
37
38
  end
38
39
 
40
+ # same as `overload`, but raises Errno::ENOENT if any files don't exist
41
+ def overload!(*filenames)
42
+ with(*filenames) do |f|
43
+ env = Environment.new(f, false)
44
+ instrument("dotenv.overload", env: env) { env.apply! }
45
+ end
46
+ end
47
+
48
+ # returns a hash of parsed key/value pairs but does not modify ENV
49
+ def parse(*filenames)
50
+ with(*filenames) do |f|
51
+ ignoring_nonexistent_files do
52
+ Environment.new(f, false)
53
+ end
54
+ end
55
+ end
56
+
39
57
  # Internal: Helper to expand list of filenames.
40
58
  #
41
59
  # Returns a hash of all the loaded environment variables.
@@ -55,6 +73,12 @@ module Dotenv
55
73
  end
56
74
  end
57
75
 
76
+ def require_keys(*keys)
77
+ missing_keys = keys.flatten - ::ENV.keys
78
+ return if missing_keys.empty?
79
+ raise MissingKeys, missing_keys
80
+ end
81
+
58
82
  def ignoring_nonexistent_files
59
83
  yield
60
84
  rescue Errno::ENOENT
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dotenv
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.8.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brandon Keepers
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-06-21 00:00:00.000000000 Z
11
+ date: 2022-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -39,19 +39,19 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: rubocop
42
+ name: standard
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: 0.40.0
47
+ version: '0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: 0.40.0
54
+ version: '0'
55
55
  description: Loads environment variables from `.env`.
56
56
  email:
57
57
  - brandon@opensoul.org
@@ -67,16 +67,18 @@ files:
67
67
  - lib/dotenv/cli.rb
68
68
  - lib/dotenv/environment.rb
69
69
  - lib/dotenv/load.rb
70
+ - lib/dotenv/missing_keys.rb
70
71
  - lib/dotenv/parser.rb
71
72
  - lib/dotenv/substitutions/command.rb
72
73
  - lib/dotenv/substitutions/variable.rb
73
74
  - lib/dotenv/tasks.rb
75
+ - lib/dotenv/template.rb
74
76
  - lib/dotenv/version.rb
75
77
  homepage: https://github.com/bkeepers/dotenv
76
78
  licenses:
77
79
  - MIT
78
80
  metadata: {}
79
- post_install_message:
81
+ post_install_message:
80
82
  rdoc_options: []
81
83
  require_paths:
82
84
  - lib
@@ -91,9 +93,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
91
93
  - !ruby/object:Gem::Version
92
94
  version: '0'
93
95
  requirements: []
94
- rubyforge_project:
95
- rubygems_version: 2.6.13
96
- signing_key:
96
+ rubygems_version: 3.2.32
97
+ signing_key:
97
98
  specification_version: 4
98
99
  summary: Loads environment variables from `.env`.
99
100
  test_files: []