-
Notifications
You must be signed in to change notification settings - Fork 48
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
feat: add gh.ExecInteractive() #115
Conversation
Could also be nice to not wrap the |
@stemar94 This is looking good so far. What would be the reason not to wrap an |
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.
Thanks for this!
gh.go
Outdated
func ExecInteractive(args ...string) (err error) { | ||
path, err := path() | ||
if err != nil { | ||
err = fmt.Errorf("could not find gh executable in PATH. error: %w", err) |
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 understand that this basically copies the error message from Exec()
, but we could maybe improve this error message in both functions.
The original error from exec.LookPath
(which safeexec
uses under the hood) will be something like:
exec: "gh": executable file not found in $PATH
After being wrapped, the full message will be:
could not find gh executable in PATH. error: exec: "gh": executable file not found in $PATH
I don't think the extra explanation added by wrapping adds any value here. I'd vote to avoid wrapping this error message altogether (and in the Exec()
function too).
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.
Done
gh.go
Outdated
} | ||
err = cmd.Run() | ||
if err != nil { | ||
err = fmt.Errorf("failed to run gh. error: %w", err) |
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 don't mind that the original ExitError is wrapped here. The extra context makes it clear that it was the gh
command that failed, and not code from the extension itself. Perhaps we can just make it a lighter wrapper:
err = fmt.Errorf("failed to run gh. error: %w", err) | |
err = fmt.Errorf("gh: %w", err) |
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 went for fmt.Errorf("gh execution failed: %w", err) for both Execs.
gh.go
Outdated
@@ -34,6 +34,16 @@ func Exec(args ...string) (stdOut, stdErr bytes.Buffer, err error) { | |||
return run(path, nil, args...) | |||
} | |||
|
|||
// Exec gh command interactively with provided arguments. | |||
func ExecInteractive(args ...string) (err error) { |
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.
Since this is meant to spawn a potentially longer-running process, this function could accept a context.Context
instance so that the caller has an option to kill the gh process when it needs to.
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.
Done, also added a test.
8917d2a
to
80cd12a
Compare
I like for the ExecInteractive to happen transparently, where I like to hand over responsibility to the actual Without unwrapping:
With unwrapping:
Also what does the one layer of wrapping give us in value? |
80cd12a
to
b964df6
Compare
b964df6
to
ec48e42
Compare
Go callers that handle specific error types should neither assume that the error value directly returned is a specific type nor manually call if err := gh.ExecInteractive(); err != nil {
var exitError *exec.ExitError
if errors.As(err, &exitError) {
os.Exit(exitError.ExitCode())
}
} This way, it doesn't matter whether |
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 looks good! Feel free to mark your PR as "ready" when you get the test right so we can proceed to the final review. Thank you
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.
Pushed some tweaks, including a new ExecContext function (to complement Exec
) and added support for the GH_PATH environment variable that the parent gh
process can set to inform extensions about the absolute location of gh
on disk, in case gh
isn't in PATH.
For #114