diff --git a/.golangci.yml b/.golangci.yml index c63b521bc..674ace4e8 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -53,6 +53,7 @@ linters: exclusions: paths: - third-party + - script rules: - path: _test\.go$ linters: diff --git a/git/client.go b/git/client.go index 5f547c99c..82cc0a794 100644 --- a/git/client.go +++ b/git/client.go @@ -45,7 +45,7 @@ var remoteRE = regexp.MustCompile(`(.+)\s+(.+)\s+\((push|fetch)\)`) // rather than the last null byte in the entire string. var commitLogRE = regexp.MustCompile(`(?m)^[0-9a-fA-F]{7,40}\x00.*?\x00[\S\s]*?\x00$`) -type errWithExitCode interface { +type withExitCodeError interface { ExitCode() int } @@ -704,7 +704,7 @@ func (c *Client) revParse(ctx context.Context, args ...string) ([]byte, error) { func (c *Client) IsLocalGitRepo(ctx context.Context) (bool, error) { _, err := c.GitDir(ctx) if err != nil { - var execError errWithExitCode + var execError withExitCodeError if errors.As(err, &execError) && execError.ExitCode() == 128 { return false, nil } @@ -860,7 +860,7 @@ func resolveGitPath() (string, error) { if runtime.GOOS == "windows" { programName = "Git for Windows" } - return "", &NotInstalled{ + return "", &NotInstalledError{ message: fmt.Sprintf("unable to find git executable in PATH; please install %s before retrying", programName), err: err, } diff --git a/git/command.go b/git/command.go index c4614d086..04a46218f 100644 --- a/git/command.go +++ b/git/command.go @@ -50,7 +50,7 @@ func (gc *Command) Output() ([]byte, error) { // is not a method and so tests can't access it. // THIS MEANS THAT TESTS WILL NOT CORRECTLY HAVE STDERR SET, // but at least tests can get the exit code. - var exitErrorWithExitCode errWithExitCode + var exitErrorWithExitCode withExitCodeError if errors.As(err, &exitErrorWithExitCode) { ge.ExitCode = exitErrorWithExitCode.ExitCode() } diff --git a/git/errors.go b/git/errors.go index a3f1645aa..7c14e9ba7 100644 --- a/git/errors.go +++ b/git/errors.go @@ -8,16 +8,16 @@ import ( // ErrNotOnAnyBranch indicates that the user is in detached HEAD state. var ErrNotOnAnyBranch = errors.New("git: not on any branch") -type NotInstalled struct { +type NotInstalledError struct { message string err error } -func (e *NotInstalled) Error() string { +func (e *NotInstalledError) Error() string { return e.message } -func (e *NotInstalled) Unwrap() error { +func (e *NotInstalledError) Unwrap() error { return e.err } diff --git a/internal/build/build.go b/internal/build/build.go index 3f0152b04..49cf0fd6e 100644 --- a/internal/build/build.go +++ b/internal/build/build.go @@ -11,7 +11,7 @@ var Version = "DEV" // Date is dynamically set at build time in the Makefile. var Date = "" // YYYY-MM-DD -func init() { +func init() { //nolint:gochecknoinits // Sets build version from module info at startup if Version == "DEV" { if info, ok := debug.ReadBuildInfo(); ok && info.Main.Version != "(devel)" { Version = info.Main.Version diff --git a/internal/codespaces/codespaces_test.go b/internal/codespaces/codespaces_test.go index d931b96ef..c4ffdbbd2 100644 --- a/internal/codespaces/codespaces_test.go +++ b/internal/codespaces/codespaces_test.go @@ -10,7 +10,7 @@ import ( "github.com/cli/cli/v2/internal/codespaces/api" ) -func init() { +func init() { //nolint:gochecknoinits // Sets test backoff to 0 for fast test execution // Set the backoff to 0 for testing so that they run quickly codespaceStatePollingBackoff = backoff.NewConstantBackOff(time.Second * 0) } diff --git a/internal/config/migration/multi_account.go b/internal/config/migration/multi_account.go index 209912781..7e958706a 100644 --- a/internal/config/migration/multi_account.go +++ b/internal/config/migration/multi_account.go @@ -10,7 +10,7 @@ import ( "github.com/cli/go-gh/v2/pkg/config" ) -var noTokenError = errors.New("no token found") +var errNoToken = errors.New("no token found") type CowardlyRefusalError struct { err error @@ -107,7 +107,7 @@ func (m MultiAccount) Do(c *config.Config) error { tokenSource, err := getToken(c, hostname) // If no token existed for this host we'll remove the entry from the hosts file // by deleting it and moving on to the next one. - if errors.Is(err, noTokenError) { + if errors.Is(err, errNoToken) { // The only error that can be returned here is the key not existing, which // we know can't be true. _ = c.Remove(append(hostsKey, hostname)) @@ -150,7 +150,7 @@ func getToken(c *config.Config, hostname string) (tokenSource, error) { // Otherwise we'll return a sentinel error if err != nil || token == "" { - return tokenSource{}, noTokenError + return tokenSource{}, errNoToken } return tokenSource{ diff --git a/internal/docs/docs_test.go b/internal/docs/docs_test.go index 71c0186a9..98fedb5b3 100644 --- a/internal/docs/docs_test.go +++ b/internal/docs/docs_test.go @@ -9,7 +9,7 @@ import ( func emptyRun(*cobra.Command, []string) {} -func init() { +func init() { //nolint:gochecknoinits // Sets up test command tree for docs generation tests rootCmd.PersistentFlags().StringP("rootflag", "r", "two", "") rootCmd.PersistentFlags().StringP("strtwo", "t", "two", "help message for parent flag strtwo") diff --git a/internal/ghcmd/cmd.go b/internal/ghcmd/cmd.go index 9fc5bcefe..989cb0f62 100644 --- a/internal/ghcmd/cmd.go +++ b/internal/ghcmd/cmd.go @@ -39,7 +39,7 @@ const ( exitPending exitCode = 8 ) -func Main() exitCode { +func Main() exitCode { //nolint:gocyclo buildDate := build.Date buildVersion := build.Version hasDebug, _ := utils.IsDebugEnabled() @@ -109,13 +109,13 @@ func Main() exitCode { rootCmd.SetArgs(expandedArgs) if cmd, err := rootCmd.ExecuteContextC(ctx); err != nil { - var pagerPipeError *iostreams.ErrClosedPagerPipe + var pagerPipeError *iostreams.ClosedPagerPipeError var noResultsError cmdutil.NoResultsError var extError *root.ExternalCommandExitError var authError *root.AuthError - if err == cmdutil.SilentError { + if err == cmdutil.ErrSilent { return exitError - } else if err == cmdutil.PendingError { + } else if err == cmdutil.ErrPending { return exitPending } else if cmdutil.IsUserCancellation(err) { if errors.Is(err, terminal.InterruptErr) { diff --git a/internal/prompter/test.go b/internal/prompter/test.go index ceada4932..4925390af 100644 --- a/internal/prompter/test.go +++ b/internal/prompter/test.go @@ -24,7 +24,8 @@ func NewMockPrompter(t *testing.T) *MockPrompter { type MockPrompter struct { ghPrompter.PrompterMock - t *testing.T + + t *testing.T authTokenStubs []authTokenStub confirmDeletionStubs []confirmDeletionStub inputHostnameStubs []inputHostnameStub diff --git a/internal/run/stub.go b/internal/run/stub.go index 507fd61d6..de9d1f728 100644 --- a/internal/run/stub.go +++ b/internal/run/stub.go @@ -106,16 +106,16 @@ type commandStub struct { callbacks []CommandCallback } -type errWithExitCode struct { +type withExitCodeError struct { message string exitCode int } -func (e errWithExitCode) Error() string { +func (e withExitCodeError) Error() string { return e.message } -func (e errWithExitCode) ExitCode() int { +func (e withExitCodeError) ExitCode() int { return e.exitCode } @@ -124,7 +124,7 @@ func (s *commandStub) Run() error { if s.exitStatus != 0 { // It's nontrivial to construct a fake `exec.ExitError` instance, so we return an error type // that has the `ExitCode() int` method. - return errWithExitCode{ + return withExitCodeError{ message: fmt.Sprintf("%s exited with status %d", s.pattern, s.exitStatus), exitCode: s.exitStatus, } diff --git a/pkg/cmd/agent-task/shared/log.go b/pkg/cmd/agent-task/shared/log.go index c94f5e603..2f0f87823 100644 --- a/pkg/cmd/agent-task/shared/log.go +++ b/pkg/cmd/agent-task/shared/log.go @@ -88,7 +88,7 @@ func (r *logRenderer) Render(logs []byte, w io.Writer, io *iostreams.IOStreams) return false, nil } -func renderLogEntry(entry chatCompletionChunkEntry, w io.Writer, io *iostreams.IOStreams) (bool, error) { +func renderLogEntry(entry chatCompletionChunkEntry, w io.Writer, io *iostreams.IOStreams) (bool, error) { //nolint:gocyclo cs := io.ColorScheme() var stop bool for _, choice := range entry.Choices { diff --git a/pkg/cmd/agent-task/view/view.go b/pkg/cmd/agent-task/view/view.go index 854faa73d..08c89bfc6 100644 --- a/pkg/cmd/agent-task/view/view.go +++ b/pkg/cmd/agent-task/view/view.go @@ -150,7 +150,7 @@ func viewRun(opts *ViewOptions) error { if err != nil { if errors.Is(err, capi.ErrSessionNotFound) { fmt.Fprintln(opts.IO.ErrOut, "session not found") - return cmdutil.SilentError + return cmdutil.ErrSilent } return err } @@ -234,7 +234,7 @@ func viewRun(opts *ViewOptions) error { if len(sessions) == 0 { fmt.Fprintln(opts.IO.ErrOut, "no session found for pull request") - return cmdutil.SilentError + return cmdutil.ErrSilent } opts.IO.StopProgressIndicator() diff --git a/pkg/cmd/agent-task/view/view_test.go b/pkg/cmd/agent-task/view/view_test.go index 34036cfa5..f2eb01fbb 100644 --- a/pkg/cmd/agent-task/view/view_test.go +++ b/pkg/cmd/agent-task/view/view_test.go @@ -187,7 +187,7 @@ func Test_viewRun(t *testing.T) { } }, wantStderr: "session not found\n", - wantErr: cmdutil.SilentError, + wantErr: cmdutil.ErrSilent, }, { name: "with session id, api error (tty)", @@ -557,7 +557,7 @@ func Test_viewRun(t *testing.T) { } }, wantStderr: "session not found\n", - wantErr: cmdutil.SilentError, + wantErr: cmdutil.ErrSilent, }, { name: "with session id, without pr data, web mode (tty)", diff --git a/pkg/cmd/api/api.go b/pkg/cmd/api/api.go index 8e4b2edd4..d433f480e 100644 --- a/pkg/cmd/api/api.go +++ b/pkg/cmd/api/api.go @@ -299,7 +299,7 @@ func NewCmdApi(f *cmdutil.Factory, runF func(*ApiOptions) error) *cobra.Command return cmd } -func apiRun(opts *ApiOptions) error { +func apiRun(opts *ApiOptions) error { //nolint:gocyclo params, err := parseFields(opts) if err != nil { return err @@ -458,7 +458,7 @@ func apiRun(opts *ApiOptions) error { var jsonContentTypeRE = regexp.MustCompile(`[/+]json(;|$)`) -func processResponse(resp *http.Response, opts *ApiOptions, bodyWriter, headersWriter io.Writer, template *template.Template, isFirstPage, isLastPage bool) (endCursor string, err error) { +func processResponse(resp *http.Response, opts *ApiOptions, bodyWriter, headersWriter io.Writer, template *template.Template, isFirstPage, isLastPage bool) (endCursor string, err error) { //nolint:gocyclo if opts.ShowResponseHeaders { fmt.Fprintln(headersWriter, resp.Proto, resp.Status) printHeaders(headersWriter, resp.Header, opts.IO.ColorEnabled()) @@ -532,7 +532,7 @@ func processResponse(resp *http.Response, opts *ApiOptions, bodyWriter, headersW if u := factory.SSOURL(); u != "" { fmt.Fprintf(opts.IO.ErrOut, "Authorize in your web browser: %s\n", u) } - err = cmdutil.SilentError + err = cmdutil.ErrSilent return } diff --git a/pkg/cmd/api/api_test.go b/pkg/cmd/api/api_test.go index bf4d51c4c..dc99cc323 100644 --- a/pkg/cmd/api/api_test.go +++ b/pkg/cmd/api/api_test.go @@ -478,7 +478,7 @@ func Test_apiRun(t *testing.T) { Body: io.NopCloser(bytes.NewBufferString(`{"message": "THIS IS FINE"}`)), Header: http.Header{"Content-Type": []string{"application/json; charset=utf-8"}}, }, - err: cmdutil.SilentError, + err: cmdutil.ErrSilent, stdout: `{"message": "THIS IS FINE"}`, stderr: "gh: THIS IS FINE (HTTP 400)\n", isatty: false, @@ -490,7 +490,7 @@ func Test_apiRun(t *testing.T) { Body: io.NopCloser(bytes.NewBufferString(`{"errors": ["ALSO", "FINE"]}`)), Header: http.Header{"Content-Type": []string{"application/json; charset=utf-8"}}, }, - err: cmdutil.SilentError, + err: cmdutil.ErrSilent, stdout: `{"errors": ["ALSO", "FINE"]}`, stderr: "gh: ALSO\nFINE\n", isatty: false, @@ -505,7 +505,7 @@ func Test_apiRun(t *testing.T) { Body: io.NopCloser(bytes.NewBufferString(`{"errors": [{"message":"AGAIN"}, {"message":"FINE"}]}`)), Header: http.Header{"Content-Type": []string{"application/json; charset=utf-8"}}, }, - err: cmdutil.SilentError, + err: cmdutil.ErrSilent, stdout: `{"errors": [{"message":"AGAIN"}, {"message":"FINE"}]}`, stderr: "gh: AGAIN\nFINE\n", isatty: false, @@ -516,7 +516,7 @@ func Test_apiRun(t *testing.T) { StatusCode: 502, Body: io.NopCloser(bytes.NewBufferString(`gateway timeout`)), }, - err: cmdutil.SilentError, + err: cmdutil.ErrSilent, stdout: `gateway timeout`, stderr: "gh: HTTP 502\n", isatty: false, @@ -606,7 +606,7 @@ func Test_apiRun(t *testing.T) { Body: io.NopCloser(bytes.NewBufferString(`{"message": "THIS IS FINE"}`)), Header: http.Header{"Content-Type": []string{"application/json; charset=utf-8"}}, }, - err: cmdutil.SilentError, + err: cmdutil.ErrSilent, stdout: `{"message": "THIS IS FINE"}`, stderr: "gh: THIS IS FINE (HTTP 400)\n", isatty: false, @@ -636,7 +636,7 @@ func Test_apiRun(t *testing.T) { Body: io.NopCloser(bytes.NewBufferString(`{"message": "THIS IS FINE"}`)), Header: http.Header{"Content-Type": []string{"application/json; charset=utf-8"}}, }, - err: cmdutil.SilentError, + err: cmdutil.ErrSilent, stdout: `{"message": "THIS IS FINE"}`, stderr: "gh: THIS IS FINE (HTTP 400)\n", isatty: false, @@ -1258,7 +1258,7 @@ func Test_apiRun_HEAD(t *testing.T) { RequestMethod: "HEAD", RequestMethodPassed: true, }) - if err != cmdutil.SilentError { + if err != cmdutil.ErrSilent { t.Fatalf("got error %v", err) } } diff --git a/pkg/cmd/attestation/trustedroot/trustedroot.go b/pkg/cmd/attestation/trustedroot/trustedroot.go index 29dd6fcd9..3470a438b 100644 --- a/pkg/cmd/attestation/trustedroot/trustedroot.go +++ b/pkg/cmd/attestation/trustedroot/trustedroot.go @@ -4,12 +4,13 @@ import ( "bytes" "encoding/json" "fmt" + "io" "net/http" "os" "github.com/cli/cli/v2/pkg/cmd/attestation/api" "github.com/cli/cli/v2/pkg/cmd/attestation/auth" - "github.com/cli/cli/v2/pkg/cmd/attestation/io" + attio "github.com/cli/cli/v2/pkg/cmd/attestation/io" "github.com/cli/cli/v2/pkg/cmd/attestation/verification" "github.com/cli/cli/v2/pkg/cmdutil" o "github.com/cli/cli/v2/pkg/option" @@ -26,6 +27,7 @@ type Options struct { VerifyOnly bool Hostname string TrustDomain string + Out io.Writer } type tufClientInstantiator func(o *tuf.Options) (*tuf.Client, error) @@ -80,7 +82,7 @@ func NewTrustedRootCmd(f *cmdutil.Factory, runF func(*Options) error) *cobra.Com if !c.Authentication().HasActiveToken(opts.Hostname) { return fmt.Errorf("not authenticated with %s", opts.Hostname) } - logger := io.NewHandler(f.IOStreams) + logger := attio.NewHandler(f.IOStreams) apiClient := api.NewLiveClient(hc, opts.Hostname, logger) td, err := apiClient.GetTrustDomain() if err != nil { @@ -93,6 +95,7 @@ func NewTrustedRootCmd(f *cmdutil.Factory, runF func(*Options) error) *cobra.Com return runF(opts) } + opts.Out = f.IOStreams.Out if err := getTrustedRoot(tuf.New, opts, hc); err != nil { return fmt.Errorf("Failed to verify the TUF repository: %w", err) } @@ -177,9 +180,9 @@ func getTrustedRoot(makeTUF tufClientInstantiator, opts *Options, hc *http.Clien } if !opts.VerifyOnly { - fmt.Println(output) + fmt.Fprintln(opts.Out, output) } else { - fmt.Printf("Local TUF repository for %s updated and verified\n", tufOpt.tufOptions.RepositoryBaseURL) + fmt.Fprintf(opts.Out, "Local TUF repository for %s updated and verified\n", tufOpt.tufOptions.RepositoryBaseURL) } } } diff --git a/pkg/cmd/attestation/trustedroot/trustedroot_test.go b/pkg/cmd/attestation/trustedroot/trustedroot_test.go index 5e8db55ad..356036b13 100644 --- a/pkg/cmd/attestation/trustedroot/trustedroot_test.go +++ b/pkg/cmd/attestation/trustedroot/trustedroot_test.go @@ -3,6 +3,7 @@ package trustedroot import ( "bytes" "fmt" + "io" "net/http" "strings" "testing" @@ -176,6 +177,7 @@ func TestGetTrustedRoot(t *testing.T) { opts := &Options{ TufUrl: mirror, TufRootPath: root, + Out: io.Discard, } reg := &httpmock.Registry{} diff --git a/pkg/cmd/auth/gitcredential/helper.go b/pkg/cmd/auth/gitcredential/helper.go index 9b64f74b9..9c8c9c536 100644 --- a/pkg/cmd/auth/gitcredential/helper.go +++ b/pkg/cmd/auth/gitcredential/helper.go @@ -102,7 +102,7 @@ func helperRun(opts *CredentialOptions) error { } if wants["protocol"] != "https" { - return cmdutil.SilentError + return cmdutil.ErrSilent } cfg, err := opts.Config() @@ -128,11 +128,11 @@ func helperRun(opts *CredentialOptions) error { } if gotUser == "" || gotToken == "" { - return cmdutil.SilentError + return cmdutil.ErrSilent } if wants["username"] != "" && gotUser != tokenUser && !strings.EqualFold(wants["username"], gotUser) { - return cmdutil.SilentError + return cmdutil.ErrSilent } fmt.Fprint(opts.IO.Out, "protocol=https\n") diff --git a/pkg/cmd/auth/login/login.go b/pkg/cmd/auth/login/login.go index 88bc09f63..1aa48b816 100644 --- a/pkg/cmd/auth/login/login.go +++ b/pkg/cmd/auth/login/login.go @@ -189,7 +189,7 @@ func loginRun(opts *LoginOptions) error { if src, writeable := shared.AuthTokenWriteable(authCfg, hostname); !writeable { fmt.Fprintf(opts.IO.ErrOut, "The value of the %s environment variable is being used for authentication.\n", src) fmt.Fprint(opts.IO.ErrOut, "To have GitHub CLI store credentials instead, first clear the value from the environment.\n") - return cmdutil.SilentError + return cmdutil.ErrSilent } plainHTTPClient, err := opts.PlainHttpClient() diff --git a/pkg/cmd/auth/login/login_test.go b/pkg/cmd/auth/login/login_test.go index 7ec174973..52f8cea46 100644 --- a/pkg/cmd/auth/login/login_test.go +++ b/pkg/cmd/auth/login/login_test.go @@ -400,7 +400,7 @@ func Test_loginRun_nontty(t *testing.T) { Token: "abc456", }, env: map[string]string{"GH_TOKEN": "value_from_env"}, - wantErr: "SilentError", + wantErr: "ErrSilent", wantStderr: heredoc.Doc(` The value of the GH_TOKEN environment variable is being used for authentication. To have GitHub CLI store credentials instead, first clear the value from the environment. @@ -413,7 +413,7 @@ func Test_loginRun_nontty(t *testing.T) { Token: "abc456", }, env: map[string]string{"GH_ENTERPRISE_TOKEN": "value_from_env"}, - wantErr: "SilentError", + wantErr: "ErrSilent", wantStderr: heredoc.Doc(` The value of the GH_ENTERPRISE_TOKEN environment variable is being used for authentication. To have GitHub CLI store credentials instead, first clear the value from the environment. diff --git a/pkg/cmd/auth/logout/logout.go b/pkg/cmd/auth/logout/logout.go index dd908a62d..c18d119f1 100644 --- a/pkg/cmd/auth/logout/logout.go +++ b/pkg/cmd/auth/logout/logout.go @@ -147,7 +147,7 @@ func logoutRun(opts *LogoutOptions) error { if src, writeable := shared.AuthTokenWriteable(authCfg, hostname); !writeable { fmt.Fprintf(opts.IO.ErrOut, "The value of the %s environment variable is being used for authentication.\n", src) fmt.Fprint(opts.IO.ErrOut, "To erase credentials stored in GitHub CLI, first clear the value from the environment.\n") - return cmdutil.SilentError + return cmdutil.ErrSilent } // We can ignore the error here because a host must always have an active user diff --git a/pkg/cmd/auth/refresh/refresh.go b/pkg/cmd/auth/refresh/refresh.go index c025df465..d82078b64 100644 --- a/pkg/cmd/auth/refresh/refresh.go +++ b/pkg/cmd/auth/refresh/refresh.go @@ -169,7 +169,7 @@ func refreshRun(opts *RefreshOptions) error { if src, writeable := shared.AuthTokenWriteable(authCfg, hostname); !writeable { fmt.Fprintf(opts.IO.ErrOut, "The value of the %s environment variable is being used for authentication.\n", src) fmt.Fprint(opts.IO.ErrOut, "To refresh credentials stored in GitHub CLI, first clear the value from the environment.\n") - return cmdutil.SilentError + return cmdutil.ErrSilent } additionalScopes := set.NewStringSet() diff --git a/pkg/cmd/auth/setupgit/setupgit.go b/pkg/cmd/auth/setupgit/setupgit.go index 0ff7b6903..06ec30df8 100644 --- a/pkg/cmd/auth/setupgit/setupgit.go +++ b/pkg/cmd/auth/setupgit/setupgit.go @@ -107,7 +107,7 @@ func setupGitRun(opts *SetupGitOptions) error { cs.Bold("gh auth login"), ) - return cmdutil.SilentError + return cmdutil.ErrSilent } for _, hostname := range hostnames { diff --git a/pkg/cmd/auth/setupgit/setupgit_test.go b/pkg/cmd/auth/setupgit/setupgit_test.go index 8d9dc2d21..1c0f16220 100644 --- a/pkg/cmd/auth/setupgit/setupgit_test.go +++ b/pkg/cmd/auth/setupgit/setupgit_test.go @@ -136,7 +136,7 @@ func Test_setupGitRun(t *testing.T) { { name: "when there are no known hosts and no hostname is provided, return an error", opts: &SetupGitOptions{}, - expectedErr: cmdutil.SilentError, + expectedErr: cmdutil.ErrSilent, expectedErrOut: "You are not logged into any GitHub hosts. Run gh auth login to authenticate.\n", }, { diff --git a/pkg/cmd/auth/shared/git_credential.go b/pkg/cmd/auth/shared/git_credential.go index e3136de43..0bf73bb20 100644 --- a/pkg/cmd/auth/shared/git_credential.go +++ b/pkg/cmd/auth/shared/git_credential.go @@ -56,7 +56,7 @@ func (flow *GitCredentialFlow) Prompt(hostname string) error { // Refs: // * https://git-scm.com/docs/git-config#_description // * https://github.com/cli/cli/pull/4109 - var errNotInstalled *git.NotInstalled + var errNotInstalled *git.NotInstalledError if errors.As(configuredHelperErr, &errNotInstalled) { return configuredHelperErr } diff --git a/pkg/cmd/auth/shared/login_flow.go b/pkg/cmd/auth/shared/login_flow.go index cd018430d..da7f28c6b 100644 --- a/pkg/cmd/auth/shared/login_flow.go +++ b/pkg/cmd/auth/shared/login_flow.go @@ -46,7 +46,7 @@ type LoginOptions struct { sshContext ssh.Context } -func Login(opts *LoginOptions) error { +func Login(opts *LoginOptions) error { //nolint:gocyclo cfg := opts.Config hostname := opts.Hostname httpClient := opts.HTTPClient diff --git a/pkg/cmd/auth/status/status.go b/pkg/cmd/auth/status/status.go index 348b9531d..ece0511ab 100644 --- a/pkg/cmd/auth/status/status.go +++ b/pkg/cmd/auth/status/status.go @@ -206,7 +206,7 @@ func statusRun(opts *StatusOptions) error { opts.Exporter.Write(opts.IO, newAuthStatus()) return nil } - return cmdutil.SilentError + return cmdutil.ErrSilent } if opts.Hostname != "" && !slices.Contains(hostnames, opts.Hostname) { @@ -217,7 +217,7 @@ func statusRun(opts *StatusOptions) error { opts.Exporter.Write(opts.IO, newAuthStatus()) return nil } - return cmdutil.SilentError + return cmdutil.ErrSilent } httpClient, err := opts.HttpClient() @@ -250,7 +250,7 @@ func statusRun(opts *StatusOptions) error { statuses.Hosts[hostname] = append(statuses.Hosts[hostname], entry) if finalErr == nil && entry.State != authEntryStateSuccess { - finalErr = cmdutil.SilentError + finalErr = cmdutil.ErrSilent } if opts.Active { @@ -274,7 +274,7 @@ func statusRun(opts *StatusOptions) error { statuses.Hosts[hostname] = append(statuses.Hosts[hostname], entry) if finalErr == nil && entry.State != authEntryStateSuccess { - finalErr = cmdutil.SilentError + finalErr = cmdutil.ErrSilent } } } diff --git a/pkg/cmd/auth/status/status_test.go b/pkg/cmd/auth/status/status_test.go index 4246b1e86..b40ef9474 100644 --- a/pkg/cmd/auth/status/status_test.go +++ b/pkg/cmd/auth/status/status_test.go @@ -118,7 +118,7 @@ func Test_statusRun(t *testing.T) { return nil, context.DeadlineExceeded }) }, - wantErr: cmdutil.SilentError, + wantErr: cmdutil.ErrSilent, wantErrOut: heredoc.Doc(` github.com X Timeout trying to log in to github.com account monalisa (GH_CONFIG_DIR/hosts.yml) @@ -178,7 +178,7 @@ func Test_statusRun(t *testing.T) { // mock for HeaderHasMinimumScopes api requests to a non-github.com host reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.StatusStringResponse(400, "no bueno")) }, - wantErr: cmdutil.SilentError, + wantErr: cmdutil.ErrSilent, wantErrOut: heredoc.Doc(` ghe.io X Failed to log in to ghe.io account monalisa-ghe (GH_CONFIG_DIR/hosts.yml) @@ -223,7 +223,7 @@ func Test_statusRun(t *testing.T) { // mocks for HeaderHasMinimumScopes api requests to a non-github.com host reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.StatusStringResponse(400, "no bueno")) }, - wantErr: cmdutil.SilentError, + wantErr: cmdutil.ErrSilent, wantErrOut: heredoc.Doc(` ghe.io X Failed to log in to ghe.io account monalisa-ghe (GH_CONFIG_DIR/hosts.yml) @@ -368,7 +368,7 @@ func Test_statusRun(t *testing.T) { login(t, c, "github.com", "monalisa", "abc123", "https") }, httpStubs: func(reg *httpmock.Registry) {}, - wantErr: cmdutil.SilentError, + wantErr: cmdutil.ErrSilent, wantErrOut: "You are not logged into any accounts on github.example.com\n", }, { @@ -420,7 +420,7 @@ func Test_statusRun(t *testing.T) { httpmock.GraphQL(`query UserCurrent\b`), httpmock.StringResponse(`{"data":{"viewer":{"login":"monalisa-ghe-2"}}}`)) }, - wantErr: cmdutil.SilentError, + wantErr: cmdutil.ErrSilent, wantErrOut: heredoc.Doc(` github.com ✓ Logged in to github.com account monalisa-2 (GH_CONFIG_DIR/hosts.yml) @@ -522,7 +522,7 @@ func Test_statusRun(t *testing.T) { // Error getting scopes for monalisa-ghe-2 reg.Register(httpmock.REST("GET", "api/v3/"), httpmock.StatusStringResponse(404, "{}")) }, - wantErr: cmdutil.SilentError, + wantErr: cmdutil.ErrSilent, wantErrOut: heredoc.Doc(` github.com ✓ Logged in to github.com account monalisa-2 (GH_CONFIG_DIR/hosts.yml) diff --git a/pkg/cmd/auth/switch/switch.go b/pkg/cmd/auth/switch/switch.go index 8822c407b..55d2bdf3b 100644 --- a/pkg/cmd/auth/switch/switch.go +++ b/pkg/cmd/auth/switch/switch.go @@ -158,7 +158,7 @@ func switchRun(opts *SwitchOptions) error { if src, writeable := shared.AuthTokenWriteable(authCfg, hostname); !writeable { fmt.Fprintf(opts.IO.ErrOut, "The value of the %s environment variable is being used for authentication.\n", src) fmt.Fprint(opts.IO.ErrOut, "To have GitHub CLI manage credentials instead, first clear the value from the environment.\n") - return cmdutil.SilentError + return cmdutil.ErrSilent } cs := opts.IO.ColorScheme() diff --git a/pkg/cmd/auth/switch/switch_test.go b/pkg/cmd/auth/switch/switch_test.go index ea55a33ca..69ada5b95 100644 --- a/pkg/cmd/auth/switch/switch_test.go +++ b/pkg/cmd/auth/switch/switch_test.go @@ -234,7 +234,7 @@ func TestSwitchRun(t *testing.T) { }, env: map[string]string{"GH_TOKEN": "unimportant-test-value"}, expectedFailure: failedExpectation{ - err: cmdutil.SilentError, + err: cmdutil.ErrSilent, stderr: "The value of the GH_TOKEN environment variable is being used for authentication.", }, }, diff --git a/pkg/cmd/codespace/create.go b/pkg/cmd/codespace/create.go index 8c580bed3..de77ebb83 100644 --- a/pkg/cmd/codespace/create.go +++ b/pkg/cmd/codespace/create.go @@ -120,7 +120,7 @@ func newCreateCmd(app *App) *cobra.Command { } // Create creates a new Codespace -func (a *App) Create(ctx context.Context, opts createOptions) error { +func (a *App) Create(ctx context.Context, opts createOptions) error { //nolint:gocyclo // Overrides for Codespace developers to target test environments vscsLocation := os.Getenv("VSCS_LOCATION") vscsTarget := os.Getenv("VSCS_TARGET") @@ -322,7 +322,7 @@ func (a *App) Create(ctx context.Context, opts createOptions) error { codespace, err = a.handleAdditionalPermissions(ctx, prompter, createParams, aerr.AllowPermissionsURL) if err != nil { - // this error could be a cmdutil.SilentError (in the case that the user opened the browser) so we don't want to wrap it + // this error could be a cmdutil.ErrSilent (in the case that the user opened the browser) so we don't want to wrap it return err } } @@ -355,7 +355,7 @@ func (a *App) handleAdditionalPermissions(ctx context.Context, prompter SurveyPr if !isInteractive { fmt.Fprintf(a.io.ErrOut, "%s in your browser to review and authorize additional permissions: %s\n", cs.Bold("Open this URL"), allowPermissionsURL) fmt.Fprintf(a.io.ErrOut, "Alternatively, you can run %q with the %q option to continue without authorizing additional permissions.\n", a.io.ColorScheme().Bold("create"), cs.Bold("--default-permissions")) - return nil, cmdutil.SilentError + return nil, cmdutil.ErrSilent } choices := []string{ diff --git a/pkg/cmd/codespace/create_test.go b/pkg/cmd/codespace/create_test.go index c5f11bd2f..aa04e954f 100644 --- a/pkg/cmd/codespace/create_test.go +++ b/pkg/cmd/codespace/create_test.go @@ -56,7 +56,7 @@ func TestCreateCmdFlagError(t *testing.T) { } } -func TestApp_Create(t *testing.T) { +func TestApp_Create(t *testing.T) { //nolint:gocyclo type fields struct { apiClient apiClient } @@ -373,7 +373,7 @@ func TestApp_Create(t *testing.T) { showStatus: false, idleTimeout: 30 * time.Minute, }, - wantErr: cmdutil.SilentError, + wantErr: cmdutil.ErrSilent, wantStderr: ` ✓ Codespaces usage for this repository is paid for by monalisa You must authorize or deny additional permissions requested by this codespace before continuing. Open this URL in your browser to review and authorize additional permissions: https://example.com/permissions @@ -405,7 +405,7 @@ Alternatively, you can run "create" with the "--default-permissions" option to c showStatus: false, idleTimeout: 30 * time.Minute, }, - wantErr: cmdutil.SilentError, + wantErr: cmdutil.ErrSilent, wantStderr: ` ✓ Codespaces usage for this repository is paid for by monalisa You must authorize or deny additional permissions requested by this codespace before continuing. Open this URL in your browser to review and authorize additional permissions: https://example.com/permissions?ref=feature-branch&devcontainer_path=.devcontainer/actions/devcontainer.json diff --git a/pkg/cmd/codespace/delete.go b/pkg/cmd/codespace/delete.go index 5da24a634..9723f5843 100644 --- a/pkg/cmd/codespace/delete.go +++ b/pkg/cmd/codespace/delete.go @@ -89,7 +89,7 @@ func newDeleteCmd(app *App) *cobra.Command { return deleteCmd } -func (a *App) Delete(ctx context.Context, opts deleteOptions) (err error) { +func (a *App) Delete(ctx context.Context, opts deleteOptions) (err error) { //nolint:gocyclo var codespaces []*api.Codespace nameFilter := opts.codespaceName if nameFilter == "" { diff --git a/pkg/cmd/codespace/ssh.go b/pkg/cmd/codespace/ssh.go index 9550dd001..2e56a5dbf 100644 --- a/pkg/cmd/codespace/ssh.go +++ b/pkg/cmd/codespace/ssh.go @@ -580,7 +580,7 @@ func (a *App) printOpenSSHConfig(ctx context.Context, opts sshOptions) (err erro for _, cs := range csList { if cs.State != "Available" && opts.selector.codespaceName == "" { fmt.Fprintf(os.Stderr, "skipping unavailable codespace %s: %s\n", cs.Name, cs.State) - status = cmdutil.SilentError + status = cmdutil.ErrSilent continue } @@ -654,7 +654,7 @@ func (a *App) printOpenSSHConfig(ctx context.Context, opts sshOptions) (err erro for result := range sshUsers { if result.err != nil { fmt.Fprintf(os.Stderr, "%v\n", result.err) - status = cmdutil.SilentError + status = cmdutil.ErrSilent continue } diff --git a/pkg/cmd/copilot/copilot.go b/pkg/cmd/copilot/copilot.go index 4ab840709..a7f99225b 100644 --- a/pkg/cmd/copilot/copilot.go +++ b/pkg/cmd/copilot/copilot.go @@ -148,11 +148,11 @@ func runCopilot(opts *CopilotOptions) error { } if !confirmed { fmt.Fprintf(opts.IO.ErrOut, "%s Copilot CLI was not installed", opts.IO.ColorScheme().WarningIcon()) - return cmdutil.SilentError + return cmdutil.ErrSilent } } else if !update.IsCI() { fmt.Fprintf(opts.IO.ErrOut, "%s Copilot CLI not installed", opts.IO.ColorScheme().WarningIcon()) - return cmdutil.SilentError + return cmdutil.ErrSilent } httpClient, err := opts.HttpClient() diff --git a/pkg/cmd/extension/browse/browse.go b/pkg/cmd/extension/browse/browse.go index 21d254956..6804ca36c 100644 --- a/pkg/cmd/extension/browse/browse.go +++ b/pkg/cmd/extension/browse/browse.go @@ -377,7 +377,7 @@ func getExtensions(opts ExtBrowseOpts) ([]extEntry, error) { return extEntries, nil } -func ExtBrowse(opts ExtBrowseOpts) error { +func ExtBrowse(opts ExtBrowseOpts) error { //nolint:gocyclo if opts.Debug { f, err := os.CreateTemp("", "extBrowse-*.txt") if err != nil { diff --git a/pkg/cmd/extension/command.go b/pkg/cmd/extension/command.go index 057f91140..51eeed26a 100644 --- a/pkg/cmd/extension/command.go +++ b/pkg/cmd/extension/command.go @@ -23,9 +23,9 @@ import ( "github.com/spf13/cobra" ) -var alreadyInstalledError = errors.New("alreadyInstalledError") +var errAlreadyInstalled = errors.New("errAlreadyInstalled") -func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { +func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { //nolint:gocyclo m := f.ExtensionManager io := f.IOStreams gc := f.GitClient @@ -61,12 +61,12 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { if err != nil { if name != "" { fmt.Fprintf(io.ErrOut, "%s Failed upgrading extension %s: %s\n", cs.FailureIcon(), name, err) - } else if errors.Is(err, noExtensionsInstalledError) { + } else if errors.Is(err, errNoExtensionsInstalled) { return cmdutil.NewNoResultsError("no installed extensions found") } else { fmt.Fprintf(io.ErrOut, "%s Failed upgrading extensions\n", cs.FailureIcon()) } - return cmdutil.SilentError + return cmdutil.ErrSilent } if io.IsStdoutTTY() { @@ -354,11 +354,11 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { } err = m.InstallLocal(wd) - var ErrExtensionExecutableNotFound *ErrExtensionExecutableNotFound - if errors.As(err, &ErrExtensionExecutableNotFound) { + var ExtensionExecutableNotFoundError *ExtensionExecutableNotFoundError + if errors.As(err, &ExtensionExecutableNotFoundError) { cs := io.ColorScheme() if io.IsStdoutTTY() { - fmt.Fprintf(io.ErrOut, "%s %s", cs.WarningIcon(), ErrExtensionExecutableNotFound.Error()) + fmt.Fprintf(io.ErrOut, "%s %s", cs.WarningIcon(), ExtensionExecutableNotFoundError.Error()) } return nil } @@ -378,7 +378,7 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { return upgradeFunc(ext.Name(), forceFlag) } - if errors.Is(err, alreadyInstalledError) { + if errors.Is(err, errAlreadyInstalled) { fmt.Fprintf(io.ErrOut, "%s Extension %s is already installed\n", cs.WarningIcon(), ghrepo.FullName(repo)) return nil } @@ -391,13 +391,13 @@ func NewCmdExtension(f *cmdutil.Factory) *cobra.Command { io.StopProgressIndicator() if err != nil { - if errors.Is(err, releaseNotFoundErr) { + if errors.Is(err, errReleaseNotFound) { return fmt.Errorf("%s Could not find a release of %s for %s", cs.FailureIcon(), args[0], cs.Cyan(pinFlag)) - } else if errors.Is(err, commitNotFoundErr) { + } else if errors.Is(err, errCommitNotFound) { return fmt.Errorf("%s %s does not exist in %s", cs.FailureIcon(), cs.Cyan(pinFlag), args[0]) - } else if errors.Is(err, repositoryNotFoundErr) { + } else if errors.Is(err, errRepositoryNotFound) { return fmt.Errorf("%s Could not find extension '%s' on host %s", cs.FailureIcon(), args[0], repo.RepoHost()) } @@ -698,7 +698,7 @@ func checkValidExtension(rootCmd *cobra.Command, m extensions.ExtensionManager, for _, ext := range m.List() { if ext.Name() == commandName { if extOwner != "" && ext.Owner() == extOwner { - return ext, alreadyInstalledError + return ext, errAlreadyInstalled } return ext, fmt.Errorf("there is already an installed extension that provides the %q command", commandName) } diff --git a/pkg/cmd/extension/command_test.go b/pkg/cmd/extension/command_test.go index 7001c8f1a..683a3cdd8 100644 --- a/pkg/cmd/extension/command_test.go +++ b/pkg/cmd/extension/command_test.go @@ -290,7 +290,7 @@ func TestNewCmdExtension(t *testing.T) { args: []string{"install", "."}, managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) { em.InstallLocalFunc = func(dir string) error { - return &ErrExtensionExecutableNotFound{ + return &ExtensionExecutableNotFoundError{ Dir: tempDir, Name: "gh-test", } @@ -309,7 +309,7 @@ func TestNewCmdExtension(t *testing.T) { args: []string{"install", "."}, managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) { em.InstallLocalFunc = func(dir string) error { - return &ErrExtensionExecutableNotFound{ + return &ExtensionExecutableNotFoundError{ Dir: tempDir, Name: "gh-test", } @@ -331,7 +331,7 @@ func TestNewCmdExtension(t *testing.T) { return []extensions.Extension{} } em.InstallFunc = func(_ ghrepo.Interface, _ string) error { - return repositoryNotFoundErr + return errRepositoryNotFound } return func(t *testing.T) { installCalls := em.InstallCalls() @@ -445,7 +445,7 @@ func TestNewCmdExtension(t *testing.T) { }, isTTY: false, wantErr: true, - errMsg: "SilentError", + errMsg: "ErrSilent", wantStdout: "", wantStderr: "X Failed upgrading extension hello: oh no\n", }, @@ -522,7 +522,7 @@ func TestNewCmdExtension(t *testing.T) { args: []string{"upgrade", "--all"}, managerStubs: func(em *extensions.ExtensionManagerMock) func(*testing.T) { em.UpgradeFunc = func(name string, force bool) error { - return noExtensionsInstalledError + return errNoExtensionsInstalled } return func(t *testing.T) { calls := em.UpgradeCalls() @@ -1052,7 +1052,7 @@ func Test_checkValidExtension(t *testing.T) { extOwner: "monalisa", extName: "gh-triage", }, - wantError: "alreadyInstalledError", + wantError: "errAlreadyInstalled", }, } for _, tt := range tests { diff --git a/pkg/cmd/extension/http.go b/pkg/cmd/extension/http.go index 90ccd64ce..f55075276 100644 --- a/pkg/cmd/extension/http.go +++ b/pkg/cmd/extension/http.go @@ -107,9 +107,9 @@ func downloadAsset(httpClient *http.Client, asset releaseAsset, destPath string) return } -var commitNotFoundErr = errors.New("commit not found") -var releaseNotFoundErr = errors.New("release not found") -var repositoryNotFoundErr = errors.New("repository not found") +var errCommitNotFound = errors.New("commit not found") +var errReleaseNotFound = errors.New("release not found") +var errRepositoryNotFound = errors.New("repository not found") // fetchLatestRelease finds the latest published release for a repository. func fetchLatestRelease(httpClient *http.Client, baseRepo ghrepo.Interface) (*release, error) { @@ -127,7 +127,7 @@ func fetchLatestRelease(httpClient *http.Client, baseRepo ghrepo.Interface) (*re defer resp.Body.Close() if resp.StatusCode == 404 { - return nil, releaseNotFoundErr + return nil, errReleaseNotFound } if resp.StatusCode > 299 { return nil, api.HandleHTTPError(resp) @@ -164,7 +164,7 @@ func fetchReleaseFromTag(httpClient *http.Client, baseRepo ghrepo.Interface, tag defer resp.Body.Close() if resp.StatusCode == 404 { - return nil, releaseNotFoundErr + return nil, errReleaseNotFound } if resp.StatusCode > 299 { return nil, api.HandleHTTPError(resp) @@ -201,7 +201,7 @@ func fetchCommitSHA(httpClient *http.Client, baseRepo ghrepo.Interface, targetRe defer resp.Body.Close() if resp.StatusCode == 422 { - return "", commitNotFoundErr + return "", errCommitNotFound } if resp.StatusCode > 299 { return "", api.HandleHTTPError(resp) diff --git a/pkg/cmd/extension/manager.go b/pkg/cmd/extension/manager.go index de758f5a3..a0c21c70a 100644 --- a/pkg/cmd/extension/manager.go +++ b/pkg/cmd/extension/manager.go @@ -30,12 +30,12 @@ import ( // ErrInitialCommitFailed indicates the initial commit when making a new extension failed. var ErrInitialCommitFailed = errors.New("initial commit failed") -type ErrExtensionExecutableNotFound struct { +type ExtensionExecutableNotFoundError struct { Dir string Name string } -func (e *ErrExtensionExecutableNotFound) Error() string { +func (e *ExtensionExecutableNotFoundError) Error() string { return fmt.Sprintf("an extension has been installed but there is no executable: executable file named \"%s\" in %s is required to run the extension after install. Perhaps you need to build it?\n", e.Name, e.Dir) } @@ -225,7 +225,7 @@ func (m *Manager) InstallLocal(dir string) error { // the executable file is built or created manually somehow. if _, err := os.Stat(filepath.Join(dir, name)); err != nil { if os.IsNotExist(err) { - return &ErrExtensionExecutableNotFound{ + return &ExtensionExecutableNotFoundError{ Dir: dir, Name: name, } @@ -249,11 +249,11 @@ type binManifest struct { func (m *Manager) Install(repo ghrepo.Interface, target string) error { isBin, err := isBinExtension(m.client, repo) if err != nil { - if errors.Is(err, releaseNotFoundErr) { + if errors.Is(err, errReleaseNotFound) { if ok, err := repoExists(m.client, repo); err != nil { return err } else if !ok { - return repositoryNotFoundErr + return errRepositoryNotFound } } else { return fmt.Errorf("could not check for binary extension: %w", err) @@ -446,10 +446,10 @@ func (m *Manager) installGit(repo ghrepo.Interface, target string) error { return f.Close() } -var pinnedExtensionUpgradeError = errors.New("pinned extensions can not be upgraded") -var localExtensionUpgradeError = errors.New("local extensions can not be upgraded") -var upToDateError = errors.New("already up to date") -var noExtensionsInstalledError = errors.New("no extensions installed") +var errPinnedExtensionUpgrade = errors.New("pinned extensions can not be upgraded") +var errLocalExtensionUpgrade = errors.New("local extensions can not be upgraded") +var errUpToDate = errors.New("already up to date") +var errNoExtensionsInstalled = errors.New("no extensions installed") func (m *Manager) Upgrade(name string, force bool) error { // Fetch metadata during list only when upgrading all extensions. @@ -458,7 +458,7 @@ func (m *Manager) Upgrade(name string, force bool) error { fetchMetadata := name == "" exts, _ := m.list(fetchMetadata) if len(exts) == 0 { - return noExtensionsInstalledError + return errNoExtensionsInstalled } if name == "" { return m.upgradeExtensions(exts, force) @@ -468,7 +468,7 @@ func (m *Manager) Upgrade(name string, force bool) error { continue } if f.IsLocal() { - return localExtensionUpgradeError + return errLocalExtensionUpgrade } // For single extensions manually retrieve latest version since we forgo doing it during list. if latestVersion := f.LatestVersion(); latestVersion == "" { @@ -491,9 +491,9 @@ func (m *Manager) upgradeExtensions(exts []*Extension, force bool) error { currentVersion := displayExtensionVersion(f, f.CurrentVersion()) err := m.upgradeExtension(f, force) if err != nil { - if !errors.Is(err, localExtensionUpgradeError) && - !errors.Is(err, upToDateError) && - !errors.Is(err, pinnedExtensionUpgradeError) { + if !errors.Is(err, errLocalExtensionUpgrade) && + !errors.Is(err, errUpToDate) && + !errors.Is(err, errPinnedExtensionUpgrade) { failed = true } fmt.Fprintf(m.io.Out, "%s\n", err) @@ -514,13 +514,13 @@ func (m *Manager) upgradeExtensions(exts []*Extension, force bool) error { func (m *Manager) upgradeExtension(ext *Extension, force bool) error { if ext.IsLocal() { - return localExtensionUpgradeError + return errLocalExtensionUpgrade } if !force && ext.IsPinned() { - return pinnedExtensionUpgradeError + return errPinnedExtensionUpgrade } if !ext.UpdateAvailable() { - return upToDateError + return errUpToDate } var err error if ext.IsBinary() { diff --git a/pkg/cmd/extension/manager_test.go b/pkg/cmd/extension/manager_test.go index 91887022c..bdc9ea5f1 100644 --- a/pkg/cmd/extension/manager_test.go +++ b/pkg/cmd/extension/manager_test.go @@ -719,7 +719,7 @@ func TestManager_UpgradeExtension_BinaryExtension_Pinned(t *testing.T) { err = m.upgradeExtension(ext, false) assert.NotNil(t, err) - assert.Equal(t, err, pinnedExtensionUpgradeError) + assert.Equal(t, err, errPinnedExtensionUpgrade) } func TestManager_UpgradeExtension_GitExtension_Pinned(t *testing.T) { @@ -746,7 +746,7 @@ func TestManager_UpgradeExtension_GitExtension_Pinned(t *testing.T) { err = m.upgradeExtension(ext, false) assert.NotNil(t, err) - assert.Equal(t, err, pinnedExtensionUpgradeError) + assert.Equal(t, err, errPinnedExtensionUpgrade) gc.AssertExpectations(t) gcOne.AssertExpectations(t) } @@ -814,7 +814,7 @@ func TestManager_Install_local_no_executable_found(t *testing.T) { // to simulate an attempt to install a local extension without an executable err := m.InstallLocal(localDir) - require.ErrorAs(t, err, new(*ErrExtensionExecutableNotFound)) + require.ErrorAs(t, err, new(*ExtensionExecutableNotFoundError)) assert.Equal(t, "", stdout.String()) assert.Equal(t, "", stderr.String()) require.NoDirExistsf(t, extensionUpdatePath, "update directory should be removed") @@ -1274,8 +1274,8 @@ func TestManager_repo_not_found(t *testing.T) { m := newTestManager(dataDir, updateDir, &http.Client{Transport: ®}, nil, ios) - if err := m.Install(repo, ""); err != repositoryNotFoundErr { - t.Errorf("expected repositoryNotFoundErr, got: %v", err) + if err := m.Install(repo, ""); err != errRepositoryNotFound { + t.Errorf("expected errRepositoryNotFound, got: %v", err) } assert.Equal(t, "", stdout.String()) diff --git a/pkg/cmd/gist/create/create.go b/pkg/cmd/gist/create/create.go index 04429ddfd..a80899149 100644 --- a/pkg/cmd/gist/create/create.go +++ b/pkg/cmd/gist/create/create.go @@ -160,7 +160,7 @@ func createRun(opts *CreateOptions) error { if httpError.StatusCode == http.StatusUnprocessableEntity { if detectEmptyFiles(files) { fmt.Fprintf(errOut, "%s Failed to create gist: %s\n", cs.FailureIcon(), "a gist file cannot be blank") - return cmdutil.SilentError + return cmdutil.ErrSilent } } } diff --git a/pkg/cmd/gist/delete/delete.go b/pkg/cmd/gist/delete/delete.go index 319f9265e..122630e34 100644 --- a/pkg/cmd/gist/delete/delete.go +++ b/pkg/cmd/gist/delete/delete.go @@ -118,13 +118,13 @@ func deleteRun(opts *DeleteOptions) error { return err } if !confirmed { - return cmdutil.CancelError + return cmdutil.ErrCancel } } apiClient := api.NewClientFromHTTP(client) if err := deleteGist(apiClient, host, gist.ID); err != nil { - if errors.Is(err, shared.NotFoundErr) { + if errors.Is(err, shared.ErrNotFound) { return fmt.Errorf("unable to delete gist %q: either the gist is not found or it is not owned by you", gist.Filename()) } return err @@ -147,7 +147,7 @@ func deleteGist(apiClient *api.Client, hostname string, gistID string) error { if err != nil { var httpErr api.HTTPError if errors.As(err, &httpErr) && httpErr.StatusCode == 404 { - return shared.NotFoundErr + return shared.ErrNotFound } return err } diff --git a/pkg/cmd/gist/delete/delete_test.go b/pkg/cmd/gist/delete/delete_test.go index cb938d6f2..570b9806c 100644 --- a/pkg/cmd/gist/delete/delete_test.go +++ b/pkg/cmd/gist/delete/delete_test.go @@ -355,7 +355,7 @@ func Test_gistDelete(t *testing.T) { }, hostname: "github.com", gistID: "1234", - wantErr: shared.NotFoundErr, // To make sure we return the pre-defined error instance. + wantErr: shared.ErrNotFound, // To make sure we return the pre-defined error instance. wantErrString: "not found", }, { diff --git a/pkg/cmd/gist/edit/edit.go b/pkg/cmd/gist/edit/edit.go index 68414359c..a89e3f11d 100644 --- a/pkg/cmd/gist/edit/edit.go +++ b/pkg/cmd/gist/edit/edit.go @@ -114,7 +114,7 @@ func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Comman return cmd } -func editRun(opts *EditOptions) error { +func editRun(opts *EditOptions) error { //nolint:gocyclo client, err := opts.HttpClient() if err != nil { return err @@ -160,7 +160,7 @@ func editRun(opts *EditOptions) error { gist, err := shared.GetGist(client, host, gistID) if err != nil { - if errors.Is(err, shared.NotFoundErr) { + if errors.Is(err, shared.ErrNotFound) { return fmt.Errorf("gist not found: %s", gistID) } return err @@ -349,7 +349,7 @@ func editRun(opts *EditOptions) error { case "Submit": stop = true case "Cancel": - return cmdutil.CancelError + return cmdutil.ErrCancel } if stop { diff --git a/pkg/cmd/gist/edit/edit_test.go b/pkg/cmd/gist/edit/edit_test.go index ac1555f5c..91c5b2416 100644 --- a/pkg/cmd/gist/edit/edit_test.go +++ b/pkg/cmd/gist/edit/edit_test.go @@ -282,7 +282,7 @@ func Test_editRun(t *testing.T) { return prompter.IndexFor(opts, "Cancel") }) }, - wantErr: "CancelError", + wantErr: "ErrCancel", mockGist: &shared.Gist{ ID: "1234", Files: map[string]*shared.GistFile{ diff --git a/pkg/cmd/gist/rename/rename.go b/pkg/cmd/gist/rename/rename.go index 96f630c02..3f555ace8 100644 --- a/pkg/cmd/gist/rename/rename.go +++ b/pkg/cmd/gist/rename/rename.go @@ -82,7 +82,7 @@ func renameRun(opts *RenameOptions) error { gist, err := shared.GetGist(client, host, gistID) if err != nil { - if errors.Is(err, shared.NotFoundErr) { + if errors.Is(err, shared.ErrNotFound) { return fmt.Errorf("gist not found: %s", gistID) } return err diff --git a/pkg/cmd/gist/shared/shared.go b/pkg/cmd/gist/shared/shared.go index 305e2f642..5246067cf 100644 --- a/pkg/cmd/gist/shared/shared.go +++ b/pkg/cmd/gist/shared/shared.go @@ -58,7 +58,7 @@ func (g Gist) TruncDescription() string { return text.Truncate(100, text.RemoveExcessiveWhitespace(g.Description)) } -var NotFoundErr = errors.New("not found") +var ErrNotFound = errors.New("not found") func GetGist(client *http.Client, hostname, gistID string) (*Gist, error) { gist := Gist{} @@ -69,7 +69,7 @@ func GetGist(client *http.Client, hostname, gistID string) (*Gist, error) { if err != nil { var httpErr api.HTTPError if errors.As(err, &httpErr) && httpErr.StatusCode == 404 { - return nil, NotFoundErr + return nil, ErrNotFound } return nil, err } diff --git a/pkg/cmd/gist/view/view.go b/pkg/cmd/gist/view/view.go index 9eb906cde..0b78c2d04 100644 --- a/pkg/cmd/gist/view/view.go +++ b/pkg/cmd/gist/view/view.go @@ -73,7 +73,7 @@ func NewCmdView(f *cmdutil.Factory, runF func(*ViewOptions) error) *cobra.Comman return cmd } -func viewRun(opts *ViewOptions) error { +func viewRun(opts *ViewOptions) error { //nolint:gocyclo gistID := opts.Selector client, err := opts.HttpClient() if err != nil { diff --git a/pkg/cmd/gpg-key/add/add.go b/pkg/cmd/gpg-key/add/add.go index 35ee12736..4eb1f25f2 100644 --- a/pkg/cmd/gpg-key/add/add.go +++ b/pkg/cmd/gpg-key/add/add.go @@ -87,11 +87,11 @@ func runAdd(opts *AddOptions) error { if errors.Is(err, errScopesMissing) { fmt.Fprint(opts.IO.ErrOut, "Error: insufficient OAuth scopes to list GPG keys\n") fmt.Fprintf(opts.IO.ErrOut, "Run the following to grant scopes: %s\n", cs.Bold("gh auth refresh -s write:gpg_key")) - return cmdutil.SilentError + return cmdutil.ErrSilent } if errors.Is(err, errDuplicateKey) { fmt.Fprintf(opts.IO.ErrOut, "%s Error: the key already exists in your account\n", cs.FailureIcon()) - return cmdutil.SilentError + return cmdutil.ErrSilent } if errors.Is(err, errWrongFormat) { fmt.Fprint(opts.IO.ErrOut, heredoc.Docf(` @@ -99,7 +99,7 @@ func runAdd(opts *AddOptions) error { Find your GPG key ID with: %s Then add it to your account: %s `, cs.FailureIcon(), cs.Bold("gpg --list-keys"), cs.Bold("gpg --armor --export | gh gpg-key add -"))) - return cmdutil.SilentError + return cmdutil.ErrSilent } return err } diff --git a/pkg/cmd/gpg-key/add/add_test.go b/pkg/cmd/gpg-key/add/add_test.go index c6d7c18fb..dff959ae2 100644 --- a/pkg/cmd/gpg-key/add/add_test.go +++ b/pkg/cmd/gpg-key/add/add_test.go @@ -77,7 +77,7 @@ func Test_runAdd(t *testing.T) { Find your GPG key ID with: gpg --list-keys Then add it to your account: gpg --armor --export | gh gpg-key add - `), - wantErrMsg: "SilentError", + wantErrMsg: "ErrSilent", opts: AddOptions{KeyFile: "-"}, }, { @@ -105,7 +105,7 @@ func Test_runAdd(t *testing.T) { }, wantStdout: "", wantStderr: "X Error: the key already exists in your account\n", - wantErrMsg: "SilentError", + wantErrMsg: "ErrSilent", opts: AddOptions{KeyFile: "-"}, }, } diff --git a/pkg/cmd/gpg-key/list/list.go b/pkg/cmd/gpg-key/list/list.go index 4244ba349..b330f9f68 100644 --- a/pkg/cmd/gpg-key/list/list.go +++ b/pkg/cmd/gpg-key/list/list.go @@ -61,7 +61,7 @@ func listRun(opts *ListOptions) error { cs := opts.IO.ColorScheme() fmt.Fprint(opts.IO.ErrOut, "Error: insufficient OAuth scopes to list GPG keys\n") fmt.Fprintf(opts.IO.ErrOut, "Run the following to grant scopes: %s\n", cs.Bold("gh auth refresh -s read:gpg_key")) - return cmdutil.SilentError + return cmdutil.ErrSilent } return err } diff --git a/pkg/cmd/issue/create/create.go b/pkg/cmd/issue/create/create.go index da3648c31..60f5ce24e 100644 --- a/pkg/cmd/issue/create/create.go +++ b/pkg/cmd/issue/create/create.go @@ -144,7 +144,7 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co return cmd } -func createRun(opts *CreateOptions) (err error) { +func createRun(opts *CreateOptions) (err error) { //nolint:gocyclo httpClient, err := opts.HttpClient() if err != nil { return @@ -326,7 +326,7 @@ func createRun(opts *CreateOptions) (err error) { if action == prShared.CancelAction { fmt.Fprintln(opts.IO.ErrOut, "Discarding.") - err = cmdutil.CancelError + err = cmdutil.ErrCancel return } } else { diff --git a/pkg/cmd/issue/delete/delete.go b/pkg/cmd/issue/delete/delete.go index 269ef7081..6990cf080 100644 --- a/pkg/cmd/issue/delete/delete.go +++ b/pkg/cmd/issue/delete/delete.go @@ -97,8 +97,7 @@ func deleteRun(opts *DeleteOptions) error { // When executed in an interactive shell, require confirmation, unless // already provided. Otherwise skip confirmation. if opts.IO.CanPrompt() && !opts.Confirmed { - cs := opts.IO.ColorScheme() - fmt.Printf("%s Deleted issues cannot be recovered.\n", cs.WarningIcon()) + fmt.Fprintf(opts.IO.ErrOut, "%s Deleted issues cannot be recovered.\n", cs.WarningIcon()) err := opts.Prompter.ConfirmDeletion(fmt.Sprintf("%d", issue.Number)) if err != nil { return err diff --git a/pkg/cmd/issue/lock/lock.go b/pkg/cmd/issue/lock/lock.go index a97f57ed9..64362edb7 100644 --- a/pkg/cmd/issue/lock/lock.go +++ b/pkg/cmd/issue/lock/lock.go @@ -50,14 +50,13 @@ var reasonsApi = []githubv4.LockReason{ // If no reason is given (an empty string), reasonsMap will return the nil // value, since it is not contained in the map. This, in turn, sets lock_reason // to null in GraphQL. -var reasonsMap map[string]*githubv4.LockReason - -func init() { - reasonsMap = make(map[string]*githubv4.LockReason) +var reasonsMap = func() map[string]*githubv4.LockReason { + m := make(map[string]*githubv4.LockReason) for i, reason := range reasons { - reasonsMap[reason] = &reasonsApi[i] + m[reason] = &reasonsApi[i] } -} + return m +}() type command struct { Name string // actual command name diff --git a/pkg/cmd/pr/checks/checks.go b/pkg/cmd/pr/checks/checks.go index 9256958aa..d251d6457 100644 --- a/pkg/cmd/pr/checks/checks.go +++ b/pkg/cmd/pr/checks/checks.go @@ -246,9 +246,9 @@ func checksRun(opts *ChecksOptions) error { } if counts.Failed > 0 { - return cmdutil.SilentError + return cmdutil.ErrSilent } else if counts.Pending > 0 { - return cmdutil.PendingError + return cmdutil.ErrPending } return nil diff --git a/pkg/cmd/pr/checks/checks_test.go b/pkg/cmd/pr/checks/checks_test.go index cbb8ddc7f..d34ed88f5 100644 --- a/pkg/cmd/pr/checks/checks_test.go +++ b/pkg/cmd/pr/checks/checks_test.go @@ -182,7 +182,7 @@ func Test_checksRun(t *testing.T) { ✓ cool tests 1m26s sweet link * slow tests 1m26s sweet link `), - wantErr: "SilentError", + wantErr: "ErrSilent", }, { name: "some cancelled tty", @@ -223,7 +223,7 @@ func Test_checksRun(t *testing.T) { * slow tests 1m26s sweet link - sad tests 1m26s sweet link `), - wantErr: "PendingError", + wantErr: "ErrPending", }, { name: "all passing tty", @@ -302,7 +302,7 @@ func Test_checksRun(t *testing.T) { ✓ cool tests 1m26s sweet link * slow tests 1m26s sweet link `, "\x1b"), - wantErr: "SilentError", + wantErr: "ErrSilent", }, { name: "with statuses tty", @@ -322,7 +322,7 @@ func Test_checksRun(t *testing.T) { ✓ cool tests 1m26s sweet link ✓ rad tests 1m26s sweet link `), - wantErr: "SilentError", + wantErr: "ErrSilent", }, { name: "no commits", @@ -355,7 +355,7 @@ func Test_checksRun(t *testing.T) { ) }, wantOut: "sad tests\tfail\t1m26s\tsweet link\t\ncool tests\tpass\t1m26s\tsweet link\t\nslow tests\tpending\t1m26s\tsweet link\t\n", - wantErr: "SilentError", + wantErr: "ErrSilent", }, { name: "some pending", @@ -366,7 +366,7 @@ func Test_checksRun(t *testing.T) { ) }, wantOut: "cool tests\tpass\t1m26s\tsweet link\t\nrad tests\tpass\t1m26s\tsweet link\t\nslow tests\tpending\t1m26s\tsweet link\t\nsad tests\tfail\t1m26s\tsweet link\t\n", - wantErr: "PendingError", + wantErr: "ErrPending", }, { name: "all passing", @@ -388,7 +388,7 @@ func Test_checksRun(t *testing.T) { ) }, wantOut: "a status\tfail\t0\tsweet link\t\ncool tests\tpass\t1m26s\tsweet link\t\nrad tests\tpass\t1m26s\tsweet link\t\n", - wantErr: "SilentError", + wantErr: "ErrSilent", }, { name: "some skipped tty", diff --git a/pkg/cmd/pr/close/close.go b/pkg/cmd/pr/close/close.go index 063501ef7..09ffbd7db 100644 --- a/pkg/cmd/pr/close/close.go +++ b/pkg/cmd/pr/close/close.go @@ -76,7 +76,7 @@ func closeRun(opts *CloseOptions) error { if pr.State == "MERGED" { fmt.Fprintf(opts.IO.ErrOut, "%s Pull request %s#%d (%s) can't be closed because it was already merged\n", cs.FailureIcon(), ghrepo.FullName(baseRepo), pr.Number, pr.Title) - return cmdutil.SilentError + return cmdutil.ErrSilent } else if !pr.IsOpen() { fmt.Fprintf(opts.IO.ErrOut, "%s Pull request %s#%d (%s) is already closed\n", cs.WarningIcon(), ghrepo.FullName(baseRepo), pr.Number, pr.Title) return nil diff --git a/pkg/cmd/pr/create/create.go b/pkg/cmd/pr/create/create.go index d67731095..2153316e5 100644 --- a/pkg/cmd/pr/create/create.go +++ b/pkg/cmd/pr/create/create.go @@ -191,7 +191,7 @@ type CreateContext struct { GitClient *git.Client } -func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Command { +func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Command { //nolint:gocyclo opts := &CreateOptions{ IO: f.IOStreams, HttpClient: f.HttpClient, @@ -373,7 +373,7 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co return cmd } -func createRun(opts *CreateOptions) error { +func createRun(opts *CreateOptions) error { //nolint:gocyclo ctx, err := NewCreateContext(opts) if err != nil { return err @@ -610,7 +610,7 @@ func createRun(opts *CreateOptions) error { if action == shared.CancelAction { fmt.Fprintln(opts.IO.ErrOut, "Discarding.") - err = cmdutil.CancelError + err = cmdutil.ErrCancel return err } @@ -703,7 +703,7 @@ func NewIssueState(ctx CreateContext, opts CreateOptions) (*shared.IssueMetadata return state, nil } -func NewCreateContext(opts *CreateOptions) (*CreateContext, error) { +func NewCreateContext(opts *CreateOptions) (*CreateContext, error) { //nolint:gocyclo httpClient, err := opts.HttpClient() if err != nil { return nil, err @@ -945,7 +945,7 @@ func NewCreateContext(opts *CreateOptions) (*CreateContext, error) { // If we haven't got a repo by now, and we can't prompt then it's game over. if !opts.IO.CanPrompt() { fmt.Fprintln(opts.IO.ErrOut, "aborted: you must first push the current branch to a remote, or use the --head flag") - return nil, cmdutil.SilentError + return nil, cmdutil.ErrSilent } // Otherwise, hooray, prompting! @@ -1006,7 +1006,7 @@ func NewCreateContext(opts *CreateOptions) (*CreateContext, error) { baseRefs: baseRefs, }), nil } else if pushOptions[selectedOption] == "Cancel" { - return nil, cmdutil.CancelError + return nil, cmdutil.ErrCancel } else { // A fork should be created. return newCreateContext(forkableRefs{ diff --git a/pkg/cmd/pr/create/create_test.go b/pkg/cmd/pr/create/create_test.go index baec719e0..6cd1232d5 100644 --- a/pkg/cmd/pr/create/create_test.go +++ b/pkg/cmd/pr/create/create_test.go @@ -330,7 +330,7 @@ func TestNewCmdCreate(t *testing.T) { } } -func Test_createRun(t *testing.T) { +func Test_createRun(t *testing.T) { //nolint:gocyclo tests := []struct { name string setup func(*CreateOptions, *testing.T) func() @@ -2330,7 +2330,7 @@ func TestNoRepoCanBeDetermined(t *testing.T) { err := createRun(&opts) // Then create fails - require.Equal(t, cmdutil.SilentError, err) + require.Equal(t, cmdutil.ErrSilent, err) assert.Equal(t, "aborted: you must first push the current branch to a remote, or use the --head flag\n", stderr.String()) } diff --git a/pkg/cmd/pr/edit/edit.go b/pkg/cmd/pr/edit/edit.go index f28a9afd2..e85a67793 100644 --- a/pkg/cmd/pr/edit/edit.go +++ b/pkg/cmd/pr/edit/edit.go @@ -39,7 +39,7 @@ type EditOptions struct { Interactive bool } -func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Command { +func NewCmdEdit(f *cmdutil.Factory, runF func(*EditOptions) error) *cobra.Command { //nolint:gocyclo opts := &EditOptions{ IO: f.IOStreams, HttpClient: f.HttpClient, diff --git a/pkg/cmd/pr/merge/merge.go b/pkg/cmd/pr/merge/merge.go index 2049b85ae..9d34edfbd 100644 --- a/pkg/cmd/pr/merge/merge.go +++ b/pkg/cmd/pr/merge/merge.go @@ -274,7 +274,7 @@ func (m *mergeContext) canMerge() error { // TODO: show this flag only to repo admins _ = m.warnf("To use administrator privileges to immediately merge the pull request, add the `--admin` flag.\n") } - return cmdutil.SilentError + return cmdutil.ErrSilent } // Merge the pull request. May prompt the user for input parameters for the merge. @@ -688,7 +688,7 @@ func confirmSubmission(client *http.Client, opts *MergeOptions, action shared.Ac case shared.CancelAction: fmt.Fprintln(opts.IO.ErrOut, "Cancelled.") - return false, cmdutil.CancelError + return false, cmdutil.ErrCancel case shared.SubmitAction: return true, nil diff --git a/pkg/cmd/pr/merge/merge_test.go b/pkg/cmd/pr/merge/merge_test.go index 03ddafa61..1ba858cda 100644 --- a/pkg/cmd/pr/merge/merge_test.go +++ b/pkg/cmd/pr/merge/merge_test.go @@ -366,7 +366,7 @@ func TestPrMerge_blocked(t *testing.T) { cs.Register(`git rev-parse --verify refs/heads/`, 0, "") output, err := runCommand(http, nil, "main", true, "pr merge 1 --merge") - assert.EqualError(t, err, "SilentError") + assert.EqualError(t, err, "ErrSilent") assert.Equal(t, "", output.String()) assert.Equal(t, heredoc.Docf(` @@ -399,7 +399,7 @@ func TestPrMerge_dirty(t *testing.T) { cs.Register(`git rev-parse --verify refs/heads/`, 0, "") output, err := runCommand(http, nil, "main", true, "pr merge 1 --merge") - assert.EqualError(t, err, "SilentError") + assert.EqualError(t, err, "ErrSilent") assert.Equal(t, "", output.String()) assert.Equal(t, heredoc.Docf(` @@ -1634,7 +1634,7 @@ func TestPRTTY_cancelled(t *testing.T) { } output, err := runCommand(http, pm, "blueberries", true, "") - if !errors.Is(err, cmdutil.CancelError) { + if !errors.Is(err, cmdutil.ErrCancel) { t.Fatalf("got error %v", err) } diff --git a/pkg/cmd/pr/ready/ready.go b/pkg/cmd/pr/ready/ready.go index 7b985a3ce..3bfdc0c24 100644 --- a/pkg/cmd/pr/ready/ready.go +++ b/pkg/cmd/pr/ready/ready.go @@ -77,7 +77,7 @@ func readyRun(opts *ReadyOptions) error { if !pr.IsOpen() { fmt.Fprintf(opts.IO.ErrOut, "%s Pull request %s#%d is closed. Only draft pull requests can be marked as \"ready for review\"\n", cs.FailureIcon(), ghrepo.FullName(baseRepo), pr.Number) - return cmdutil.SilentError + return cmdutil.ErrSilent } httpClient, err := opts.HttpClient() diff --git a/pkg/cmd/pr/ready/ready_test.go b/pkg/cmd/pr/ready/ready_test.go index 5a6053a17..7c6e44443 100644 --- a/pkg/cmd/pr/ready/ready_test.go +++ b/pkg/cmd/pr/ready/ready_test.go @@ -216,7 +216,7 @@ func TestPRReady_closed(t *testing.T) { }, ghrepo.New("OWNER", "REPO")) output, err := runCommand(http, true, "123") - assert.EqualError(t, err, "SilentError") + assert.EqualError(t, err, "ErrSilent") assert.Equal(t, "", output.String()) assert.Equal(t, "X Pull request OWNER/REPO#123 is closed. Only draft pull requests can be marked as \"ready for review\"\n", output.Stderr()) } diff --git a/pkg/cmd/pr/reopen/reopen.go b/pkg/cmd/pr/reopen/reopen.go index 2aae2b8f5..d6bc27fb9 100644 --- a/pkg/cmd/pr/reopen/reopen.go +++ b/pkg/cmd/pr/reopen/reopen.go @@ -65,7 +65,7 @@ func reopenRun(opts *ReopenOptions) error { if pr.State == "MERGED" { fmt.Fprintf(opts.IO.ErrOut, "%s Pull request %s#%d (%s) can't be reopened because it was already merged\n", cs.FailureIcon(), ghrepo.FullName(baseRepo), pr.Number, pr.Title) - return cmdutil.SilentError + return cmdutil.ErrSilent } if pr.IsOpen() { diff --git a/pkg/cmd/pr/reopen/reopen_test.go b/pkg/cmd/pr/reopen/reopen_test.go index 9fb3702c0..d5bc1cd2c 100644 --- a/pkg/cmd/pr/reopen/reopen_test.go +++ b/pkg/cmd/pr/reopen/reopen_test.go @@ -103,7 +103,7 @@ func TestPRReopen_alreadyMerged(t *testing.T) { }, ghrepo.New("OWNER", "REPO")) output, err := runCommand(http, true, "123") - assert.EqualError(t, err, "SilentError") + assert.EqualError(t, err, "ErrSilent") assert.Equal(t, "", output.String()) assert.Equal(t, "X Pull request OWNER/REPO#123 (The title of the PR) can't be reopened because it was already merged\n", output.Stderr()) } diff --git a/pkg/cmd/pr/revert/revert.go b/pkg/cmd/pr/revert/revert.go index 544550d41..fa6bfa0c2 100644 --- a/pkg/cmd/pr/revert/revert.go +++ b/pkg/cmd/pr/revert/revert.go @@ -95,7 +95,7 @@ func revertRun(opts *RevertOptions) error { } if pr.State != "MERGED" { fmt.Fprintf(opts.IO.ErrOut, "%s Pull request %s#%d (%s) can't be reverted because it has not been merged\n", cs.FailureIcon(), ghrepo.FullName(baseRepo), pr.Number, pr.Title) - return cmdutil.SilentError + return cmdutil.ErrSilent } httpClient, err := opts.HttpClient() diff --git a/pkg/cmd/pr/revert/revert_test.go b/pkg/cmd/pr/revert/revert_test.go index 49e1a6efc..53de70d86 100644 --- a/pkg/cmd/pr/revert/revert_test.go +++ b/pkg/cmd/pr/revert/revert_test.go @@ -136,7 +136,7 @@ func TestPRRevert_notRevertable(t *testing.T) { // Target PR is not merged. output, err := runCommand(http, true, "123") // API error, non-zero exit. - assert.EqualError(t, err, "SilentError") + assert.EqualError(t, err, "ErrSilent") assert.Equal(t, "X Pull request OWNER/REPO#123 (The title of the PR) can't be reverted because it has not been merged\n", output.Stderr()) // No URL printed. assert.Equal(t, "", output.String()) @@ -317,7 +317,7 @@ func TestPRRevert_multipleInvocations(t *testing.T) { output, err = runCommand(http, true, "123") // Revert PR is not created, API error, non-zero exit. - assert.EqualError(t, err, "SilentError") + assert.EqualError(t, err, "ErrSilent") assert.Equal(t, "X Pull request OWNER/REPO#123 (The title of the PR) can't be reverted because it has not been merged\n", output.Stderr()) // No URL printed. assert.Equal(t, "", output.String()) diff --git a/pkg/cmd/pr/shared/finder.go b/pkg/cmd/pr/shared/finder.go index 80f1e707d..f3264cca4 100644 --- a/pkg/cmd/pr/shared/finder.go +++ b/pkg/cmd/pr/shared/finder.go @@ -108,7 +108,7 @@ type FindOptions struct { Detector fd.Detector } -func (f *finder) Find(opts FindOptions) (*api.PullRequest, ghrepo.Interface, error) { +func (f *finder) Find(opts FindOptions) (*api.PullRequest, ghrepo.Interface, error) { //nolint:gocyclo // If we have a URL, we don't need git stuff if len(opts.Fields) == 0 { return nil, nil, errors.New("Find error: no fields specified") diff --git a/pkg/cmd/pr/shared/git_cached_config_client.go b/pkg/cmd/pr/shared/git_cached_config_client.go index b65df507e..360c85281 100644 --- a/pkg/cmd/pr/shared/git_cached_config_client.go +++ b/pkg/cmd/pr/shared/git_cached_config_client.go @@ -10,6 +10,7 @@ var _ GitConfigClient = &CachedBranchConfigGitConfigClient{} type CachedBranchConfigGitConfigClient struct { GitConfigClient + CachedBranchConfig git.BranchConfig } diff --git a/pkg/cmd/pr/shared/survey.go b/pkg/cmd/pr/shared/survey.go index 303f2e372..4eae2cde0 100644 --- a/pkg/cmd/pr/shared/survey.go +++ b/pkg/cmd/pr/shared/survey.go @@ -154,7 +154,7 @@ func MetadataSurvey(p Prompt, io *iostreams.IOStreams, baseRepo ghrepo.Interface for _, c := range state.Metadata { if m == c { return true - } + } //nolint:gocyclo } return false } diff --git a/pkg/cmd/pr/update-branch/update_branch.go b/pkg/cmd/pr/update-branch/update_branch.go index ca3b2c910..9903f3145 100644 --- a/pkg/cmd/pr/update-branch/update_branch.go +++ b/pkg/cmd/pr/update-branch/update_branch.go @@ -90,7 +90,7 @@ func updateBranchRun(opts *UpdateBranchOptions) error { cs := opts.IO.ColorScheme() if pr.Mergeable == api.PullRequestMergeableConflicting { fmt.Fprintf(opts.IO.ErrOut, "%s Cannot update PR branch due to conflicts\n", cs.FailureIcon()) - return cmdutil.SilentError + return cmdutil.ErrSilent } httpClient, err := opts.HttpClient() @@ -126,7 +126,7 @@ func updateBranchRun(opts *UpdateBranchOptions) error { // TODO: this is a best effort approach and not a resilient way of handling API errors. if strings.Contains(err.Error(), "GraphQL: merge conflict between base and head (updatePullRequestBranch)") { fmt.Fprintf(opts.IO.ErrOut, "%s Cannot update PR branch due to conflicts\n", cs.FailureIcon()) - return cmdutil.SilentError + return cmdutil.ErrSilent } return err } diff --git a/pkg/cmd/pr/update-branch/update_branch_test.go b/pkg/cmd/pr/update-branch/update_branch_test.go index fa0902c3c..70ad47cb2 100644 --- a/pkg/cmd/pr/update-branch/update_branch_test.go +++ b/pkg/cmd/pr/update-branch/update_branch_test.go @@ -206,7 +206,7 @@ func Test_updateBranchRun(t *testing.T) { }, ghrepo.New("OWNER", "REPO")), }, stderr: "X Cannot update PR branch due to conflicts\n", - wantsErr: cmdutil.SilentError.Error(), + wantsErr: cmdutil.ErrSilent.Error(), }, { name: "success, merge", @@ -357,7 +357,7 @@ func Test_updateBranchRun(t *testing.T) { })) }, stderr: "X Cannot update PR branch due to conflicts\n", - wantsErr: cmdutil.SilentError.Error(), + wantsErr: cmdutil.ErrSilent.Error(), }, { name: "failure, API error on update request", diff --git a/pkg/cmd/project/item-edit/item_edit.go b/pkg/cmd/project/item-edit/item_edit.go index 6eb44caf4..1fca88d79 100644 --- a/pkg/cmd/project/item-edit/item_edit.go +++ b/pkg/cmd/project/item-edit/item_edit.go @@ -165,7 +165,7 @@ func runEditItem(config editItemConfig) error { if _, err := fmt.Fprintln(config.io.ErrOut, "error: no changes to make"); err != nil { return err } - return cmdutil.SilentError + return cmdutil.ErrSilent } func fetchDraftIssueByID(config editItemConfig, draftIssueID string) (*queries.DraftIssue, error) { diff --git a/pkg/cmd/project/item-edit/item_edit_test.go b/pkg/cmd/project/item-edit/item_edit_test.go index 64852bad5..a5f53595d 100644 --- a/pkg/cmd/project/item-edit/item_edit_test.go +++ b/pkg/cmd/project/item-edit/item_edit_test.go @@ -693,7 +693,7 @@ func TestRunItemEdit_NoChanges(t *testing.T) { } err := runEditItem(config) - assert.Error(t, err, "SilentError") + assert.Error(t, err, "ErrSilent") assert.Equal(t, "", stdout.String()) assert.Equal(t, "error: no changes to make\n", stderr.String()) } diff --git a/pkg/cmd/release/create/create.go b/pkg/cmd/release/create/create.go index 56ca9d133..1f2224200 100644 --- a/pkg/cmd/release/create/create.go +++ b/pkg/cmd/release/create/create.go @@ -224,7 +224,7 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co return cmd } -func createRun(opts *CreateOptions) error { +func createRun(opts *CreateOptions) error { //nolint:gocyclo httpClient, err := opts.HttpClient() if err != nil { return err @@ -329,7 +329,7 @@ func createRun(opts *CreateOptions) error { var generatedChangelog string generatedNotes, err = generateReleaseNotes(httpClient, baseRepo, opts.TagName, opts.Target, opts.NotesStartTag) - if err != nil && !errors.Is(err, notImplementedError) { + if err != nil && !errors.Is(err, errNotImplemented) { return err } @@ -438,7 +438,7 @@ func createRun(opts *CreateOptions) error { case "Save as draft": opts.Draft = true case "Cancel": - return cmdutil.CancelError + return cmdutil.ErrCancel default: return fmt.Errorf("invalid action: %v", opts.SubmitAction) } @@ -468,7 +468,7 @@ func createRun(opts *CreateOptions) error { if opts.GenerateNotes { if opts.NotesStartTag != "" { generatedNotes, err := generateReleaseNotes(httpClient, baseRepo, opts.TagName, opts.Target, opts.NotesStartTag) - if err != nil && !errors.Is(err, notImplementedError) { + if err != nil && !errors.Is(err, errNotImplemented) { return err } if generatedNotes != nil { @@ -512,9 +512,9 @@ func createRun(opts *CreateOptions) error { newRelease, err := createRelease(httpClient, baseRepo, params) - var errMissingRequiredWorkflowScope *errMissingRequiredWorkflowScope - if errors.As(err, &errMissingRequiredWorkflowScope) { - host := errMissingRequiredWorkflowScope.Hostname + var missingRequiredWorkflowScopeError *missingRequiredWorkflowScopeError + if errors.As(err, &missingRequiredWorkflowScopeError) { + host := missingRequiredWorkflowScopeError.Hostname refreshInstructions := fmt.Sprintf("gh auth refresh -h %[1]s -s workflow", host) cs := opts.IO.ColorScheme() @@ -523,7 +523,7 @@ func createRun(opts *CreateOptions) error { sb.WriteString(fmt.Sprintf("To request it, run:\n%s\n", cs.Bold(refreshInstructions))) fmt.Fprint(opts.IO.ErrOut, sb.String()) - return cmdutil.SilentError + return cmdutil.ErrSilent } if err != nil { diff --git a/pkg/cmd/release/create/create_test.go b/pkg/cmd/release/create/create_test.go index a6e6cd7c6..edf390625 100644 --- a/pkg/cmd/release/create/create_test.go +++ b/pkg/cmd/release/create/create_test.go @@ -1217,7 +1217,7 @@ func Test_createRun(t *testing.T) { To request it, run: gh auth refresh -h github.com -s workflow `), - wantErr: cmdutil.SilentError.Error(), + wantErr: cmdutil.ErrSilent.Error(), }, { name: "API returns 404, OAuth token has workflow scope", diff --git a/pkg/cmd/release/create/http.go b/pkg/cmd/release/create/http.go index 4311a3896..8274219c4 100644 --- a/pkg/cmd/release/create/http.go +++ b/pkg/cmd/release/create/http.go @@ -30,13 +30,13 @@ type releaseNotes struct { Body string `json:"body"` } -var notImplementedError = errors.New("not implemented") +var errNotImplemented = errors.New("not implemented") -type errMissingRequiredWorkflowScope struct { +type missingRequiredWorkflowScopeError struct { Hostname string } -func (e errMissingRequiredWorkflowScope) Error() string { +func (e missingRequiredWorkflowScopeError) Error() string { return "workflow scope may be required" } @@ -123,7 +123,7 @@ func generateReleaseNotes(httpClient *http.Client, repo ghrepo.Interface, tagNam defer resp.Body.Close() if resp.StatusCode == 404 { - return nil, notImplementedError + return nil, errNotImplemented } success := resp.StatusCode >= 200 && resp.StatusCode < 300 @@ -200,7 +200,7 @@ func createRelease(httpClient *http.Client, repo ghrepo.Interface, params map[st // https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes if resp.StatusCode == http.StatusNotFound && !tokenHasWorkflowScope(resp) { normalizedHostname := ghauth.NormalizeHostname(resp.Request.URL.Hostname()) - return nil, &errMissingRequiredWorkflowScope{ + return nil, &missingRequiredWorkflowScopeError{ Hostname: normalizedHostname, } } diff --git a/pkg/cmd/release/delete-asset/delete_asset.go b/pkg/cmd/release/delete-asset/delete_asset.go index b2e1f22fe..2ed5a31d5 100644 --- a/pkg/cmd/release/delete-asset/delete_asset.go +++ b/pkg/cmd/release/delete-asset/delete_asset.go @@ -81,7 +81,7 @@ func deleteAssetRun(opts *DeleteAssetOptions) error { } if !confirmed { - return cmdutil.CancelError + return cmdutil.ErrCancel } } diff --git a/pkg/cmd/release/delete/delete.go b/pkg/cmd/release/delete/delete.go index 622b18893..0a00898e4 100644 --- a/pkg/cmd/release/delete/delete.go +++ b/pkg/cmd/release/delete/delete.go @@ -88,7 +88,7 @@ func deleteRun(opts *DeleteOptions) error { } if !confirmed { - return cmdutil.CancelError + return cmdutil.ErrCancel } } diff --git a/pkg/cmd/release/shared/upload.go b/pkg/cmd/release/shared/upload.go index ab7533320..5dfe0d19c 100644 --- a/pkg/cmd/release/shared/upload.go +++ b/pkg/cmd/release/shared/upload.go @@ -23,7 +23,7 @@ type httpDoer interface { Do(*http.Request) (*http.Response, error) } -type errNetwork struct{ error } +type networkError struct{ error } type AssetForUpload struct { Name string @@ -131,7 +131,7 @@ func ConcurrentUpload(httpClient httpDoer, uploadURL string, numWorkers int, ass } func shouldRetry(err error) bool { - var networkError errNetwork + var networkError networkError if errors.As(err, &networkError) { return true } @@ -184,7 +184,7 @@ func uploadAsset(ctx context.Context, httpClient httpDoer, uploadURL string, ass resp, err := httpClient.Do(req) if err != nil { - return nil, errNetwork{err} + return nil, networkError{err} } defer resp.Body.Close() diff --git a/pkg/cmd/repo/archive/archive.go b/pkg/cmd/repo/archive/archive.go index 86e1a6df7..8199f0837 100644 --- a/pkg/cmd/repo/archive/archive.go +++ b/pkg/cmd/repo/archive/archive.go @@ -121,7 +121,7 @@ func archiveRun(opts *ArchiveOptions) error { return fmt.Errorf("failed to prompt: %w", err) } if !confirmed { - return cmdutil.CancelError + return cmdutil.ErrCancel } } diff --git a/pkg/cmd/repo/create/create.go b/pkg/cmd/repo/create/create.go index 8b73b3106..4f019db7a 100644 --- a/pkg/cmd/repo/create/create.go +++ b/pkg/cmd/repo/create/create.go @@ -25,7 +25,7 @@ import ( "github.com/spf13/cobra" ) -type errWithExitCode interface { +type withExitCodeError interface { ExitCode() int } @@ -65,7 +65,7 @@ type CreateOptions struct { AddReadme bool } -func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Command { +func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Command { //nolint:gocyclo opts := &CreateOptions{ IO: f.IOStreams, HttpClient: f.HttpClient, @@ -333,7 +333,7 @@ func createFromScratch(opts *CreateOptions) error { if err != nil { return err } else if !confirmed { - return cmdutil.CancelError + return cmdutil.ErrCancel } } @@ -494,7 +494,7 @@ func createFromTemplate(opts *CreateOptions) error { if err != nil { return err } else if !confirmed { - return cmdutil.CancelError + return cmdutil.ErrCancel } repo, err := repoCreate(httpClient, repoToCreate.RepoHost(), input) @@ -528,7 +528,7 @@ func createFromTemplate(opts *CreateOptions) error { } // create repo on remote host from existing local repo -func createFromLocal(opts *CreateOptions) error { +func createFromLocal(opts *CreateOptions) error { //nolint:gocyclo httpClient, err := opts.HttpClient() if err != nil { return err @@ -720,7 +720,7 @@ func cloneWithRetry(opts *CreateOptions, remoteURL, branch string) error { stderr := &bytes.Buffer{} _, err := opts.GitClient.Clone(ctx, remoteURL, args, git.WithStderr(stderr)) - var execError errWithExitCode + var execError withExitCodeError if errors.As(err, &execError) && execError.ExitCode() == 128 { return err } else { @@ -780,7 +780,7 @@ const ( func localRepoType(gitClient *git.Client) (repoType, error) { projectDir, projectDirErr := gitClient.GitDir(context.Background()) if projectDirErr != nil { - var execError errWithExitCode + var execError withExitCodeError if errors.As(projectDirErr, &execError) { if exitCode := execError.ExitCode(); exitCode == 128 { return unknown, nil diff --git a/pkg/cmd/repo/create/create_test.go b/pkg/cmd/repo/create/create_test.go index dd8937fde..43366dd45 100644 --- a/pkg/cmd/repo/create/create_test.go +++ b/pkg/cmd/repo/create/create_test.go @@ -186,7 +186,7 @@ func TestNewCmdCreate(t *testing.T) { } } -func Test_createRun(t *testing.T) { +func Test_createRun(t *testing.T) { //nolint:gocyclo tests := []struct { name string tty bool @@ -379,7 +379,7 @@ func Test_createRun(t *testing.T) { }, wantStdout: "", wantErr: true, - errMsg: "CancelError", + errMsg: "ErrCancel", }, { name: "interactive with existing repository public", diff --git a/pkg/cmd/repo/delete/delete.go b/pkg/cmd/repo/delete/delete.go index 6724191da..45ebb62b8 100644 --- a/pkg/cmd/repo/delete/delete.go +++ b/pkg/cmd/repo/delete/delete.go @@ -131,7 +131,7 @@ func deleteRun(opts *DeleteOptions) error { statusCode == http.StatusPermanentRedirect { cs := opts.IO.ColorScheme() fmt.Fprintf(opts.IO.ErrOut, "%s Failed to delete repository: %s has changed name or transferred ownership\n", cs.FailureIcon(), fullName) - return cmdutil.SilentError + return cmdutil.ErrSilent } } return err diff --git a/pkg/cmd/repo/delete/delete_test.go b/pkg/cmd/repo/delete/delete_test.go index 64a8ee301..e08b0e951 100644 --- a/pkg/cmd/repo/delete/delete_test.go +++ b/pkg/cmd/repo/delete/delete_test.go @@ -191,7 +191,7 @@ func Test_deleteRun(t *testing.T) { name: "repo transferred ownership", opts: &DeleteOptions{RepoArg: "OWNER/REPO", Confirmed: true}, wantErr: true, - errMsg: "SilentError", + errMsg: "ErrSilent", wantStderr: "X Failed to delete repository: OWNER/REPO has changed name or transferred ownership\n", httpStubs: func(reg *httpmock.Registry) { reg.Register( diff --git a/pkg/cmd/repo/edit/edit.go b/pkg/cmd/repo/edit/edit.go index f47c8f856..f72ce5d46 100644 --- a/pkg/cmd/repo/edit/edit.go +++ b/pkg/cmd/repo/edit/edit.go @@ -387,7 +387,7 @@ func interactiveChoice(p iprompter, r *api.Repository) ([]string, error) { return answers, err } -func interactiveRepoEdit(opts *EditOptions, r *api.Repository) error { +func interactiveRepoEdit(opts *EditOptions, r *api.Repository) error { //nolint:gocyclo for _, v := range r.RepositoryTopics.Nodes { opts.topicsCache = append(opts.topicsCache, v.Topic.Name) } diff --git a/pkg/cmd/repo/fork/fork.go b/pkg/cmd/repo/fork/fork.go index 76a6fad0c..e4c81b2b8 100644 --- a/pkg/cmd/repo/fork/fork.go +++ b/pkg/cmd/repo/fork/fork.go @@ -53,7 +53,7 @@ type ForkOptions struct { DefaultBranchOnly bool } -type errWithExitCode interface { +type withExitCodeError interface { ExitCode() int } @@ -146,7 +146,7 @@ func NewCmdFork(f *cmdutil.Factory, runF func(*ForkOptions) error) *cobra.Comman return cmd } -func forkRun(opts *ForkOptions) error { +func forkRun(opts *ForkOptions) error { //nolint:gocyclo var repoToFork ghrepo.Interface var err error inParent := false // whether or not we're forking the repo we're currently "in" @@ -352,7 +352,7 @@ func forkRun(opts *ForkOptions) error { if err == nil { return dir, nil } - var execError errWithExitCode + var execError withExitCodeError if errors.As(err, &execError) && execError.ExitCode() == 128 { return "", err } diff --git a/pkg/cmd/repo/garden/garden.go b/pkg/cmd/repo/garden/garden.go index 097a4a34f..cdc88639e 100644 --- a/pkg/cmd/repo/garden/garden.go +++ b/pkg/cmd/repo/garden/garden.go @@ -122,7 +122,7 @@ func NewCmdGarden(f *cmdutil.Factory, runF func(*GardenOptions) error) *cobra.Co return cmd } -func gardenRun(opts *GardenOptions) error { +func gardenRun(opts *GardenOptions) error { //nolint:gocyclo cs := opts.IO.ColorScheme() out := opts.IO.Out @@ -435,7 +435,7 @@ func drawGarden(io *iostreams.IOStreams, garden [][]*Cell, player *Player) { fmt.Fprintln(out) } - fmt.Println() + fmt.Fprintln(out) fmt.Fprintln(out, cs.Bold(sl)) } diff --git a/pkg/cmd/repo/sync/http.go b/pkg/cmd/repo/sync/http.go index 27e9a6351..93adab18a 100644 --- a/pkg/cmd/repo/sync/http.go +++ b/pkg/cmd/repo/sync/http.go @@ -30,10 +30,10 @@ func latestCommit(client *api.Client, repo ghrepo.Interface, branch string) (com return response, err } -type upstreamMergeErr struct{ error } +type upstreamMergeError struct{ error } var missingWorkflowScopeRE = regexp.MustCompile("refusing to allow.*without `workflow(s)?` (scope|permission)") -var missingWorkflowScopeErr = errors.New("Upstream commits contain workflow changes, which require the `workflow` scope or permission to merge. To request it, run: gh auth refresh -s workflow") +var errMissingWorkflowScope = errors.New("Upstream commits contain workflow changes, which require the `workflow` scope or permission to merge. To request it, run: gh auth refresh -s workflow") func triggerUpstreamMerge(client *api.Client, repo ghrepo.Interface, branch string) (string, error) { var payload bytes.Buffer @@ -55,9 +55,9 @@ func triggerUpstreamMerge(client *api.Client, repo ghrepo.Interface, branch stri switch httpErr.StatusCode { case http.StatusUnprocessableEntity, http.StatusConflict: if missingWorkflowScopeRE.MatchString(httpErr.Message) { - return "", missingWorkflowScopeErr + return "", errMissingWorkflowScope } - return "", upstreamMergeErr{errors.New(httpErr.Message)} + return "", upstreamMergeError{errors.New(httpErr.Message)} } } return "", err diff --git a/pkg/cmd/repo/sync/sync.go b/pkg/cmd/repo/sync/sync.go index b025d9eec..6f501836a 100644 --- a/pkg/cmd/repo/sync/sync.go +++ b/pkg/cmd/repo/sync/sync.go @@ -148,7 +148,7 @@ func syncLocalRepo(opts *SyncOptions) error { err = executeLocalRepoSync(srcRepo, remote, opts) opts.IO.StopProgressIndicator() if err != nil { - if errors.Is(err, divergingError) { + if errors.Is(err, errDiverging) { return fmt.Errorf("can't sync because there are diverging changes; use `--force` to overwrite the destination branch") } return err @@ -194,7 +194,7 @@ func syncRemoteRepo(opts *SyncOptions) error { baseBranchLabel, err := executeRemoteRepoSync(apiClient, destRepo, srcRepo, opts) opts.IO.StopProgressIndicator() if err != nil { - if errors.Is(err, divergingError) { + if errors.Is(err, errDiverging) { return fmt.Errorf("can't sync because there are diverging changes; use `--force` to overwrite the destination branch") } return err @@ -216,7 +216,7 @@ func syncRemoteRepo(opts *SyncOptions) error { return nil } -var divergingError = errors.New("diverging changes") +var errDiverging = errors.New("diverging changes") func executeLocalRepoSync(srcRepo ghrepo.Interface, remote string, opts *SyncOptions) error { git := opts.Git @@ -230,7 +230,7 @@ func executeLocalRepoSync(srcRepo ghrepo.Interface, remote string, opts *SyncOpt return err } if !fastForward && !useForce { - return divergingError + return errDiverging } if fastForward && useForce { useForce = false @@ -288,7 +288,7 @@ func executeRemoteRepoSync(client *api.Client, destRepo, srcRepo ghrepo.Interfac } } - var apiErr upstreamMergeErr + var apiErr upstreamMergeError if baseBranch, err := triggerUpstreamMerge(client, destRepo, branchName); err == nil { return baseBranch, nil } else if !errors.As(err, &apiErr) { @@ -320,7 +320,7 @@ func executeRemoteRepoSync(client *api.Client, destRepo, srcRepo ghrepo.Interfac if errors.As(err, &httpErr) { switch httpErr.Message { case notFastForwardErrorMessage: - return "", divergingError + return "", errDiverging case branchDoesNotExistErrorMessage: return "", fmt.Errorf("%s branch does not exist on %s repository", branchName, ghrepo.FullName(destRepo)) } diff --git a/pkg/cmd/repo/unarchive/unarchive.go b/pkg/cmd/repo/unarchive/unarchive.go index 74d84a779..0238e8d66 100644 --- a/pkg/cmd/repo/unarchive/unarchive.go +++ b/pkg/cmd/repo/unarchive/unarchive.go @@ -120,7 +120,7 @@ func unarchiveRun(opts *UnarchiveOptions) error { return err } if !confirmed { - return cmdutil.CancelError + return cmdutil.ErrCancel } } diff --git a/pkg/cmd/repo/view/http.go b/pkg/cmd/repo/view/http.go index 5988580e5..fb60f21de 100644 --- a/pkg/cmd/repo/view/http.go +++ b/pkg/cmd/repo/view/http.go @@ -14,7 +14,7 @@ import ( "golang.org/x/text/transform" ) -var NotFoundError = errors.New("not found") +var ErrNotFound = errors.New("not found") type RepoReadme struct { Filename string @@ -34,7 +34,7 @@ func RepositoryReadme(client *http.Client, repo ghrepo.Interface, branch string) if err != nil { var httpError api.HTTPError if errors.As(err, &httpError) && httpError.StatusCode == 404 { - return nil, NotFoundError + return nil, ErrNotFound } return nil, err } diff --git a/pkg/cmd/repo/view/view.go b/pkg/cmd/repo/view/view.go index b13276c80..3e73d9f8b 100644 --- a/pkg/cmd/repo/view/view.go +++ b/pkg/cmd/repo/view/view.go @@ -124,7 +124,7 @@ func viewRun(opts *ViewOptions) error { if !opts.Web && opts.Exporter == nil { readme, err = RepositoryReadme(httpClient, toView, opts.Branch) - if err != nil && !errors.Is(err, NotFoundError) { + if err != nil && !errors.Is(err, ErrNotFound) { return err } } diff --git a/pkg/cmd/run/view/view.go b/pkg/cmd/run/view/view.go index 1fb2bd5dc..ff441d025 100644 --- a/pkg/cmd/run/view/view.go +++ b/pkg/cmd/run/view/view.go @@ -200,7 +200,7 @@ func NewCmdView(f *cmdutil.Factory, runF func(*ViewOptions) error) *cobra.Comman return cmd } -func runView(opts *ViewOptions) error { +func runView(opts *ViewOptions) error { //nolint:gocyclo httpClient, err := opts.HttpClient() if err != nil { return fmt.Errorf("failed to create http client: %w", err) @@ -335,7 +335,7 @@ func runView(opts *ViewOptions) error { } if opts.ExitStatus && shared.IsFailureState(run.Conclusion) { - return cmdutil.SilentError + return cmdutil.ErrSilent } return nil } @@ -385,7 +385,7 @@ func runView(opts *ViewOptions) error { fmt.Fprintf(out, "For more information, see: %s\n", cs.Bold(run.URL)) if opts.ExitStatus { - return cmdutil.SilentError + return cmdutil.ErrSilent } return nil } @@ -431,7 +431,7 @@ func runView(opts *ViewOptions) error { fmt.Fprintln(out, cs.Mutedf("View this run on GitHub: %s", run.URL)) if opts.ExitStatus && shared.IsFailureState(run.Conclusion) { - return cmdutil.SilentError + return cmdutil.ErrSilent } } else { fmt.Fprintln(out) @@ -443,7 +443,7 @@ func runView(opts *ViewOptions) error { fmt.Fprintln(out, cs.Mutedf("View this run on GitHub: %s", run.URL)) if opts.ExitStatus && shared.IsFailureState(selectedJob.Conclusion) { - return cmdutil.SilentError + return cmdutil.ErrSilent } } diff --git a/pkg/cmd/run/watch/watch.go b/pkg/cmd/run/watch/watch.go index a73a91e1a..ed88aca8d 100644 --- a/pkg/cmd/run/watch/watch.go +++ b/pkg/cmd/run/watch/watch.go @@ -138,7 +138,7 @@ func watchRun(opts *WatchOptions) error { if run.Status == shared.Completed { fmt.Fprintf(opts.IO.Out, "Run %s (%s) has already completed with '%s'\n", cs.Bold(run.WorkflowName()), cs.Cyanf("%d", run.ID), run.Conclusion) if opts.ExitStatus && run.Conclusion != shared.Success { - return cmdutil.SilentError + return cmdutil.ErrSilent } return nil } @@ -205,7 +205,7 @@ func watchRun(opts *WatchOptions) error { } if opts.ExitStatus && run.Conclusion != shared.Success { - return cmdutil.SilentError + return cmdutil.ErrSilent } return nil diff --git a/pkg/cmd/run/watch/watch_test.go b/pkg/cmd/run/watch/watch_test.go index 1471f64cf..1e21bd877 100644 --- a/pkg/cmd/run/watch/watch_test.go +++ b/pkg/cmd/run/watch/watch_test.go @@ -243,7 +243,7 @@ func TestWatchRun(t *testing.T) { }, wantOut: "Run CI (1234) has already completed with 'failure'\n", wantErr: true, - errMsg: "SilentError", + errMsg: "ErrSilent", }, { name: "prompt, no in progress runs", @@ -306,7 +306,7 @@ func TestWatchRun(t *testing.T) { }, wantOut: "\x1b[?1049h\x1b[0;0H\x1b[JRefreshing run status every 0 seconds. Press Ctrl+C to quit.\n\n* trunk CI · 2\nTriggered via push about 59 minutes ago\n\n\x1b[?1049lX trunk CI · 2\nTriggered via push about 59 minutes ago\n\nJOBS\nX sad job in 4m34s (ID 20)\n ✓ barf the quux\n X quux the barf\n\nANNOTATIONS\nX the job is sad\nsad job: blaze.py#420\n\n\nX Run CI (2) completed with 'failure'\n", wantErr: true, - errMsg: "SilentError", + errMsg: "ErrSilent", }, { name: "failed to get run status", diff --git a/pkg/cmd/ssh-key/list/list.go b/pkg/cmd/ssh-key/list/list.go index f69e57ea3..a8570492c 100644 --- a/pkg/cmd/ssh-key/list/list.go +++ b/pkg/cmd/ssh-key/list/list.go @@ -69,7 +69,7 @@ func listRun(opts *ListOptions) error { } if authKeyErr != nil && signKeyErr != nil { - return cmdutil.SilentError + return cmdutil.ErrSilent } sshKeys := append(sshAuthKeys, sshSigningKeys...) diff --git a/pkg/cmd/workflow/list/list_test.go b/pkg/cmd/workflow/list/list_test.go index 4a2b33a3d..f6e31a537 100644 --- a/pkg/cmd/workflow/list/list_test.go +++ b/pkg/cmd/workflow/list/list_test.go @@ -167,8 +167,7 @@ func TestListRun(t *testing.T) { }, stubs: func(reg *httpmock.Registry) { workflows := []shared.Workflow{} - var flowID int64 - for flowID = 0; flowID < 103; flowID++ { + for flowID := range int64(103) { workflows = append(workflows, shared.Workflow{ ID: flowID, Name: fmt.Sprintf("flow %d", flowID), diff --git a/pkg/cmdutil/errors.go b/pkg/cmdutil/errors.go index edb97abcd..aee7fc6a2 100644 --- a/pkg/cmdutil/errors.go +++ b/pkg/cmdutil/errors.go @@ -31,17 +31,17 @@ func (fe *FlagError) Unwrap() error { return fe.err } -// SilentError is an error that triggers exit code 1 without any error messaging -var SilentError = errors.New("SilentError") +// ErrSilent is an error that triggers exit code 1 without any error messaging +var ErrSilent = errors.New("ErrSilent") -// CancelError signals user-initiated cancellation -var CancelError = errors.New("CancelError") +// ErrCancel signals user-initiated cancellation +var ErrCancel = errors.New("ErrCancel") -// PendingError signals nothing failed but something is pending -var PendingError = errors.New("PendingError") +// ErrPending signals nothing failed but something is pending +var ErrPending = errors.New("ErrPending") func IsUserCancellation(err error) bool { - return errors.Is(err, CancelError) || errors.Is(err, terminal.InterruptErr) + return errors.Is(err, ErrCancel) || errors.Is(err, terminal.InterruptErr) } func MutuallyExclusive(message string, conditions ...bool) error { diff --git a/pkg/iostreams/iostreams.go b/pkg/iostreams/iostreams.go index d0ed0e031..6064b86d3 100644 --- a/pkg/iostreams/iostreams.go +++ b/pkg/iostreams/iostreams.go @@ -22,8 +22,8 @@ import ( const DefaultWidth = 80 -// ErrClosedPagerPipe is the error returned when writing to a pager that has been closed. -type ErrClosedPagerPipe struct { +// ClosedPagerPipeError is the error returned when writing to a pager that has been closed. +type ClosedPagerPipeError struct { error } @@ -566,7 +566,7 @@ func isCygwinTerminal(fd uintptr) bool { return isatty.IsCygwinTerminal(fd) } -// pagerWriter implements a WriteCloser that wraps all EPIPE errors in an ErrClosedPagerPipe type. +// pagerWriter implements a WriteCloser that wraps all EPIPE errors in an ClosedPagerPipeError type. type pagerWriter struct { io.WriteCloser } @@ -574,7 +574,7 @@ type pagerWriter struct { func (w *pagerWriter) Write(d []byte) (int, error) { n, err := w.WriteCloser.Write(d) if err != nil && (errors.Is(err, io.ErrClosedPipe) || isEpipeError(err)) { - return n, &ErrClosedPagerPipe{err} + return n, &ClosedPagerPipeError{err} } return n, err } diff --git a/pkg/iostreams/iostreams_test.go b/pkg/iostreams/iostreams_test.go index eefc07b9c..352eed5bb 100644 --- a/pkg/iostreams/iostreams_test.go +++ b/pkg/iostreams/iostreams_test.go @@ -52,7 +52,7 @@ func TestHelperProcess(t *testing.T) { } scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { - fmt.Printf("pager: %s\n", scanner.Text()) + fmt.Printf("pager: %s\n", scanner.Text()) //nolint:forbidigo // This is a subprocess that simulates a pager, not CLI output } if err := scanner.Err(); err != nil { fmt.Fprintf(os.Stderr, "error reading stdin: %v", err) diff --git a/pkg/surveyext/editor.go b/pkg/surveyext/editor.go index 21af8a216..965ba0332 100644 --- a/pkg/surveyext/editor.go +++ b/pkg/surveyext/editor.go @@ -15,22 +15,22 @@ import ( ) var ( - bom = []byte{0xef, 0xbb, 0xbf} - defaultEditor = "nano" // EXTENDED to switch from vim as a default editor + bom = []byte{0xef, 0xbb, 0xbf} + // EXTENDED to switch from vim as a default editor + defaultEditor = func() string { + if g := os.Getenv("GIT_EDITOR"); g != "" { + return g + } else if v := os.Getenv("VISUAL"); v != "" { + return v + } else if e := os.Getenv("EDITOR"); e != "" { + return e + } else if runtime.GOOS == "windows" { + return "notepad" + } + return "nano" + }() ) -func init() { - if g := os.Getenv("GIT_EDITOR"); g != "" { - defaultEditor = g - } else if v := os.Getenv("VISUAL"); v != "" { - defaultEditor = v - } else if e := os.Getenv("EDITOR"); e != "" { - defaultEditor = e - } else if runtime.GOOS == "windows" { - defaultEditor = "notepad" - } -} - // EXTENDED to enable different prompting behavior type GhEditor struct { *survey.Editor