Skip to content
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

Update shell detection #3466

Merged
merged 41 commits into from
Sep 9, 2024
Merged

Update shell detection #3466

merged 41 commits into from
Sep 9, 2024

Conversation

MDrakos
Copy link
Member

@MDrakos MDrakos commented Aug 27, 2024

TaskDX-3006 Improve SHELL detection; base on parent process

@MDrakos MDrakos changed the base branch from master to version/0-47-0-RC1 August 27, 2024 22:20
@MDrakos MDrakos marked this pull request as ready for review September 3, 2024 18:26
@MDrakos
Copy link
Member Author

MDrakos commented Sep 3, 2024

@Naatan I'm looking for feedback on how I addressed the integration test failures. I think the comment explain it but if there are any questions let me know. With this approach or a different one I will have to go through all of the integration tests and update them.

Of course feel free to review everything. I'm just asking for a review early before I address the remaining tests.

@MDrakos MDrakos requested a review from Naatan September 3, 2024 18:31
Copy link
Member

@Naatan Naatan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks ok to me, but I don't think we need to make such sweeping changes. The only place this ought to matter is where we specifically test shell detection, which I imagine should be only one test.

I imagine what you're running into is that other tests have started to break because we shifted shell detection to be process based? If that's the case I think a more general purpose solution is appropriate, eg. add an env var that will trump shell detection that we can set on CI (ACTIVESTATE_OVERRIDE_SHELL?).

I'd prefer that over updating all these tests and the e2e code, as that feels less maintainable.

@MDrakos MDrakos requested a review from Naatan September 3, 2024 22:30
Comment on lines 186 to 204
if os.Getenv(constants.OverrideShellEnvVarName) != "" {
binary = os.Getenv(constants.OverrideShellEnvVarName)
}

if binary == "" {
binary = detectShellParent()
}

if binary == "" {
binary = configured
}

if binary == "" {
if runtime.GOOS == "windows" {
binary = "cmd.exe"
} else {
binary = "bash"
}
binary = os.Getenv(SHELL_ENV_VAR)
}

if binary == "" {
binary = OS_DEFULAT
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we change this into a switch case? We don't need to assert binary == nil, instead assert whether we have something to populate it with.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can however this leads to us calling functions like Getenv or detectShellParent() twice. We could also move the function calls outside of the switch but then there will be cases where we are calling them needlessly.

I'm not sure how much of a performance impact detectShellParent() has but we would be adding inefficiency for a marginal gain in readability. I'm fine with whatever direction we want to go but I wanted to flag this before I make the change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I see. Annoying Go doesn't let you assign in a switch case like it does in a regular conditional. I guess there isn't really a decent pattern for us to use here :\

internal/subshell/subshell.go Show resolved Hide resolved
p, err := process.NewProcess(int32(os.Getppid()))
if err != nil && !errors.As(err, ptr.To(&os.PathError{})) {
panic(err)
logging.Error("Failed to get parent process: %v", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why this was a panic, but we went from panicking to essentially ignoring it. Please return the error up the chain instead.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was originally a windows only function which may be a reason for the panic?

No other functions in this package return errors either as DetectShell has fallbacks so it always returns a shell name. This function is also used but subshell.New. So even if we get a fallback shell from either the SHELL env var or the system default we would error out because we couldn't detect the parent.

Again, I just want to check before making this change.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, let's go with this for now, but please make it a multilog error so we can track this on rollbar. If this is happening a lot we'll want to know about it.

internal/subshell/subshell_lin_mac.go Outdated Show resolved Hide resolved
internal/subshell/subshell_win.go Outdated Show resolved Hide resolved
internal/subshell/subshell_lin_mac.go Outdated Show resolved Hide resolved
internal/subshell/subshell.go Show resolved Hide resolved
internal/subshell/subshell_win.go Outdated Show resolved Hide resolved
internal/testhelpers/e2e/session.go Outdated Show resolved Hide resolved
@@ -74,7 +74,7 @@ func (s *SpawnedCmd) ExpectInput(opts ...termtest.SetExpectOpt) error {
expect := `expect'input from posix shell`
if cmdName != "bash" && shellName != "bash" && runtime.GOOS == "windows" {
if strings.Contains(cmdName, "powershell") || strings.Contains(shellName, "powershell") {
send = "echo \"`<expect input from powershell`>\""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure this works? IIRC the backtick is an escape on powershell.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You were right, I was running into a failure with this because it was defaulting back to cmd.exe and not powershell.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind, I was right. Here's the output on powershell

[ActiveState-CLI/small-python] C:\Users\runneradmin\AppData\Local\Temp\2179854665\work\small-python>echo "`<expect input from powershell`>" 
"`<expect input from powershell`>"    

And the expect

'Expected: "<expect input from powershell>": after 40s: timeout':
              'after 40s: timeout': timeout

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is it depends on which shell you started from. So your new tests may want this variant but older tests will want the escaping? Worth perhaps looking for other places where we run ExpectInput and running those tests on Windows before merging your PR.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All of the integration tests that start powershell are also critical. Only one of them expects input which is the one that flagged this change.

@MDrakos MDrakos requested a review from Naatan September 5, 2024 18:31
Comment on lines 186 to 204
if os.Getenv(constants.OverrideShellEnvVarName) != "" {
binary = os.Getenv(constants.OverrideShellEnvVarName)
}

if binary == "" {
binary = detectShellParent()
}

if binary == "" {
binary = configured
}

if binary == "" {
if runtime.GOOS == "windows" {
binary = "cmd.exe"
} else {
binary = "bash"
}
binary = os.Getenv(SHELL_ENV_VAR)
}

if binary == "" {
binary = OS_DEFULAT
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I see. Annoying Go doesn't let you assign in a switch case like it does in a regular conditional. I guess there isn't really a decent pattern for us to use here :\

p, err := process.NewProcess(int32(os.Getppid()))
if err != nil && !errors.As(err, ptr.To(&os.PathError{})) {
panic(err)
logging.Error("Failed to get parent process: %v", err)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, let's go with this for now, but please make it a multilog error so we can track this on rollbar. If this is happening a lot we'll want to know about it.

internal/subshell/subshell.go Outdated Show resolved Hide resolved
@@ -188,19 +189,19 @@ func DetectShell(cfg sscommon.Configurable) (string, string) {
}

if binary == "" {
binary = detectShellParent()
binary = configured
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I realized upon reading the changes that configured had a different connotation than I remembered. In my mind this was "what the user configured", but actually this is just a fallback we ourselves set when we detect the shell.

This is awkward and should probably be revisited, but given the current behaviour I this should probably be a fallback after shell parent and environment.

@MDrakos MDrakos requested a review from Naatan September 6, 2024 18:19
Copy link
Member

@Naatan Naatan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, but please read the comment on ExpectInput.

@@ -74,7 +74,7 @@ func (s *SpawnedCmd) ExpectInput(opts ...termtest.SetExpectOpt) error {
expect := `expect'input from posix shell`
if cmdName != "bash" && shellName != "bash" && runtime.GOOS == "windows" {
if strings.Contains(cmdName, "powershell") || strings.Contains(shellName, "powershell") {
send = "echo \"`<expect input from powershell`>\""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My guess is it depends on which shell you started from. So your new tests may want this variant but older tests will want the escaping? Worth perhaps looking for other places where we run ExpectInput and running those tests on Windows before merging your PR.

@MDrakos MDrakos merged commit 7ecd46e into version/0-47-0-RC1 Sep 9, 2024
7 of 8 checks passed
@MDrakos MDrakos deleted the DX-3006 branch September 9, 2024 23:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants