CLI: Add non-interactive option to interactive commands (#651)

Sascha and Michael Muré created

* Add option to skip the AvatarURL input request

Using an empty string for the avatar cli flag e.g. `git-bug user create
-a ""` will still result in a prompt. As the avatar URL is an optional
option, it should be possible to skip asking for it entirely.
Otherwise automated user creation via a script must make use of pipe hacks.

* Add global --non-interactive cmdline option

* Replace --skipAvatar for --non-interactive option

* Cmd BugAdd: respect non-interactive option

* Cmd bridge configure: respect non-interactive opt

* Cmd CommentAdd: respect non-interactive option

* Cmd CommentEdit: respect non-interactive option

* Cmd TermUI: respect non-interactive option

* Cmd TitleEdit: respect non-interactive option

* Remove global non-interactive option

* Cmd UserCreate: Use local non-interactive option

* Cmd BugAdd: Use local non-interactive option

* Cmd BridgeConfigure: Use local non-interactive option

* Cmd CommentAdd: Use local non-interactive option

* Cmd CommentEdit: Use local non-interactive option

* Cmd TermUI: Drop non-interactive option

It should be obviouse that the termui is an interactive command.

* Cmd TitleEdit: Use local non-interactive option

* Update docs

* Bridge GitHub: respect non-interactive option

* Bridge GitLab: respect non-interactive option

* Bridge Jira: respect non-interactive and token opt

* Fix failing compilation

* Bridge launchpad: respect non-interactive option

* bridge: isNonInteractive --> interactive

Co-authored-by: Michael Muré <batolettre@gmail.com>

Change summary

bridge/core/bridge.go              |  4 +-
bridge/core/interfaces.go          |  4 +-
bridge/github/config.go            | 12 +++++++
bridge/gitlab/config.go            | 14 ++++++++
bridge/jira/config.go              | 49 +++++++++++++++++++++----------
bridge/launchpad/config.go         |  5 ++
commands/add.go                    | 10 +++--
commands/bridge_configure.go       | 18 ++++++-----
commands/comment_add.go            | 10 +++++-
commands/comment_edit.go           | 10 +++++-
commands/title_edit.go             |  8 ++++
commands/user_create.go            | 14 +++++---
doc/man/git-bug-add.1              |  4 ++
doc/man/git-bug-bridge-configure.1 |  4 ++
doc/man/git-bug-comment-add.1      |  4 ++
doc/man/git-bug-comment-edit.1     |  4 ++
doc/man/git-bug-title-edit.1       |  4 ++
doc/man/git-bug-user-create.1      |  4 ++
doc/md/git-bug_add.md              |  9 +++--
doc/md/git-bug_bridge_configure.md |  1 
doc/md/git-bug_comment_add.md      |  7 ++-
doc/md/git-bug_comment_edit.md     |  7 ++-
doc/md/git-bug_title_edit.md       |  5 +-
doc/md/git-bug_user_create.md      |  9 +++--
misc/bash_completion/git-bug       | 12 +++++++
25 files changed, 170 insertions(+), 62 deletions(-)

Detailed changes

bridge/core/bridge.go 🔗

@@ -202,10 +202,10 @@ func RemoveBridge(repo repository.RepoConfig, name string) error {
 }
 
 // Configure run the target specific configuration process
-func (b *Bridge) Configure(params BridgeParams) error {
+func (b *Bridge) Configure(params BridgeParams, interactive bool) error {
 	validateParams(params, b.impl)
 
-	conf, err := b.impl.Configure(b.repo, params)
+	conf, err := b.impl.Configure(b.repo, params, interactive)
 	if err != nil {
 		return err
 	}

bridge/core/interfaces.go 🔗

@@ -20,8 +20,8 @@ type BridgeImpl interface {
 	NewExporter() Exporter
 
 	// Configure handle the user interaction and return a key/value configuration
-	// for future use
-	Configure(repo *cache.RepoCache, params BridgeParams) (Configuration, error)
+	// for future use.
+	Configure(repo *cache.RepoCache, params BridgeParams, interactive bool) (Configuration, error)
 
 	// The set of the BridgeParams fields supported
 	ValidParams() map[string]interface{}

bridge/github/config.go 🔗

@@ -40,7 +40,7 @@ func (g *Github) ValidParams() map[string]interface{} {
 	}
 }
 
-func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (core.Configuration, error) {
+func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams, interactive bool) (core.Configuration, error) {
 	var err error
 	var owner string
 	var project string
@@ -60,6 +60,9 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
 		}
 	default:
 		// terminal prompt
+		if !interactive {
+			return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the remote repository with --owner and --project, or via --url option.")
+		}
 		owner, project, err = promptURL(repo)
 		if err != nil {
 			return nil, err
@@ -99,6 +102,9 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
 		cred = token
 	default:
 		if params.Login == "" {
+			if !interactive {
+				return nil, fmt.Errorf("Non-interactive-mode is active. Please specify a login via the --login option.")
+			}
 			login, err = promptLogin()
 		} else {
 			// validate login and override with the correct case
@@ -110,6 +116,10 @@ func (g *Github) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
 		if err != nil {
 			return nil, err
 		}
+
+		if !interactive {
+			return nil, fmt.Errorf("Non-interactive-mode is active. Please specify a access token via the --token option.")
+		}
 		cred, err = promptTokenOptions(repo, login, owner, project)
 		if err != nil {
 			return nil, err

bridge/gitlab/config.go 🔗

@@ -32,7 +32,7 @@ func (g *Gitlab) ValidParams() map[string]interface{} {
 	}
 }
 
-func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (core.Configuration, error) {
+func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams, interactive bool) (core.Configuration, error) {
 	var err error
 	var baseUrl string
 
@@ -40,6 +40,9 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
 	case params.BaseURL != "":
 		baseUrl = params.BaseURL
 	default:
+		if !interactive {
+			return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the gitlab instance URL via the --base-url option.")
+		}
 		baseUrl, err = input.PromptDefault("Gitlab server URL", "URL", defaultBaseURL, input.Required, input.IsURL)
 		if err != nil {
 			return nil, errors.Wrap(err, "base url prompt")
@@ -54,6 +57,9 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
 		projectURL = params.URL
 	default:
 		// terminal prompt
+		if !interactive {
+			return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the gitlab project URL via the --url option.")
+		}
 		projectURL, err = promptProjectURL(repo, baseUrl)
 		if err != nil {
 			return nil, errors.Wrap(err, "url prompt")
@@ -89,6 +95,9 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
 		cred = token
 	default:
 		if params.Login == "" {
+			if !interactive {
+				return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the login name via the --login option.")
+			}
 			// TODO: validate username
 			login, err = input.Prompt("Gitlab login", "login", input.Required)
 		} else {
@@ -98,6 +107,9 @@ func (g *Gitlab) Configure(repo *cache.RepoCache, params core.BridgeParams) (cor
 		if err != nil {
 			return nil, err
 		}
+		if !interactive {
+			return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the access token via the --token option.")
+		}
 		cred, err = promptTokenOptions(repo, login, baseUrl)
 		if err != nil {
 			return nil, err

bridge/jira/config.go 🔗

@@ -33,15 +33,19 @@ func (*Jira) ValidParams() map[string]interface{} {
 		"Login":      nil,
 		"CredPrefix": nil,
 		"Project":    nil,
+		"TokenRaw":   nil,
 	}
 }
 
 // Configure sets up the bridge configuration
-func (j *Jira) Configure(repo *cache.RepoCache, params core.BridgeParams) (core.Configuration, error) {
+func (j *Jira) Configure(repo *cache.RepoCache, params core.BridgeParams, interactive bool) (core.Configuration, error) {
 	var err error
 
 	baseURL := params.BaseURL
 	if baseURL == "" {
+		if !interactive {
+			return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the JIRA server URL via the --base-url option.")
+		}
 		// terminal prompt
 		baseURL, err = input.Prompt("JIRA server URL", "URL", input.Required, input.IsURL)
 		if err != nil {
@@ -51,20 +55,17 @@ func (j *Jira) Configure(repo *cache.RepoCache, params core.BridgeParams) (core.
 
 	project := params.Project
 	if project == "" {
+		if !interactive {
+			return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the JIRA project key via the --project option.")
+		}
 		project, err = input.Prompt("JIRA project key", "project", input.Required)
 		if err != nil {
 			return nil, err
 		}
 	}
 
-	fmt.Println(credTypeText)
-	credTypeInput, err := input.PromptChoice("Authentication mechanism", []string{"SESSION", "TOKEN"})
-	if err != nil {
-		return nil, err
-	}
-	credType := []string{"SESSION", "TOKEN"}[credTypeInput]
-
 	var login string
+	var credType string
 	var cred auth.Credential
 
 	switch {
@@ -80,18 +81,34 @@ func (j *Jira) Configure(repo *cache.RepoCache, params core.BridgeParams) (core.
 		login = l
 	default:
 		if params.Login == "" {
-			// TODO: validate username
+			if !interactive {
+				return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the login name via the --login option.")
+			}
 			login, err = input.Prompt("JIRA login", "login", input.Required)
+			if err != nil {
+				return nil, err
+			}
 		} else {
-			// TODO: validate username
 			login = params.Login
 		}
-		if err != nil {
-			return nil, err
-		}
-		cred, err = promptCredOptions(repo, login, baseURL)
-		if err != nil {
-			return nil, err
+		// TODO: validate username
+
+		if params.TokenRaw == "" {
+			if !interactive {
+				return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the access token via the --token option.")
+			}
+			fmt.Println(credTypeText)
+			credTypeInput, err := input.PromptChoice("Authentication mechanism", []string{"SESSION", "TOKEN"})
+			if err != nil {
+				return nil, err
+			}
+			credType = []string{"SESSION", "TOKEN"}[credTypeInput]
+			cred, err = promptCredOptions(repo, login, baseURL)
+			if err != nil {
+				return nil, err
+			}
+		} else {
+			credType = "TOKEN"
 		}
 	}
 

bridge/launchpad/config.go 🔗

@@ -20,7 +20,7 @@ func (Launchpad) ValidParams() map[string]interface{} {
 	}
 }
 
-func (l *Launchpad) Configure(repo *cache.RepoCache, params core.BridgeParams) (core.Configuration, error) {
+func (l *Launchpad) Configure(repo *cache.RepoCache, params core.BridgeParams, interactive bool) (core.Configuration, error) {
 	var err error
 	var project string
 
@@ -31,6 +31,9 @@ func (l *Launchpad) Configure(repo *cache.RepoCache, params core.BridgeParams) (
 		// get project name from url
 		project, err = splitURL(params.URL)
 	default:
+		if !interactive {
+			return nil, fmt.Errorf("Non-interactive-mode is active. Please specify the project name with the --project option.")
+		}
 		// get project name from terminal prompt
 		project, err = input.Prompt("Launchpad project name", "project name", input.Required)
 	}

commands/add.go 🔗

@@ -8,9 +8,10 @@ import (
 )
 
 type addOptions struct {
-	title       string
-	message     string
-	messageFile string
+	title          string
+	message        string
+	messageFile    string
+	nonInteractive bool
 }
 
 func newAddCommand() *cobra.Command {
@@ -36,6 +37,7 @@ func newAddCommand() *cobra.Command {
 		"Provide a message to describe the issue")
 	flags.StringVarP(&options.messageFile, "file", "F", "",
 		"Take the message from the given file. Use - to read the message from the standard input")
+	flags.BoolVar(&options.nonInteractive, "non-interactive", false, "Do not ask for user input")
 
 	return cmd
 }
@@ -49,7 +51,7 @@ func runAdd(env *Env, opts addOptions) error {
 		}
 	}
 
-	if opts.messageFile == "" && (opts.message == "" || opts.title == "") {
+	if !opts.nonInteractive && opts.messageFile == "" && (opts.message == "" || opts.title == "") {
 		opts.title, opts.message, err = input.BugCreateEditorInput(env.backend, opts.title, opts.message)
 
 		if err == input.ErrEmptyTitle {

commands/bridge_configure.go 🔗

@@ -16,11 +16,12 @@ import (
 )
 
 type bridgeConfigureOptions struct {
-	name       string
-	target     string
-	params     core.BridgeParams
-	token      string
-	tokenStdin bool
+	name           string
+	target         string
+	params         core.BridgeParams
+	token          string
+	tokenStdin     bool
+	nonInteractive bool
 }
 
 func newBridgeConfigureCommand() *cobra.Command {
@@ -105,6 +106,7 @@ git bug bridge configure \
 	flags.BoolVar(&options.tokenStdin, "token-stdin", false, "Will read the token from stdin and ignore --token")
 	flags.StringVarP(&options.params.Owner, "owner", "o", "", "The owner of the remote repository")
 	flags.StringVarP(&options.params.Project, "project", "p", "", "The name of the remote repository")
+	flags.BoolVar(&options.nonInteractive, "non-interactive", false, "Do not ask for user input")
 
 	return cmd
 }
@@ -136,14 +138,14 @@ func runBridgeConfigure(env *Env, opts bridgeConfigureOptions) error {
 		opts.params.TokenRaw = opts.token
 	}
 
-	if opts.target == "" {
+	if !opts.nonInteractive && opts.target == "" {
 		opts.target, err = promptTarget()
 		if err != nil {
 			return err
 		}
 	}
 
-	if opts.name == "" {
+	if !opts.nonInteractive && opts.name == "" {
 		opts.name, err = promptName(env.repo)
 		if err != nil {
 			return err
@@ -155,7 +157,7 @@ func runBridgeConfigure(env *Env, opts bridgeConfigureOptions) error {
 		return err
 	}
 
-	err = b.Configure(opts.params)
+	err = b.Configure(opts.params, !opts.nonInteractive)
 	if err != nil {
 		return err
 	}

commands/comment_add.go 🔗

@@ -9,8 +9,9 @@ import (
 )
 
 type commentAddOptions struct {
-	messageFile string
-	message     string
+	messageFile    string
+	message        string
+	nonInteractive bool
 }
 
 func newCommentAddCommand() *cobra.Command {
@@ -35,6 +36,7 @@ func newCommentAddCommand() *cobra.Command {
 
 	flags.StringVarP(&options.message, "message", "m", "",
 		"Provide the new message from the command line")
+	flags.BoolVar(&options.nonInteractive, "non-interactive", false, "Do not ask for user input")
 
 	return cmd
 }
@@ -53,6 +55,10 @@ func runCommentAdd(env *Env, opts commentAddOptions, args []string) error {
 	}
 
 	if opts.messageFile == "" && opts.message == "" {
+		if opts.nonInteractive {
+			env.err.Println("No message given. Use -m or -F option to specify a message. Aborting.")
+			return nil
+		}
 		opts.message, err = input.BugCommentEditorInput(env.backend, "")
 		if err == input.ErrEmptyMessage {
 			env.err.Println("Empty message, aborting.")

commands/comment_edit.go 🔗

@@ -7,8 +7,9 @@ import (
 )
 
 type commentEditOptions struct {
-	messageFile string
-	message     string
+	messageFile    string
+	message        string
+	nonInteractive bool
 }
 
 func newCommentEditCommand() *cobra.Command {
@@ -34,6 +35,7 @@ func newCommentEditCommand() *cobra.Command {
 
 	flags.StringVarP(&options.message, "message", "m", "",
 		"Provide the new message from the command line")
+	flags.BoolVar(&options.nonInteractive, "non-interactive", false, "Do not ask for user input")
 
 	return cmd
 }
@@ -52,6 +54,10 @@ func runCommentEdit(env *Env, opts commentEditOptions, args []string) error {
 	}
 
 	if opts.messageFile == "" && opts.message == "" {
+		if opts.nonInteractive {
+			env.err.Println("No message given. Use -m or -F option to specify a message. Aborting.")
+			return nil
+		}
 		opts.message, err = input.BugCommentEditorInput(env.backend, "")
 		if err == input.ErrEmptyMessage {
 			env.err.Println("Empty message, aborting.")

commands/title_edit.go 🔗

@@ -9,7 +9,8 @@ import (
 )
 
 type titleEditOptions struct {
-	title string
+	title          string
+	nonInteractive bool
 }
 
 func newTitleEditCommand() *cobra.Command {
@@ -32,6 +33,7 @@ func newTitleEditCommand() *cobra.Command {
 	flags.StringVarP(&options.title, "title", "t", "",
 		"Provide a title to describe the issue",
 	)
+	flags.BoolVar(&options.nonInteractive, "non-interactive", false, "Do not ask for user input")
 
 	return cmd
 }
@@ -45,6 +47,10 @@ func runTitleEdit(env *Env, opts titleEditOptions, args []string) error {
 	snap := b.Snapshot()
 
 	if opts.title == "" {
+		if opts.nonInteractive {
+			env.err.Println("No title given. Use -m or -F option to specify a title. Aborting.")
+			return nil
+		}
 		opts.title, err = input.BugTitleEditorInput(env.repo, snap.Title)
 		if err == input.ErrEmptyTitle {
 			env.out.Println("Empty title, aborting.")

commands/user_create.go 🔗

@@ -7,9 +7,10 @@ import (
 )
 
 type createUserOptions struct {
-	name      string
-	email     string
-	avatarURL string
+	name           string
+	email          string
+	avatarURL      string
+	nonInteractive bool
 }
 
 func newUserCreateCommand() *cobra.Command {
@@ -30,13 +31,14 @@ func newUserCreateCommand() *cobra.Command {
 	flags.StringVarP(&options.name, "name", "n", "", "Name to identify the user")
 	flags.StringVarP(&options.email, "email", "e", "", "Email of the user")
 	flags.StringVarP(&options.avatarURL, "avatar", "a", "", "Avatar URL")
+	flags.BoolVar(&options.nonInteractive, "non-interactive", false, "Do not ask for user input")
 
 	return cmd
 }
 
 func runUserCreate(env *Env, opts createUserOptions) error {
 
-	if opts.name == "" {
+	if !opts.nonInteractive && opts.name == "" {
 		preName, err := env.backend.GetUserName()
 		if err != nil {
 			return err
@@ -47,7 +49,7 @@ func runUserCreate(env *Env, opts createUserOptions) error {
 		}
 	}
 
-	if opts.email == "" {
+	if !opts.nonInteractive && opts.email == "" {
 		preEmail, err := env.backend.GetUserEmail()
 		if err != nil {
 			return err
@@ -59,7 +61,7 @@ func runUserCreate(env *Env, opts createUserOptions) error {
 		}
 	}
 
-	if opts.avatarURL == "" {
+	if !opts.nonInteractive && opts.avatarURL == "" {
 		var err error
 		opts.avatarURL, err = input.Prompt("Avatar URL", "avatar")
 		if err != nil {

doc/man/git-bug-add.1 🔗

@@ -29,6 +29,10 @@ Create a new bug.
 \fB\-F\fP, \fB\-\-file\fP=""
 	Take the message from the given file. Use \- to read the message from the standard input
 
+.PP
+\fB\-\-non\-interactive\fP[=false]
+	Do not ask for user input
+
 .PP
 \fB\-h\fP, \fB\-\-help\fP[=false]
 	help for add

doc/man/git-bug-bridge-configure.1 🔗

@@ -63,6 +63,10 @@ Configure a new bridge by passing flags or/and using interactive terminal prompt
 \fB\-p\fP, \fB\-\-project\fP=""
 	The name of the remote repository
 
+.PP
+\fB\-\-non\-interactive\fP[=false]
+	Do not ask for user input
+
 .PP
 \fB\-h\fP, \fB\-\-help\fP[=false]
 	help for configure

doc/man/git-bug-comment-add.1 🔗

@@ -25,6 +25,10 @@ Add a new comment to a bug.
 \fB\-m\fP, \fB\-\-message\fP=""
 	Provide the new message from the command line
 
+.PP
+\fB\-\-non\-interactive\fP[=false]
+	Do not ask for user input
+
 .PP
 \fB\-h\fP, \fB\-\-help\fP[=false]
 	help for add

doc/man/git-bug-comment-edit.1 🔗

@@ -25,6 +25,10 @@ Edit an existing comment on a bug.
 \fB\-m\fP, \fB\-\-message\fP=""
 	Provide the new message from the command line
 
+.PP
+\fB\-\-non\-interactive\fP[=false]
+	Do not ask for user input
+
 .PP
 \fB\-h\fP, \fB\-\-help\fP[=false]
 	help for edit

doc/man/git-bug-title-edit.1 🔗

@@ -21,6 +21,10 @@ Edit a title of a bug.
 \fB\-t\fP, \fB\-\-title\fP=""
 	Provide a title to describe the issue
 
+.PP
+\fB\-\-non\-interactive\fP[=false]
+	Do not ask for user input
+
 .PP
 \fB\-h\fP, \fB\-\-help\fP[=false]
 	help for edit

doc/man/git-bug-user-create.1 🔗

@@ -33,6 +33,10 @@ Create a new identity.
 \fB\-n\fP, \fB\-\-name\fP=""
 	Name to identify the user
 
+.PP
+\fB\-\-non\-interactive\fP[=false]
+	Do not ask for user input
+
 
 .SH SEE ALSO
 .PP

doc/md/git-bug_add.md 🔗

@@ -9,10 +9,11 @@ git-bug add [flags]
 ### Options
 
 ```
-  -t, --title string     Provide a title to describe the issue
-  -m, --message string   Provide a message to describe the issue
-  -F, --file string      Take the message from the given file. Use - to read the message from the standard input
-  -h, --help             help for add
+  -t, --title string      Provide a title to describe the issue
+  -m, --message string    Provide a message to describe the issue
+  -F, --file string       Take the message from the given file. Use - to read the message from the standard input
+      --non-interactive   Do not ask for user input
+  -h, --help              help for add
 ```
 
 ### SEE ALSO

doc/md/git-bug_bridge_configure.md 🔗

@@ -81,6 +81,7 @@ git bug bridge configure \
       --token-stdin         Will read the token from stdin and ignore --token
   -o, --owner string        The owner of the remote repository
   -p, --project string      The name of the remote repository
+      --non-interactive     Do not ask for user input
   -h, --help                help for configure
 ```
 

doc/md/git-bug_comment_add.md 🔗

@@ -9,9 +9,10 @@ git-bug comment add [ID] [flags]
 ### Options
 
 ```
-  -F, --file string      Take the message from the given file. Use - to read the message from the standard input
-  -m, --message string   Provide the new message from the command line
-  -h, --help             help for add
+  -F, --file string       Take the message from the given file. Use - to read the message from the standard input
+  -m, --message string    Provide the new message from the command line
+      --non-interactive   Do not ask for user input
+  -h, --help              help for add
 ```
 
 ### SEE ALSO

doc/md/git-bug_comment_edit.md 🔗

@@ -9,9 +9,10 @@ git-bug comment edit [COMMENT_ID] [flags]
 ### Options
 
 ```
-  -F, --file string      Take the message from the given file. Use - to read the message from the standard input
-  -m, --message string   Provide the new message from the command line
-  -h, --help             help for edit
+  -F, --file string       Take the message from the given file. Use - to read the message from the standard input
+  -m, --message string    Provide the new message from the command line
+      --non-interactive   Do not ask for user input
+  -h, --help              help for edit
 ```
 
 ### SEE ALSO

doc/md/git-bug_title_edit.md 🔗

@@ -9,8 +9,9 @@ git-bug title edit [ID] [flags]
 ### Options
 
 ```
-  -t, --title string   Provide a title to describe the issue
-  -h, --help           help for edit
+  -t, --title string      Provide a title to describe the issue
+      --non-interactive   Do not ask for user input
+  -h, --help              help for edit
 ```
 
 ### SEE ALSO

doc/md/git-bug_user_create.md 🔗

@@ -9,10 +9,11 @@ git-bug user create [flags]
 ### Options
 
 ```
-  -a, --avatar string   Avatar URL
-  -e, --email string    Email of the user
-  -h, --help            help for create
-  -n, --name string     Name to identify the user
+  -a, --avatar string     Avatar URL
+  -e, --email string      Email of the user
+  -h, --help              help for create
+  -n, --name string       Name to identify the user
+      --non-interactive   Do not ask for user input
 ```
 
 ### SEE ALSO

misc/bash_completion/git-bug 🔗

@@ -390,6 +390,8 @@ _git-bug_add()
     local_nonpersistent_flags+=("--file")
     local_nonpersistent_flags+=("--file=")
     local_nonpersistent_flags+=("-F")
+    flags+=("--non-interactive")
+    local_nonpersistent_flags+=("--non-interactive")
 
     must_have_one_flag=()
     must_have_one_noun=()
@@ -565,6 +567,8 @@ _git-bug_bridge_configure()
     local_nonpersistent_flags+=("--project")
     local_nonpersistent_flags+=("--project=")
     local_nonpersistent_flags+=("-p")
+    flags+=("--non-interactive")
+    local_nonpersistent_flags+=("--non-interactive")
 
     must_have_one_flag=()
     must_have_one_noun=()
@@ -716,6 +720,8 @@ _git-bug_comment_add()
     local_nonpersistent_flags+=("--message")
     local_nonpersistent_flags+=("--message=")
     local_nonpersistent_flags+=("-m")
+    flags+=("--non-interactive")
+    local_nonpersistent_flags+=("--non-interactive")
 
     must_have_one_flag=()
     must_have_one_noun=()
@@ -748,6 +754,8 @@ _git-bug_comment_edit()
     local_nonpersistent_flags+=("--message")
     local_nonpersistent_flags+=("--message=")
     local_nonpersistent_flags+=("-m")
+    flags+=("--non-interactive")
+    local_nonpersistent_flags+=("--non-interactive")
 
     must_have_one_flag=()
     must_have_one_noun=()
@@ -1196,6 +1204,8 @@ _git-bug_title_edit()
     local_nonpersistent_flags+=("--title")
     local_nonpersistent_flags+=("--title=")
     local_nonpersistent_flags+=("-t")
+    flags+=("--non-interactive")
+    local_nonpersistent_flags+=("--non-interactive")
 
     must_have_one_flag=()
     must_have_one_noun=()
@@ -1275,6 +1285,8 @@ _git-bug_user_create()
     local_nonpersistent_flags+=("--name")
     local_nonpersistent_flags+=("--name=")
     local_nonpersistent_flags+=("-n")
+    flags+=("--non-interactive")
+    local_nonpersistent_flags+=("--non-interactive")
 
     must_have_one_flag=()
     must_have_one_noun=()