Post

Isolated development with direnv & devbox (& gum)

In this blog we will talk about 3 tools to make a deal with multiple environments easier.

Isolated development with direnv & devbox (& gum)

In real world development, we have to maintain environment variables e.g. target urls, service port number, database table name, etc. It would sound messy if we have to declare those variables every time we open an IDE, and would be more pain if we need to switch to another environment.

In this blog we will talk about 3 tools to make a deal with multiple environments easier.

  1. direnv to get folder ready for environment variables.
  2. devbox to make a folder isolated like a container for packages installed.
  3. gum to switch environment easily.

plus a big advantage for team collaboration because they are file-based that we can push to the repo (with proper security management).


direnv for env

direnv is a tool to setup environment when access a prepared folder. for example, we enter a folder of python and it automatically activates venv for us.

direnv setup

  1. we need to install direnv. in my setup, i installed it through homebrew.
  2. once it’s installed, add the hook into your shell file. in my setup that uses zsh, i just add this line into my ~/.zshrc.
1
eval "$(direnv hook zsh)"

and that’s it. we are ready to initial my folder.

direnv usage

auto-scripts

say we want to develop a python app. once we created venv, we have to activate it first, and deactivate at last, right?

with direnv we don’t have to do so. just enter the folder and it will activate and deactivate when leave the folder for us. follow this.

  1. create venv venv
  2. create .envrc to activate venv. end with layout python
  1. Make sure we are in the folder and direnv allow to execute .envrc allow
  2. Leave the folder and see direnv deactivate the environment. leave

We can check Python venv with command which pip. The figure above represent my prompt showing venv from Oh-my-posh installed. Learn more about it from my dotfiles or https://ohmyposh.dev.

embedded env vars

Beside of that auto-script, the another main objective of direnv is to embed variables into the environment.

Let’s say we embed a variable env into this folder. .envrc would look like this.

When we direnv allow and enter the folder, we will access the variable env. And get nothing when leave the folder.

env

Now we don’t have to create and remove variables we declared over and over again.

Our lives go easier by +1 step.


devbox for packages

Move to another tool. devbox enables a directory installs packages locally

devbox setup

1
curl -fsSL https://get.jetify.com/devbox | bash

If that is the error Error: Unable to find nix startup file, please try installing Nix package manager.

1
sh <(curl -L https://nixos.org/nix/install) # for macos

devbox usage

First, init it.

1
devbox init

then we can see a file “devbox.json”.

Now we need to find the packages we want to install using devbox search like this.

1
2
devbox search package
devbox search package@version

search

Okay, we are gonna add Python 3.10 via

1
devbox add [email protected]

If this is a first time, devbox will install nix package manager if it’s not installed yet.

devbox first time

Next time we can see the package has been being installed.

devbox add after

Then we should see the updated “devbox.json” like this.

The packages shows “[email protected]” (line 4) right there.

Next we start with the command below.

1
devbox shell # start shell

And we can see the python environment has been created. Basically venv folder named “.venv”.

And exit at the end.

1
exit # exit shell

devbox shell

However the env is in .venv. We can custom the folder name by adding env (line 17-19) and apply it in init_hook (line 9) like this.

combo direnv & devbox

With devbox, we have no need to create venv beforehand because devbox will do it for us but we have to run shell and activate every time.

We can combo devbox with direnv to run shell automatically with this command.

1
devbox generate direnv

devbox gen direnv

.envrc generated this way will be like this.

At this step, we now control packages and access the environment at ease.


gum for multiple env

Okay we now are able to build an isolated workspace. How about maintaining multiple environment such as dev & prod?

Of course we have to prepare multiple files for each environment. And it will be good if we can switch from an environment to another.

We are talking about gum.

gum is a tiny tool to represent designated prompt for a specific task. It works great and flexible in operations using shell scripts. Here we will see how can we utilize gum to work with multiple environment.

gum setup

Install via homebrew.

1
brew install gum

or others by your preferences by visiting the link in references below.

gum usage

With gum alone, we can create a simple shell prompt like this.

gum choose

And we will adapt with our setup earlier.

Say we have 2 environments; dev & prod. Also there are 2 env files like this.

gum env

And the structure becomes as below.

We will use a flag of devbox for direnv to select each of both files like this. That flag is --env-file followed by a target env filepath. It will turn out like this in .envrc.

  • ls .envs to list all files in .envs folder.
  • gum choose to prompt choosing files from ls above.
  • --env-file to input chosen files from gum prompt.

And we run direnv allow. Finally we can select any env file to start an environment to work with.

gum select select an env file

gum show activate selected env


Repo


References

This post is licensed under CC BY 4.0 by the author.