in commands/auth/login/login.go [46:141]
func NewCmdLogin(f *cmdutils.Factory) *cobra.Command {
opts = &LoginOptions{
IO: f.IO,
Config: f.Config,
}
var tokenStdin bool
cmd := &cobra.Command{
Use: "login",
Args: cobra.ExactArgs(0),
Short: "Authenticate with a GitLab instance.",
Long: heredoc.Docf(`
Authenticate with a GitLab instance.
You can pass in a token on standard input by using %[1]s--stdin%[1]s.
The minimum required scopes for the token are: %[1]sapi%[1]s, %[1]swrite_repository%[1]s.
Configuration and credentials are stored in the global configuration file (default %[1]s~/.config/glab-cli/config.yml%[1]s)
`, "`"),
Example: heredoc.Docf(`
# Start interactive setup
$ glab auth login
# Authenticate against %[1]sgitlab.com%[1]s by reading the token from a file
$ glab auth login --stdin < myaccesstoken.txt
# Authenticate with GitLab Self-Managed or GitLab Dedicated
$ glab auth login --hostname salsa.debian.org
# Non-interactive setup
$ glab auth login --hostname gitlab.example.org --token glpat-xxx --api-host gitlab.example.org:3443 --api-protocol https --git-protocol ssh
# Non-interactive setup reading token from a file
$ glab auth login --hostname gitlab.example.org --api-host gitlab.example.org:3443 --api-protocol https --git-protocol ssh --stdin < myaccesstoken.txt
# Non-interactive job token setup
$ glab auth login --hostname gitlab.example.org --job-token $CI_JOB_TOKEN
`, "`"),
RunE: func(cmd *cobra.Command, args []string) error {
if !opts.IO.PromptEnabled() && !tokenStdin && opts.Token == "" && opts.JobToken == "" {
return &cmdutils.FlagError{Err: errors.New("'--stdin', '--token', or '--job-token' required when not running interactively.")}
}
if opts.JobToken != "" && (opts.Token != "" || tokenStdin) {
return &cmdutils.FlagError{Err: errors.New("specify one of '--job-token' or '--token' or '--stdin'. You cannot use more than one of these at the same time.")}
}
if opts.Token != "" && tokenStdin {
return &cmdutils.FlagError{Err: errors.New("specify one of '--token' or '--stdin'. You cannot use both flags at the same time.")}
}
if tokenStdin {
defer opts.IO.In.Close()
token, err := io.ReadAll(opts.IO.In)
if err != nil {
return fmt.Errorf("failed to read token from STDIN: %w", err)
}
opts.Token = strings.TrimSpace(string(token))
}
if opts.IO.PromptEnabled() && opts.Token == "" && opts.JobToken == "" && opts.IO.IsaTTY {
opts.Interactive = true
}
if cmd.Flags().Changed("hostname") {
if err := hostnameValidator(opts.Hostname); err != nil {
return &cmdutils.FlagError{Err: fmt.Errorf("error parsing '--hostname': %w", err)}
}
}
if !opts.Interactive && opts.Hostname == "" {
opts.Hostname = glinstance.Default()
}
if opts.Interactive && (opts.ApiHost != "" || opts.ApiProtocol != "" || opts.GitProtocol != "") {
return &cmdutils.FlagError{Err: errors.New("api-host, api-protocol, and git-protocol can only be used in non-interactive mode.")}
}
if err := loginRun(opts); err != nil {
return cmdutils.WrapError(err, "Could not sign in!")
}
return nil
},
}
cmd.Flags().StringVarP(&opts.Hostname, "hostname", "h", "", "The hostname of the GitLab instance to authenticate with.")
cmd.Flags().StringVarP(&opts.Token, "token", "t", "", "Your GitLab access token.")
cmd.Flags().StringVarP(&opts.JobToken, "job-token", "j", "", "CI job token.")
cmd.Flags().BoolVar(&tokenStdin, "stdin", false, "Read token from standard input.")
cmd.Flags().BoolVar(&opts.UseKeyring, "use-keyring", false, "Store token in your operating system's keyring.")
cmd.Flags().StringVarP(&opts.ApiHost, "api-host", "a", "", "API host url.")
cmd.Flags().StringVarP(&opts.ApiProtocol, "api-protocol", "p", "", "API protocol: https, http")
cmd.Flags().StringVarP(&opts.GitProtocol, "git-protocol", "g", "", "Git protocol: ssh, https, http")
return cmd
}