Closed nonrational closed 2 years ago
I'm going to quickly restate the problem this PR is trying to solve to make sure I understand it correctly.
The current technique (master
) for loading environment variables is this:
os.Environ()
THREADS
, WORKERS
, and CONFIG
values to the environment variable list$SHELL
if set, /bin/bash
otherwise. Pass in the computed environment.
bash
shell
cd
to the path
of the app (not the destPath
), basically just the symlink in ~/.puma-dev
source
env files (~/.powconfig
, .env
, .powrc
, .powenv
, .pumaenv
)exec
pumaProblems with the current approach
$SHELL
that puma-dev
uses since it cannot be modified using an env
file. Users might want to change the $SHELL
if the user has configured zsh
as their normal shell (and their rbenv
or rvm
is configured in .zshrc
, but not in their default $SHELL
). https://github.com/puma/puma-dev/issues/295cwd
of the puma process is unexpectedly set to the symlink in ~/.puma-dev
instead of the actual application directory. https://github.com/puma/puma-dev/issues/248$SHELL
OR a non-login shell in bash
is configured appropriately to find the correct ruby (using rbenv
or rvm
or asdf
or similar), but it's not always obvious how to make this happen.puma
command constructed by puma-dev
sets these values in CLI argsThe proposed solution is this:
os.Environ
to get environment variables for the current puma-dev
process. Try to read all of the env
files in Go (and merge in the values into the current environment). This is done, in part, to determine the correct $SHELL
to use at the top level. If any of the env
files are more complicated than just KEY=value
, then this approach is aborted.$SHELL
determined by reading all of environment variables (falling back to /bin/bash
if unset)
$SHELL
cd
, source
env files, and exec
puma.This solution successfully gives folks the ability to change the shell that puma-dev uses when starting application subprocesses, so it definitely provides an option to people that was not previously available. It has two potential drawbacks, IMO
env
files are more complicated than just KEY=value
declarations, the $SHELL
will not be configured as the user expects.env
files will now be source
d using the specified $SHELL
. I think this can cause problems for teams of devs that use different shells, since they’ll likely share the env
files for their projects. I think it is simpler to standardize that all env
files will be interpreted in bash
, regardless of the user’s preferred shell. This is what the current approach does on master
and is actually identical to tools like direnv
.I think there are two potential paths forward to consider, both of them just alternative ways for the user to specify the $SHELL
for the top-level login shell.
bash
do this work: start a new short-lived bash
subprocess. In that process, just source
all of the env files and print out the value of $SHELL
. This way all env files are interpreted using bash
(so they can do more complicated scripting stuff). Collect the output of this process in Go to determine the $SHELL
to use for the actual application subprocess at the top level (in the login shell). In that subprocess, just do what puma-dev
does currently (start a new bash
shell, source
the env files, and exec
puma).puma-dev -install
option to allow users to specify the shell they want puma to use when starting application subprocesses. We can pass the selected shell as a CLI argument to the puma-dev
process when launched by the init
process.The other thing that's missing is probably just better documentation and better tools for debugging this kind of stuff. It's not super obvious what shells puma-dev
is using, which ones are login shells, and consequently, which files need to be modified to make puma-dev
happy (.bashrc
, .bash_profile
, .zshrc
, etc).
Instead of trying to build the env map in Go, just let bash do this work.
I think this has a lot of benefits. My original intent was to reduce the amount of shell code significantly, but you've convinced me that there's more value in letting shell handle env grooming, rather than restricting ourselves to dotenv-style configs.
This approach also preserves my original intent, namely to get us back into Go after reading the env, so we can build the puma
CLI string in Go, rather than having to do it in pure shell, which is really ugly.
I do worry that now macOS has made zsh the default, it's confusing that we'll still force someone to run bash
under the hood. And, as you say, it becomes doubly confusing to trace where the env actually comes from.
[What's] missing is probably just better documentation and better tools for debugging this kind of stuff
You're totally right. It's incredibly hard to figure out how all of these pieces interact. I'm hopeful that splitting out some of this behavior will make it easier to follow in the code, but will also look for opportunities for logging in the short-term.
So, I think the way forward involves a few changes and, potentially, splitting this PR in 2-3 pieces to keep things straight.
~/.pumaconfig
xor ~/.pumaenv
with the eventual goal of deprecating config files referencing "pow".env
, .pumaenv
, ...) via shell.
bash -l
. Though, if i run zsh
will we still pick up the right env e.g. asdf, rbenv, etc.? If we can't get the exact env in Go that we'll have when puma
's running, its prob not worth it and we should just do everything in shell. I do worry that now macOS has made zsh the default, it's confusing that we'll still force someone to run
bash
under the hood. And, as you say, it becomes doubly confusing to trace where the env actually comes from.
Yeah, I acknowledge that using bash
for this case can be confusing, but I think as long as it is well-documented, it's worth it just to standardize the shell among devs. Even though bash
isn't my favorite interactive shell, it's clear that it's ubiquitous for scripting/env tasks.
So, I think the way forward involves a few changes and, potentially, splitting this PR in 2-3 pieces to keep things straight.
I love this approach of breaking up the work into a few smaller PRs. Feel free to tag me for review for any. The list of steps you laid out seems great!
Related to:
295
248
187
Changes
~/.puma-dev/myapp
) to absoluteappDir
to make relative Gemfile paths workbash
-C
,-t
,-w
) if ENV vars aren't setzsh
to build matrixBinaries
https://github.com/puma/puma-dev/actions/runs/1798040084