Skip to content

Commit 9234163

Browse files
committed
Formalize gh process exit codes
Here are the statuses: - 0: success - 1: misc. error - 2: user interrupt/cancellation - 4: authentication needed These old exit codes are now changed to "1": - we used to return "2" for config file errors; - we used to return "2" for alias expansion errors; - we used to return "3" for alias runtime errors. I do not believe that there is a need to distinguish these specific cases via exit status, and converting them to "1" frees codes "2" and "3" for more practical use.
1 parent dd34cae commit 9234163

File tree

1 file changed

+34
-13
lines changed

1 file changed

+34
-13
lines changed

cmd/gh/main.go

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"time"
1414

1515
surveyCore "github.com/AlecAivazis/survey/v2/core"
16+
"github.com/AlecAivazis/survey/v2/terminal"
1617
"github.com/cli/cli/api"
1718
"github.com/cli/cli/internal/build"
1819
"github.com/cli/cli/internal/config"
@@ -32,7 +33,21 @@ import (
3233

3334
var updaterEnabled = ""
3435

36+
type exitCode int
37+
38+
const (
39+
exitOK exitCode = 0
40+
exitError exitCode = 1
41+
exitCancel exitCode = 2
42+
exitAuth exitCode = 4
43+
)
44+
3545
func main() {
46+
code := mainRun()
47+
os.Exit(int(code))
48+
}
49+
50+
func mainRun() exitCode {
3651
buildDate := build.Date
3752
buildVersion := build.Version
3853

@@ -78,7 +93,7 @@ func main() {
7893
cfg, err := cmdFactory.Config()
7994
if err != nil {
8095
fmt.Fprintf(stderr, "failed to read configuration: %s\n", err)
81-
os.Exit(2)
96+
return exitError
8297
}
8398

8499
if prompt, _ := cfg.Get("", "prompt"); prompt == "disabled" {
@@ -102,7 +117,7 @@ func main() {
102117
expandedArgs, isShell, err = expand.ExpandAlias(cfg, os.Args, nil)
103118
if err != nil {
104119
fmt.Fprintf(stderr, "failed to process aliases: %s\n", err)
105-
os.Exit(2)
120+
return exitError
106121
}
107122

108123
if hasDebug {
@@ -113,7 +128,7 @@ func main() {
113128
exe, err := safeexec.LookPath(expandedArgs[0])
114129
if err != nil {
115130
fmt.Fprintf(stderr, "failed to run external command: %s", err)
116-
os.Exit(3)
131+
return exitError
117132
}
118133

119134
externalCmd := exec.Command(exe, expandedArgs[1:]...)
@@ -125,14 +140,14 @@ func main() {
125140
err = preparedCmd.Run()
126141
if err != nil {
127142
if ee, ok := err.(*exec.ExitError); ok {
128-
os.Exit(ee.ExitCode())
143+
return exitCode(ee.ExitCode())
129144
}
130145

131146
fmt.Fprintf(stderr, "failed to run external command: %s", err)
132-
os.Exit(3)
147+
return exitError
133148
}
134149

135-
os.Exit(0)
150+
return exitOK
136151
}
137152
}
138153

@@ -142,29 +157,33 @@ func main() {
142157
fmt.Fprintln(stderr, cs.Bold("Welcome to GitHub CLI!"))
143158
fmt.Fprintln(stderr)
144159
fmt.Fprintln(stderr, "To authenticate, please run `gh auth login`.")
145-
os.Exit(4)
160+
return exitAuth
146161
}
147162

148163
rootCmd.SetArgs(expandedArgs)
149164

150165
if cmd, err := rootCmd.ExecuteC(); err != nil {
151166
if err == cmdutil.SilentError {
152-
os.Exit(1)
167+
return exitError
153168
} else if cmdutil.IsUserCancellation(err) {
154-
os.Exit(2)
169+
if errors.Is(err, terminal.InterruptErr) {
170+
// ensure the next shell prompt will start on its own line
171+
fmt.Fprint(stderr, "\n")
172+
}
173+
return exitCancel
155174
}
156175

157176
printError(stderr, err, cmd, hasDebug)
158177

159178
var httpErr api.HTTPError
160179
if errors.As(err, &httpErr) && httpErr.StatusCode == 401 {
161-
fmt.Println("hint: try authenticating with `gh auth login`")
180+
fmt.Fprintln(stderr, "hint: try authenticating with `gh auth login`")
162181
}
163182

164-
os.Exit(1)
183+
return exitError
165184
}
166185
if root.HasFailed() {
167-
os.Exit(1)
186+
return exitError
168187
}
169188

170189
newRelease := <-updateMessageChan
@@ -175,7 +194,7 @@ func main() {
175194
}
176195
if isHomebrew && isRecentRelease(newRelease.PublishedAt) {
177196
// do not notify Homebrew users before the version bump had a chance to get merged into homebrew-core
178-
return
197+
return exitOK
179198
}
180199
fmt.Fprintf(stderr, "\n\n%s %s → %s\n",
181200
ansi.Color("A new release of gh is available:", "yellow"),
@@ -187,6 +206,8 @@ func main() {
187206
fmt.Fprintf(stderr, "%s\n\n",
188207
ansi.Color(newRelease.URL, "yellow"))
189208
}
209+
210+
return exitOK
190211
}
191212

192213
func printError(out io.Writer, err error, cmd *cobra.Command, debug bool) {

0 commit comments

Comments
 (0)