Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dotenv.load behavior is different from Dotenv.parse #392

Closed
amanfredi opened this issue Jun 14, 2019 · 7 comments
Closed

Dotenv.load behavior is different from Dotenv.parse #392

amanfredi opened this issue Jun 14, 2019 · 7 comments
Labels

Comments

@amanfredi
Copy link

Steps to reproduce

Tell us how to reproduce the issue.
Show how you included dotenv (Gemfile).

amanfredi@Anthonys-MacBook-Pro-3:[~]$ gem list | grep dotenv
dotenv (2.7.2)
amanfredi@Anthonys-MacBook-Pro-3:[~]$ cat .env
MY_ENV_VAR='development'
amanfredi@Anthonys-MacBook-Pro-3:[~]$ cat .env.production
MY_ENV_VAR='production'

irb(main):001:0> require 'dotenv'
=> true
irb(main):006:0> vars = Dotenv.parse(*['.env.production','.env'].compact)
=> {"MY_ENV_VAR"=>"development"}
irb(main):003:0> Dotenv.load(*['.env.production','.env'])
=> {"MY_ENV_VAR"=>"development"}
irb(main):004:0> ENV['MY_ENV_VAR']
=> "production"

Expected behavior

MY_ENV_VAR should be 'production' in the return value
The documentation says that the "most important" files should be passed first, and that the first value set will be kept. This is consistent with the order of filenames defined in lib/dotenv/rails.rb
'.env' comes last and we expect that values in later files are only used if they are not already set by a prior file.

Actual behavior

MY_ENV_VAR is 'development'
The actual behavior is the reverse. The last file passed to dotenv has the highest priority.

System configuration

dotenv version: 2.7.2

Rails version: N/A

Ruby version: ruby 2.2.3p173 (2015-08-18 revision 51636) [x86_64-darwin15]

@stale
Copy link

stale bot commented Aug 13, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Aug 13, 2019
@amanfredi
Copy link
Author

I can look at putting together a PR for this.

@stale stale bot removed the wontfix label Aug 14, 2019
@mobilutz
Copy link

mobilutz commented Sep 9, 2019

I just stumbled over that problem.
And it actually lead to my local development DB being deleted completely ☹️

@stale
Copy link

stale bot commented Nov 8, 2019

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the wontfix label Nov 8, 2019
@stale stale bot closed this as completed Nov 15, 2019
@mobilutz
Copy link

@amanfredi I just see, that README says:

By default, load [...]. The first value set for a variable will win.

So it seems, that this situation mentioned in this issue in itself is not really a bug, but a big change in behaviour.
I think the biggest thing that leads someone to think that there is an error is, that calling Dotenv.load(*['.env.production','.env']) returns the content of the last file, plus anything that came in previous files, see this:

> cat .env
MY_ENV_VAR='development'
MY_SECOND_ENV_VAR='development'
> cat .env.production
MY_ENV_VAR='production'
MY_THIRD_ENV_VAR='production'

> irb
irb(main):001:0> require 'dotenv'
=> true
irb(main):002:0> Dotenv.load(*['.env.production','.env'])
=> {"MY_ENV_VAR"=>"development", "MY_THIRD_ENV_VAR"=>"production", "MY_SECOND_ENV_VAR"=>"development"}
irb(main):003:0> ENV['MY_ENV_VAR']
=> "production"

I expected Dotenv.load to return hash with "MY_ENV_VAR" => "production".
Like I said, this seems to be the biggest problem here in my opinion.

@nruth
Copy link

nruth commented Jan 13, 2020

It does say that, and the parse example

Dotenv.parse(".env.local", ".env")
# => {'S3_BUCKET' => 'YOURS3BUCKET', 'SECRET_KEY' => 'YOURSECRETKEYGOESHERE', ...}

follows the idiom of the .env.local values winning, but Dotenv.parse doesn't actually do that right now, the values in .env win, so there is a bug (reproduced in v 2.7.1 and current 2.7.5).

Parse was added recently in #362 and the test coverage doesn't actually cover overriding any values (look at the fixtures, their values do not intersect). Needs a PR.
https://github.com/bkeepers/dotenv/blob/master/spec/dotenv_spec.rb#L225
https://github.com/bkeepers/dotenv/blob/master/spec/fixtures/plain.env
https://github.com/bkeepers/dotenv/blob/master/spec/fixtures/.env

I'll try to improve the test as a starting point.

@nruth
Copy link

nruth commented Jan 13, 2020

If you want to script around this in a way that won't break if/when the bug is fixed, you might try something like:

require "dotenv"
env = Dotenv.parse(".env.development")
local_env = Dotenv.parse(".env.development.local")
envs = env.merge(local_env)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants