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.
direnv
to get folder ready for environment variables.devbox
to make a folder isolated like a container for packages installed.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
- We need to install
direnv
. In my setup, I installed it through homebrew. - 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
.
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.
- Create
venv
- Create
.envrc
to activatevenv
. End withlayout python
- Make sure we are in the folder and
direnv allow
to execute.envrc
- Leave the folder and see
direnv
deactivate the environment.
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.
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
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.
sh <(curl -L https://nixos.org/nix/install) # for macos
devbox
usage
First, init it
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.
devbox search package
devbox search package@version
Okay, we are gonna add Python 3.10 via
devbox add [email protected]
If this is a first time, devbox
will install nix package manager if it's not installed yet.
Next time we can see the package has been being installed.
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.
devbox shell # start shell
And we can see the python environment has been created. Basically venv
folder named ".venv".
And exit at the end.
exit # exit 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.
devbox generate 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.
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.
And we will adapt with our setup earlier.
Say we have 2 environments; dev
& prod
. Also there are 2 env
files like this.
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 fromls
above.--env-file
to input chosen files fromgum
prompt.
And we run direnv allow
. Finally we can select any env
file to start an environment to work with.
Repo
References
direnv
https://direnv.netdirenv
wiki https://github.com/direnv/direnv/wikihomebrew
https://www.bluebirz.net/en/homebrew-one-place-for-all/devbox
by jetify https://www.jetify.com/devbox/- Nix package manager https://nixos.org/download/
gum
https://github.com/charmbracelet/gum