diff --git a/pkg/cmd/env/env.go b/pkg/cmd/env/env.go new file mode 100644 index 00000000000..239b4053ab4 --- /dev/null +++ b/pkg/cmd/env/env.go @@ -0,0 +1,71 @@ +package env + +import ( + "fmt" + "os" + + "github.com/cli/cli/pkg/cmdutil" + "github.com/spf13/cobra" +) + +func NewCmdEnv(f *cmdutil.Factory) *cobra.Command { + var verbose bool + cmd := &cobra.Command{ + Use: "env", + Short: "Display environment variables for gh", + Long: "Display values for gh environment variables.", + Args: cobra.NoArgs, + + RunE: func(cmd *cobra.Command, args []string) error { + envVars := map[string]string{ + "GITHUB_TOKEN": "an authentication token for github.com API requests. Setting this avoids\nbeing prompted to authenticate and takes precedence over previously stored credentials.", + "GITHUB_ENTERPRISE_TOKEN": "an authentication token for API requests to GitHub Enterprise.", + "GH_REPO": "specify the GitHub repository in the '[HOST/]OWNER/REPO' format for commands\nthat otherwise operate on a local repository.", + "GH_HOST": "specify the GitHub hostname for commands that would otherwise assume\nthe 'github.com' host when not in a context of an existing repository.", + "GH_EDITOR": "the editor tool to use for authoring text (1st precedence).", + "GIT_EDITOR": "the editor tool to use for authoring text (2nd precedence).", + "VISUAL": "the editor tool to use for authoring text (3rd precedence).", + "EDITOR": "the editor tool to use for authoring text (4th precedence).", + "BROWSER": "the web browser to use for opening links.", + "DEBUG": "set to any value to enable verbose output to standard error. Include values 'api'\nor 'oauth' to print detailed information about HTTP requests or authentication flow.", + "GLAMOR_STYLE": "the style to use for rendering Markdown. See\nhttps://github.com/charmbracelet/glamour#styles", + "NO_COLOR": "avoid printing ANSI escape sequences for color output.", + } + + orderedKeys := []string{ + "GITHUB_TOKEN", + "GITHUB_ENTERPRISE_TOKEN", + "GH_REPO", + "GH_HOST", + "GH_EDITOR", + "GIT_EDITOR", + "VISUAL", + "EDITOR", + "BROWSER", + "DEBUG", + "GLAMOR_STYLE", + "NO_COLOR", + } + + for _, k := range orderedKeys { + if verbose { + fmt.Fprintf(f.IOStreams.Out, "%s - %s\n", k, envVars[k]) + } + + fmt.Fprintf(f.IOStreams.Out, "%s: %s\n", k, os.Getenv(k)) + + if verbose { + fmt.Fprintln(f.IOStreams.Out, "") + } + } + + return nil + }, + } + + cmd.Flags().BoolVarP(&verbose, "verbose", "v", false, "Show environment variable descriptions") + + cmdutil.DisableAuthCheck(cmd) + + return cmd +} diff --git a/pkg/cmd/env/env_test.go b/pkg/cmd/env/env_test.go new file mode 100644 index 00000000000..69d859880f0 --- /dev/null +++ b/pkg/cmd/env/env_test.go @@ -0,0 +1,71 @@ +package env + +import ( + "testing" + + "github.com/cli/cli/pkg/cmdutil" + "github.com/cli/cli/pkg/iostreams" + "github.com/stretchr/testify/assert" +) + +func TestNewCmdEnv(t *testing.T) { + tests := []struct { + name string + args []string + flags []string + wantsErr bool + }{ + { + name: "no args or flags", + args: []string{}, + flags: []string{}, + wantsErr: false, + }, + { + name: "verbose flag", + args: []string{}, + flags: []string{"--verbose"}, + wantsErr: false, + }, + { + name: "help flag", + args: []string{}, + flags: []string{"--help"}, + wantsErr: false, + }, + { + name: "invalid arg", + args: []string{"invalid"}, + flags: []string{}, + wantsErr: true, + }, + { + name: "invalid flag", + args: []string{}, + flags: []string{"--invalid"}, + wantsErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + io, _, stdout, stderr := iostreams.Test() + + f := &cmdutil.Factory{ + IOStreams: io, + } + + cmd := NewCmdEnv(f) + cmd.SetArgs(append(tt.args, tt.flags...)) + cmd.SetOut(stdout) + cmd.SetErr(stderr) + + _, err := cmd.ExecuteC() + if tt.wantsErr { + assert.Error(t, err) + return + } + assert.NoError(t, err) + }) + } +} diff --git a/pkg/cmd/root/help.go b/pkg/cmd/root/help.go index 019ec53cdb0..90fd7bf878c 100644 --- a/pkg/cmd/root/help.go +++ b/pkg/cmd/root/help.go @@ -25,7 +25,7 @@ func rootUsageFunc(command *cobra.Command) error { return nil } - flagUsages := command.LocalFlags().FlagUsages() + flagUsages := command.Flags().FlagUsages() if flagUsages != "" { command.Println("\n\nFlags:") command.Print(text.Indent(dedent(flagUsages), " ")) diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index 0eadbd575db..cf06aba9cf7 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -14,6 +14,7 @@ import ( apiCmd "github.com/cli/cli/pkg/cmd/api" authCmd "github.com/cli/cli/pkg/cmd/auth" configCmd "github.com/cli/cli/pkg/cmd/config" + envCmd "github.com/cli/cli/pkg/cmd/env" "github.com/cli/cli/pkg/cmd/factory" gistCmd "github.com/cli/cli/pkg/cmd/gist" issueCmd "github.com/cli/cli/pkg/cmd/issue" @@ -43,31 +44,6 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) *cobra.Command { "help:feedback": heredoc.Doc(` Open an issue using “gh issue create -R cli/cli” `), - "help:environment": heredoc.Doc(` - GITHUB_TOKEN: an authentication token for github.com API requests. Setting this avoids - being prompted to authenticate and takes precedence over previously stored credentials. - - GITHUB_ENTERPRISE_TOKEN: an authentication token for API requests to GitHub Enterprise. - - GH_REPO: specify the GitHub repository in the "[HOST/]OWNER/REPO" format for commands - that otherwise operate on a local repository. - - GH_HOST: specify the GitHub hostname for commands that would otherwise assume - the "github.com" host when not in a context of an existing repository. - - GH_EDITOR, GIT_EDITOR, VISUAL, EDITOR (in order of precedence): the editor tool to use - for authoring text. - - BROWSER: the web browser to use for opening links. - - DEBUG: set to any value to enable verbose output to standard error. Include values "api" - or "oauth" to print detailed information about HTTP requests or authentication flow. - - GLAMOUR_STYLE: the style to use for rendering Markdown. See - https://github.com/charmbracelet/glamour#styles - - NO_COLOR: avoid printing ANSI escape sequences for color output. - `), }, } @@ -110,6 +86,7 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) *cobra.Command { cmd.AddCommand(authCmd.NewCmdAuth(f)) cmd.AddCommand(configCmd.NewCmdConfig(f)) cmd.AddCommand(creditsCmd.NewCmdCredits(f, nil)) + cmd.AddCommand(envCmd.NewCmdEnv(f)) cmd.AddCommand(gistCmd.NewCmdGist(f)) cmd.AddCommand(NewCmdCompletion(f.IOStreams))