Skip to content

Instantly share code, notes, and snippets.

@stevenharman
Last active September 7, 2023 15:56
Show Gist options
  • Save stevenharman/6da9c7ddde7dd02fe0e4421dbff0aa48 to your computer and use it in GitHub Desktop.
Save stevenharman/6da9c7ddde7dd02fe0e4421dbff0aa48 to your computer and use it in GitHub Desktop.

Revisions

  1. stevenharman revised this gist Sep 7, 2023. 1 changed file with 0 additions and 0 deletions.
    Empty file modified read_some_env_vars
    100644 → 100755
    Empty file.
  2. stevenharman revised this gist Aug 29, 2023. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions _README.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    # Heroku CLI Bug

    `--env=` flag not behaving as expected.
    The `--env=` option not behaving as expected. Or, at least not the way it used to.

    ## This minimal reproduction

    @@ -91,4 +91,3 @@ OTHER_ENV_VAR=value for other
    ## Conclusion

    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.

  3. stevenharman revised this gist Aug 29, 2023. 6 changed files with 16 additions and 1 deletion.
    4 changes: 4 additions & 0 deletions .env
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,4 @@
    BASE_ENV_VAR="value for base"

    # Set a value specific to you in your .env.local
    OTHER_ENV_VAR=
    Empty file added .env.empty
    Empty file.
    1 change: 1 addition & 0 deletions .env.local
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    OTHER_ENV_VAR="value for other"
    1 change: 1 addition & 0 deletions Procfile
    Original file line number Diff line number Diff line change
    @@ -0,0 +1 @@
    bug: ruby ./read_some_env_vars
    3 changes: 2 additions & 1 deletion _README.md
    Original file line number Diff line number Diff line change
    @@ -90,4 +90,5 @@ OTHER_ENV_VAR=value for other

    ## Conclusion

    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.
    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.

    8 changes: 8 additions & 0 deletions read_some_env_vars
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    #!/usr/bin/env ruby

    puts <<~EOF
    ⚠️
    BASE_ENV_VAR=#{ENV.fetch("BASE_ENV_VAR", :not_set)}
    OTHER_ENV_VAR=#{ENV.fetch("OTHER_ENV_VAR", :not_set)}
    ⚠️
    EOF
  4. stevenharman created this gist Aug 29, 2023.
    93 changes: 93 additions & 0 deletions _README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,93 @@
    # Heroku CLI Bug

    `--env=` flag not behaving as expected.

    ## This minimal reproduction

    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`:

    ```console
    $ ./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:

    ```console
    $ 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=
    ⚠️
    ```

    ## What's wrong?

    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:

    ```console
    $ 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.

    ```console
    $ 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!

    ```console
    $ 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
    ⚠️
    ```

    ## Conclusion

    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.