@@ -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
3134func 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 )
0 commit comments