direnv / direnv

unclutter your .profile
http://direnv.net
MIT License
12.25k stars 628 forks source link

Multiple dotenv #544

Open jandudulski opened 4 years ago

jandudulski commented 4 years ago

It's often a case that locally developer has different environment variables depending if just running the app or running tests (like e.g. database url).

Ruby dotenv allows you to have multiple different .env files with environment name suffix like .env.local, .env.development or .env.test.local.

It would be really helpful if I could somehow dynamically switch between dotenv files depending on some defined context or at least easy way to make a switch with a command. Or maybe it's already possible somehow?

zimbatm commented 4 years ago

You could write a little direnv-switch wrapper function like this:

#!/usr/bin/env bash
# Usage: direnv-switch <env-name>
set -euo pipefail

# take the env as the first argument
env_name=$1
env_file=.env.${env_name}

# check if the .env.$env_name exists
if [[ ! -f $env_file ]]; then
  echo "env $env_name not found" >&2
  exit 1
fi

# create a new .envrc for the user
cat <<NEW_ENVRC > .envrc
log Loading environment "$env_name"
dotenv "$env_file"
NEW_ENVRC
# allow the execution
direnv allow .

The script assumes that the user is at the repo root, you can maybe first cd "$(git rev-parse --show-toplevel)" if you are using git for development.

The user then run:

$ direnv-switch test
direnv: loading .envrc
Loading environment "test"
direnv: export ...
$ 

You might also want to add a default environment, handling for .local files, ...

The main downside is that all shells will switch to that environment on next prompt.

glensc commented 4 years ago

Perhaps different request, but I would like to load .envrc, .envrc.dist, .envrc.local, i.e load when present, without extra dynamic logic for variable filename.

The purpose is to keep .envrc.dist in VCS for sharing with other devlopers, while adding .envrc.local to .gitignore

bronislav commented 4 years ago

@glensc You may add .envrc file to the VCS and add following to the end of it:

[[ -f .envrc.local ]] && dotenv ".envrc.local"
sigprof commented 2 years ago

Beware that the solution suggested in the above comment is insecure — if .envrc.local does not exist in the working copy, it may arrive from VCS in a subsequent update, then it will be executed without any verification.

donhector commented 1 year ago

I'm happy with the following approach in my .envrc as it allows for different override levels:

# Load any .envrc files all the way till /
source_up

# Load .env file if exists
dotenv_if_exists

# Load environment specific overrides if exists
test -f ".env.${APP_ENV}" && dotenv ".env.${APP_ENV}"

# Load local overrides if exists
test -f .env.local && dotenv .env.local

Just export APP_ENV whenever you need one, either in the shell directly or by adding it in your .env file.

Don't forget to adjust your .gitignore with whatever dot env files you don't want committed.

cloud303-cholden commented 8 months ago

Script

#!/usr/bin/env bash

env_name=$1
cp "$env_name".env .envrc
sed -i 's/^/export /' .envrc
direnv allow

Example

  1. I named the script de and put it in ~/.local/bin so it works everywhere.
  2. Create environment files like local.env and prod.env:
    
    # local.env

FOO=BAR

3. Run `de local`.
4. The script creates the following `.envrc` and automatically runs `direnv allow`:

.envrc

export FOO=BAR