-
Notifications
You must be signed in to change notification settings - Fork 127
Add support for any shell for stack shellinit #921
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
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! Maybe this is also a way to support other shells like powershell in the future 🙂
Added some comments, the most important ones would be to decide if we want separated types for the different posix shells, and to define the new flag and their description in cobraext as is done in other modules. The rest of comments are suggestions about code organization.
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.
Thinking about UX and I'm wondering it it would be possible attempt determine the shell automatically such that it automatically does the correct thing for the user's environment (e.g. if we detect fish then output in the appropriate fish format).
I think the most reliable and cross-platform means (assuming we need this to work on Windows to output PowerShell format) of detecting the shell would be to get the executable name of the parent process. Like
// Using github.com/elastic/go-sysinfo.
parent, err := sysinfo.Process(os.Getppid())
if err != nil {
log.Fatal(err)
}
parentInfo, err := parent.Info()
if err != nil {
log.Fatal(err)
}
shell := filepath.Base(parentInfo.Exe)Reading the SHELL env var could be a simple option, but if a user has launched a subshell explicitly then it will be wrong (e.g. opening fish from bash).
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.
Could you please explain what's wrong with the original implementation? I might be missing something. Fish seems to be supported too.
$ elastic-package completion
Generate the autocompletion script for elastic-package for the specified shell.
See each sub-command's help for details on how to use the generated script.
Usage:
elastic-package completion [command]
Available Commands:
bash Generate the autocompletion script for bash
fish Generate the autocompletion script for fish
powershell Generate the autocompletion script for powershell
zsh Generate the autocompletion script for zsh$ elastic-package completion fish|
I misread your intention, thanks @jsoriano for pointing it. I thought it's about |
|
I updated the code with Jaime suggestion:
Instead of exposing I would strongly advise against using
This can create issues when running the command in subshell or automating it and depends on a parameter that may not be configurable (think running this in the CI), leading to "fail first, configure later" scenario that I think are I like Andrew's approach, just want to double check if you are ok adding |
cmd/stack.go
Outdated
| return cobraext.FlagParsingError(err, cobraext.ProfileFlagName) | ||
| } | ||
|
|
||
| s, err := cmd.Flags().GetString(cobraext.ShellInitShellFlagName) |
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.
Please use a more meaningful name here.
| s, err := cmd.Flags().GetString(cobraext.ShellInitShellFlagName) | |
| shellName, err := cmd.Flags().GetString(cobraext.ShellInitShellFlagName) |
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.
fixed in 18364c6 (#921)
internal/stack/shellinit.go
Outdated
| export %s=%s | ||
| export %s=%s | ||
| export %s=%s | ||
| export %s=%s |
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.
This is adding spaces before each export right? Can you check the output of elastic-package stack shellinit?
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.
fixed in 7a98775 (#921)
internal/stack/shellinit.go
Outdated
| case "zsh": | ||
| return posixTemplate | ||
| default: | ||
| panic("shell type is unknown, should be one of " + strings.Join(availableShellTypes, ", ")) |
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.
s comes directly from user input, we shouldn't panic in this case.
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.
fixed in 5a0adf4 (#921)
I think it would be fine to add this dependency if it helps to have a better UX. |
🌐 Coverage report
|
|
Added shell detection using the script provided by Andrew in |
|
CI failures seem related, |
`stack shellinit` command outputs shell code to setup the environment and connect to the local stack instances created by the `stack` command. Before this change this command was only supporting POSIX compatible shells. After this commit the support has been extended so is possible to specify, through a flag, the desired compatibility for it's output.
This removes the `shell` package moving the logic alongside `ShellInit`, removes the `Shell` type and reduce template code to only POSIX compliant and fish shell.
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.
👍
cmd/stack.go
Outdated
| return "", fmt.Errorf("cannot retrieve information for parent of process %d: %w", ppid, err) | ||
| } | ||
|
|
||
| shell := filepath.Base(parentInfo.Exe) |
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.
Found another corner case.
When running elastic-package with go run, it detects go as the shell:
detected shell: go
Error: shellinit failed: cannot get shell init template: shell type is unknown, should be one of bash, fish, sh, zsh
exit status 1
This happens when running elastic-package with go run in repositories where this package is in go.mod. This is done in CI in some cases, and for example I use it when trying to reproduce failures in the integrations repository with the same version of elastic-package that is used in CI.
This could be considered a regression, could we do something about this? Maybe it is possible to detect if elastic-package is being run with go run, or we could get the parent of the parent when it is go.
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.
Or maybe another option to avoid regressions, would be to directly return bash and log something to stderr instead of failing when this method cannot detect the shell.
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.
This use case is supported by not using auto detection (passing --shell=bash). I think that is preferable than deciding to fallback to BASH because that can lead to errors that are very hard to troubleshoot and less explanatory.
We may want to make this explicit using a different error message.
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.
Well, let's separate my two comments:
- Not breaking the not so rare
go runcase. Possible workaround for this could be: if found shell isgo, try to get the parent of the parent instead. - General solution to don't break unknown cases that work now. I propose to use
bashin case of error only to keep the current behavior, where only bash is supported. I agree that it could be more discussed as I don't have more use cases beyond the mentioned ones, and it would be better to have explicit behavior.
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.
Not breaking the not so rare go run case. Possible workaround for this could be: if found shell is go, try to get the parent of the parent instead.
I added this in 12ddc3d (with tests)
General solution to don't break unknown cases that work now. I propose to use bash in case of error only to keep the current behavior, where only bash is supported.
I didn't consider this POV, but it make complete sense, as the behaviour would not change from current implementation. I will change the default case.
|
The CI fails on |
CI uses go 1.19, is it possible that you are using an older version? |
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.
Apart of some last nitpicking and the issues with CI and go.mod it LGTM, thanks!
Co-authored-by: Jaime Soriano Pastor <jaime.soriano@elastic.co>
I'm using go 1.19.1 locally, which is the same as reported in |
If I run Shall I push the changes I see to this branch? |
|
@jsoriano yes please, I cannot reproduce even with go 1.19.2 :( |
|
Thank you! |
elastic-package stack shellinitoutput shell code needed to setup the testing environment and connect to the stack instance started viaelastic-package stack up.The current implementation emits POSIX shell code, compatible with
sh,zshandbash. The shellcode breaks on other shells, likefish- that I'm using. There are workarounds (like the awesomebabelfish) but I think a built in solution would be preferred.This PR aims to address this, adding a simple template mechanism that allows to support any shell through a custom shell code template, adds supports for
fishshell and a--shellflag on theshellinitcommand to select the desired shell output.This change is not breaking, as by default it outputs POSIX compatible shell code.