X Tutup
Skip to content

Commit 2345f49

Browse files
vilmibmvilmibm
authored andcommitted
support auth login --web
1 parent 5a8df47 commit 2345f49

File tree

2 files changed

+113
-52
lines changed

2 files changed

+113
-52
lines changed

pkg/cmd/auth/login/login.go

Lines changed: 69 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,11 @@ type LoginOptions struct {
2424
IO *iostreams.IOStreams
2525
Config func() (config.Config, error)
2626

27+
Interactive bool
28+
2729
Hostname string
2830
Token string
31+
Web bool
2932
}
3033

3134
func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Command {
@@ -51,13 +54,24 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm
5154
$ gh auth login
5255
# => do an interactive setup
5356
57+
$ gh auth login --web
58+
# => open a browser to authenticate and do a non-interactive setup
59+
5460
$ gh auth login --with-token < mytoken.txt
5561
# => read token from mytoken.txt and authenticate against github.com
5662
5763
$ gh auth login --hostname enterprise.internal --with-token < mytoken.txt
5864
# => read token from mytoken.txt and authenticate against a GitHub Enterprise Server instance
5965
`),
6066
RunE: func(cmd *cobra.Command, args []string) error {
67+
if !opts.IO.CanPrompt() && !(tokenStdin || opts.Web) {
68+
return &cmdutil.FlagError{Err: errors.New("--web or --with-token required when not running interactively")}
69+
}
70+
71+
if tokenStdin && opts.Web {
72+
return &cmdutil.FlagError{Err: errors.New("specify only one of --web or --with-token")}
73+
}
74+
6175
if tokenStdin {
6276
defer opts.IO.In.Close()
6377
token, err := ioutil.ReadAll(opts.IO.In)
@@ -67,15 +81,8 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm
6781
opts.Token = strings.TrimSpace(string(token))
6882
}
6983

70-
if opts.Token != "" {
71-
// Assume non-interactive if a token is specified
72-
if opts.Hostname == "" {
73-
opts.Hostname = ghinstance.Default()
74-
}
75-
} else {
76-
if !opts.IO.CanPrompt() {
77-
return &cmdutil.FlagError{Err: errors.New("--with-token required when not running interactively")}
78-
}
84+
if opts.IO.CanPrompt() && opts.Token == "" && !opts.Web {
85+
opts.Interactive = true
7986
}
8087

8188
if cmd.Flags().Changed("hostname") {
@@ -84,6 +91,12 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm
8491
}
8592
}
8693

94+
if !opts.Interactive {
95+
if opts.Hostname == "" {
96+
opts.Hostname = ghinstance.Default()
97+
}
98+
}
99+
87100
if runF != nil {
88101
return runF(opts)
89102
}
@@ -94,6 +107,7 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm
94107

95108
cmd.Flags().StringVarP(&opts.Hostname, "hostname", "h", "", "The hostname of the GitHub instance to authenticate with")
96109
cmd.Flags().BoolVar(&tokenStdin, "with-token", false, "Read token from standard input")
110+
cmd.Flags().BoolVarP(&opts.Web, "web", "w", false, "Open a browser to authenticate")
97111

98112
return cmd
99113
}
@@ -168,24 +182,26 @@ func loginRun(opts *LoginOptions) error {
168182
return err
169183
}
170184

171-
username, err := api.CurrentLoginName(apiClient, hostname)
172-
if err != nil {
173-
return fmt.Errorf("error using api: %w", err)
174-
}
175-
var keepGoing bool
176-
err = prompt.SurveyAskOne(&survey.Confirm{
177-
Message: fmt.Sprintf(
178-
"You're already logged into %s as %s. Do you want to re-authenticate?",
179-
hostname,
180-
username),
181-
Default: false,
182-
}, &keepGoing)
183-
if err != nil {
184-
return fmt.Errorf("could not prompt: %w", err)
185-
}
185+
if opts.Interactive {
186+
username, err := api.CurrentLoginName(apiClient, hostname)
187+
if err != nil {
188+
return fmt.Errorf("error using api: %w", err)
189+
}
190+
var keepGoing bool
191+
err = prompt.SurveyAskOne(&survey.Confirm{
192+
Message: fmt.Sprintf(
193+
"You're already logged into %s as %s. Do you want to re-authenticate?",
194+
hostname,
195+
username),
196+
Default: false,
197+
}, &keepGoing)
198+
if err != nil {
199+
return fmt.Errorf("could not prompt: %w", err)
200+
}
186201

187-
if !keepGoing {
188-
return nil
202+
if !keepGoing {
203+
return nil
204+
}
189205
}
190206
}
191207
}
@@ -195,15 +211,19 @@ func loginRun(opts *LoginOptions) error {
195211
}
196212

197213
var authMode int
198-
err = prompt.SurveyAskOne(&survey.Select{
199-
Message: "How would you like to authenticate?",
200-
Options: []string{
201-
"Login with a web browser",
202-
"Paste an authentication token",
203-
},
204-
}, &authMode)
205-
if err != nil {
206-
return fmt.Errorf("could not prompt: %w", err)
214+
if opts.Web {
215+
authMode = 0
216+
} else {
217+
err = prompt.SurveyAskOne(&survey.Select{
218+
Message: "How would you like to authenticate?",
219+
Options: []string{
220+
"Login with a web browser",
221+
"Paste an authentication token",
222+
},
223+
}, &authMode)
224+
if err != nil {
225+
return fmt.Errorf("could not prompt: %w", err)
226+
}
207227
}
208228

209229
if authMode == 0 {
@@ -239,19 +259,21 @@ func loginRun(opts *LoginOptions) error {
239259
}
240260
}
241261

242-
var gitProtocol string
243-
err = prompt.SurveyAskOne(&survey.Select{
244-
Message: "Choose default git protocol",
245-
Options: []string{
246-
"HTTPS",
247-
"SSH",
248-
},
249-
}, &gitProtocol)
250-
if err != nil {
251-
return fmt.Errorf("could not prompt: %w", err)
252-
}
262+
gitProtocol := "https"
263+
if opts.Interactive {
264+
err = prompt.SurveyAskOne(&survey.Select{
265+
Message: "Choose default git protocol",
266+
Options: []string{
267+
"HTTPS",
268+
"SSH",
269+
},
270+
}, &gitProtocol)
271+
if err != nil {
272+
return fmt.Errorf("could not prompt: %w", err)
273+
}
253274

254-
gitProtocol = strings.ToLower(gitProtocol)
275+
gitProtocol = strings.ToLower(gitProtocol)
276+
}
255277

256278
fmt.Fprintf(opts.IO.ErrOut, "- gh config set -h %s git_protocol %s\n", hostname, gitProtocol)
257279
err = cfg.Set(hostname, "git_protocol", gitProtocol)

pkg/cmd/auth/login/login_test.go

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -81,19 +81,43 @@ func Test_NewCmdLogin(t *testing.T) {
8181
stdinTTY: true,
8282
cli: "--hostname barry.burton",
8383
wants: LoginOptions{
84-
Hostname: "barry.burton",
85-
Token: "",
84+
Hostname: "barry.burton",
85+
Token: "",
86+
Interactive: true,
8687
},
8788
},
8889
{
8990
name: "tty",
9091
stdinTTY: true,
9192
cli: "",
9293
wants: LoginOptions{
93-
Hostname: "",
94-
Token: "",
94+
Hostname: "",
95+
Token: "",
96+
Interactive: true,
9597
},
9698
},
99+
{
100+
name: "tty web",
101+
stdinTTY: true,
102+
cli: "--web",
103+
wants: LoginOptions{
104+
Hostname: "github.com",
105+
Web: true,
106+
},
107+
},
108+
{
109+
name: "nontty web",
110+
cli: "--web",
111+
wants: LoginOptions{
112+
Hostname: "github.com",
113+
Web: true,
114+
},
115+
},
116+
{
117+
name: "web and with-token",
118+
cli: "--web --with-token",
119+
wantsErr: true,
120+
},
97121
}
98122

99123
for _, tt := range tests {
@@ -134,6 +158,8 @@ func Test_NewCmdLogin(t *testing.T) {
134158

135159
assert.Equal(t, tt.wants.Token, gotOpts.Token)
136160
assert.Equal(t, tt.wants.Hostname, gotOpts.Hostname)
161+
assert.Equal(t, tt.wants.Web, gotOpts.Web)
162+
assert.Equal(t, tt.wants.Interactive, gotOpts.Interactive)
137163
})
138164
}
139165
}
@@ -262,6 +288,9 @@ func Test_loginRun_Survey(t *testing.T) {
262288
}{
263289
{
264290
name: "already authenticated",
291+
opts: &LoginOptions{
292+
Interactive: true,
293+
},
265294
cfg: func(cfg config.Config) {
266295
_ = cfg.Set("github.com", "oauth_token", "ghi789")
267296
},
@@ -280,7 +309,8 @@ func Test_loginRun_Survey(t *testing.T) {
280309
{
281310
name: "hostname set",
282311
opts: &LoginOptions{
283-
Hostname: "rebecca.chambers",
312+
Hostname: "rebecca.chambers",
313+
Interactive: true,
284314
},
285315
wantHosts: "rebecca.chambers:\n oauth_token: def456\n git_protocol: https\n user: jillv\n",
286316
askStubs: func(as *prompt.AskStubber) {
@@ -298,6 +328,9 @@ func Test_loginRun_Survey(t *testing.T) {
298328
{
299329
name: "choose enterprise",
300330
wantHosts: "brad.vickers:\n oauth_token: def456\n git_protocol: https\n user: jillv\n",
331+
opts: &LoginOptions{
332+
Interactive: true,
333+
},
301334
askStubs: func(as *prompt.AskStubber) {
302335
as.StubOne(1) // host type enterprise
303336
as.StubOne("brad.vickers") // hostname
@@ -315,6 +348,9 @@ func Test_loginRun_Survey(t *testing.T) {
315348
{
316349
name: "choose github.com",
317350
wantHosts: "github.com:\n oauth_token: def456\n git_protocol: https\n user: jillv\n",
351+
opts: &LoginOptions{
352+
Interactive: true,
353+
},
318354
askStubs: func(as *prompt.AskStubber) {
319355
as.StubOne(0) // host type github.com
320356
as.StubOne(1) // auth mode: token
@@ -325,6 +361,9 @@ func Test_loginRun_Survey(t *testing.T) {
325361
{
326362
name: "sets git_protocol",
327363
wantHosts: "github.com:\n oauth_token: def456\n git_protocol: ssh\n user: jillv\n",
364+
opts: &LoginOptions{
365+
Interactive: true,
366+
},
328367
askStubs: func(as *prompt.AskStubber) {
329368
as.StubOne(0) // host type github.com
330369
as.StubOne(1) // auth mode: token

0 commit comments

Comments
 (0)
X Tutup