-
Notifications
You must be signed in to change notification settings - Fork 249
wrappers] ensure bin-wrappers invoke other binaries and not bin-wrappers #1160
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Current dependencies on/for this PR:
This comment was auto-generated by Graphite. |
160387f
to
9242e8a
Compare
9242e8a
to
8583ba3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
In this case shellenv will be invoked on every binary call, which will impact performance.
As a follow up, perhaps we can generate this PATH env variable and store it in a file. In every wrapped binary, we simply source that file.
The file only needs to be re-generated if __DEVBOX_SHELLENV_HASH_
does not match.
I don't know if you want to re-think this PR that way 🤷♀️
Edit: btw the test is failing because you need to export PGHOST
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice. Thank you. Just one nit comment
func shellEnvOnlyPathWithoutWrappersCmd() *cobra.Command { | ||
flags := shellEnvOnlyPathWithoutWrappersCmdFlags{} | ||
command := &cobra.Command{ | ||
Use: "only-path-without-wrappers", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit, drop the only and let the command be "path-without-wrappers"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤔 I'd prefer leaving it in to make it clear that this is not also returning other env-vars of shellenv.
8583ba3
to
f075729
Compare
That was the case with the fix in #1151 as well. I'm not very concerned because a cached For now, would prefer focussing on correctness, and once we've settled on the final design - optimize it from there. |
## Summary follow up to #1160 correctness: - consolidate some code into calling `wrapnix.GetWrapperBinPath` - the earlier code had a bug where I forgot to call `-c <project dir>`, but that is moot now (see below change) perf: - call DO_NOT_TRACK=1 to minimize segment perf impact - simplify OnlyPathWithoutWrappers to directly call `os.Getenv("PATH")`, remove WrapperBins, and exportify it. This function is used in a very specific context, so we can _know_ we can skip the nix.ComputeEnv calculation. - Doing `time devbox shellenv only-path-without-wrappers` is now consistently ~ 18-25 milliseconds. I have a slight preference for this over writing PATH to a file and sourcing it, since we may run into correctness issues with that file getting outdated, and it'll introduce perf regression on every shellenv call to write the file. ## How was it tested? - [x] testscripts pass - [x] `iex -S mix` works visual inspection: ``` 1 #!/nix/store/w849dr5qcbrrnxv69sy7kdnifa9jpjyf-bash-5.2-p15/bin/bash 2 3 4 5 if [[ "$__DEVBOX_SHELLENV_HASH_ac6a60d54a9d1ba6618cce8d40bfdfb50059d814edfe5f49bca3168c5c34e970" != "b1a4903de70aa4d610ecb00ffb3dd755913b4505651e6bebbf41571a406d415c" ]] & & [[ -z "$__DEVBOX_SHELLENV_HASH_ac6a60d54a9d1ba6618cce8d40bfdfb50059d814edfe5f49bca3168c5c34e970_GUARD" ]]; then 6 export __DEVBOX_SHELLENV_HASH_ac6a60d54a9d1ba6618cce8d40bfdfb50059d814edfe5f49bca3168c5c34e970_GUARD=true 7 eval "$(DO_NOT_TRACK=1 devbox shellenv -c /Users/savil/code/jetpack/devbox/examples/development/elixir/elixir_hello)" 8 fi 9 10 eval "$(DO_NOT_TRACK=1 devbox shellenv only-path-without-wrappers -c /Users/savil/code/jetpack/devbox/examples/development/elixir/elixir_hello)" 11 12 exec /nix/store/47whvyx9x48ishndcjw71xs7l0a6v6sd-elixir-1.14.4/bin/iex "$@" ```
@@ -59,7 +59,7 @@ func runShellCmd(cmd *cobra.Command, flags shellCmdFlags) error { | |||
if flags.printEnv { | |||
// false for includeHooks is because init hooks is not compatible with .envrc files generated | |||
// by versions older than 0.4.6 | |||
script, err := box.PrintEnv(cmd.Context(), false /*includeHooks*/) | |||
script, err := box.PrintEnv(&devopt.PrintEnv{Ctx: cmd.Context()}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
super golang nit, generally context and struct are passed as 2 args. The reason is that storing context in a struct is risky because we may accidentally keep it in state somewhere.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
good point, this has been undone in a future PR already!
@@ -322,9 +322,23 @@ func (d *Devbox) PrintEnv(ctx context.Context, includeHooks bool) (string, error | |||
return "", err | |||
} | |||
|
|||
if opts.OnlyPathWithoutWrappers { | |||
path := []string{} | |||
for _, p := range strings.Split(envs["PATH"], string(filepath.ListSeparator)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
filepath.SplitList
?
@@ -29,4 +29,9 @@ export {{ .ShellEnvHashKey }}_GUARD=true | |||
eval "$(DO_NOT_TRACK=1 devbox shellenv -c {{ .ProjectDir }})" | |||
fi | |||
|
|||
# So that we do not invoke other bin-wrappers from | |||
# this bin-wrapper. Instead, we directly invoke the binary from the nix store, which |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, it's the binary of the profile (which I guess points to the nix store path)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the emphasis here is on binary as opposed to wrapper
## Summary This replaces our existing `only-path-without-wrappers` wrapper implementation to use `sed`. Context: We use `only-path-without-wrappers` to remove bin wrappers in the environment of our binaries. This is particularly useful when a binary calls another binary. See #1160 for more context. Unfortunately this adds a perf hit to every single binary call. In my informal experiments this cost was ~40ms. For example: Previously, `time go version` was taking ~60ms even if environment is fully up to date. Now, `time go version` takes ~20ms. @Lagoja I'm getting an error in the elixer example (since that was the motivation for the original fix) but it looks like nix elixer on Sonoma is broken: https://elixirforum.com/t/bus-error-after-upgrading-to-sonoma-beta/56354/33 (Our CICD runners will test on Ubuntu and older macOS, Monterrey I believe) ## How was it tested? * Tested time to call `go version` before and after * Inspected PATH of shell to ensure `.wrappers` was still there. * Copy pasted `sed` code from one of the bin wrappers
Summary
This is an alternate to #1151 (see explanation in #1159)
In this approach, the wrapped-binary always calls:
eval $(devbox shellenv only-path-without-wrappers)
to ensure that the PATH is set without the
wrappers/bin
directory.In contrast to #1151, we do not always set any other environment variables
Fixes #1142
How was it tested?
issue from #1142 is fixed: