The --env=
option not behaving as expected. Or, at least not the way it used to.
In this example repo, you'll see a "base" .env
file which sets BASE_ENV_VAR="value for base"
and has a blank OTHER_ENV_VAR=
.
The .env.local
file declares OTHER_ENV_VAR="value for other"
.
The .env.empty
is just an empty file, with no content.
Finally the Procfile
has a single entry that runs the read_some_env_vars
Ruby executable script.
That script just prints out the values of ENV["BASE_ENV_VAR"]
and ENV["OTHER_ENV_VAR"]
.
Running the executable Ruby script directly results in exactly what we'd expect, both values being not_set
:
$ ./read_some_env_vars
⚠️
BASE_ENV_VAR=not_set
OTHER_ENV_VAR=not_set
⚠️
Then using heroku local:run
we would expect to see the values from the .env
, and we do:
$ heroku local:run ./read_some_env_vars
[OKAY] Loaded ENV .env File as KEY=VALUE Format
⚠️
BASE_ENV_VAR=value for base
OTHER_ENV_VAR=
⚠️
In the Heroku CLI prior to 8.2, passing --env=/dev/null
(or any empty file) as the Environment file would result in nothing additional being loaded into the ENV
.
We would do this because we need to load multiple files, in a certain order, to match the behavior of dotenv-rails
's loading.
Specifically, we want to load .env.local
(ignored from our Git repo) first, and then .env
(checked into Git).
The .env
hold base configuration needed, and a number of blank values with comments explaining what these are used for.
Then the ignored-from-Git .env.local
overrides some of the entries from the .env
file.
Using our earlier example, we'll now send --env=/dev/null
and then --env=.env.empty
.
In both cases we'd expect to see output similar to directly running the read_some_env_vars
script - not_set
for both.
But… instead we see the values from the .env
file:
$ heroku local:run ./read_some_env_vars --env=/dev/null
[OKAY] Loaded ENV /dev/null File as KEY=VALUE Format
⚠️
BASE_ENV_VAR=value for base
OTHER_ENV_VAR=
⚠️
$ heroku local:run ./read_some_env_vars --env=.env.empty
[OKAY] Loaded ENV .env.empty File as KEY=VALUE Format
⚠️
BASE_ENV_VAR=value for base
OTHER_ENV_VAR=
⚠️
If we use the dotenv
executable to load .env.local
before we run heroku local
, we would only expect to see BASE_ENV_VAR
as not_set
, with OTHER_ENV_VAR
having the value from .env.local
.
Again, we don't get what we'd expect.
We do see the OTHER_ENV_VAR
with the expected value from .env.local
, so that's good!
But we also see the BASE_ENV_VAR
value from .env
.
And that's bad.
$ dotenv -f .env.local heroku local:run ./read_some_env_vars --env=/dev/null
[OKAY] Loaded ENV /dev/null File as KEY=VALUE Format
⚠️
BASE_ENV_VAR=value for base
OTHER_ENV_VAR=value for other
⚠️
Finally, if we tell heroku local
to explicitly load just the .env.local
, we see it do that, and also load the .env
.
Which it should not!
$ heroku local:run ./read_some_env_vars --env=.env.local
[OKAY] Loaded ENV .env.local File as KEY=VALUE Format
⚠️
BASE_ENV_VAR=value for base
OTHER_ENV_VAR=value for other
⚠️
Something changed from Heroku CLI 8.1.9 to 8.2+ wherein the .env
file is being loaded regardless of the list of files given via the --env
argument.