From 7cfbff8881229bc61447d5cb0d8da41ba11f9316 Mon Sep 17 00:00:00 2001 From: benPearce1 Date: Tue, 7 Mar 2023 16:22:03 +1000 Subject: [PATCH 1/2] added stack trace debug output --- cmd/octopus/main.go | 9 ++++- go.mod | 2 + go.sum | 4 ++ pkg/apiclient/client_factory.go | 21 +++++----- pkg/cmd/account/helper/helper.go | 5 ++- pkg/cmd/package/nuget/create/create.go | 11 +++--- pkg/cmd/package/support/pack.go | 3 +- pkg/cmd/package/upload/upload.go | 13 ++++--- pkg/cmd/project/convert/convert.go | 41 ++++++++++---------- pkg/cmd/project/create/create.go | 11 +++--- pkg/cmd/project/create/create_opts.go | 11 +++--- pkg/cmd/project/variables/create/create.go | 15 +++---- pkg/cmd/project/variables/exclude/exclude.go | 9 +++-- pkg/cmd/project/variables/include/include.go | 17 ++++---- pkg/cmd/project/variables/shared/input.go | 15 +++---- pkg/cmd/project/variables/update/update.go | 7 ++-- pkg/cmd/release/create/create.go | 41 ++++++++++---------- pkg/cmd/root/root.go | 1 + pkg/cmd/runbook/run/run.go | 23 +++++------ pkg/cmd/space/create/create.go | 31 ++++++++------- pkg/cmd/target/cloud-region/create/create.go | 9 +++-- pkg/cmd/target/list/list.go | 5 ++- pkg/cmd/target/shared/environment.go | 3 +- pkg/cmd/target/shared/role.go | 7 ++-- pkg/cmd/target/shared/view.go | 17 ++++---- pkg/cmd/target/ssh/view/view.go | 5 ++- pkg/cmd/task/wait/wait.go | 7 ++-- pkg/cmd/tenant/connect/connect.go | 23 +++++------ pkg/cmd/tenant/create/create.go | 9 +++-- pkg/cmd/tenant/disconnect/disconnect.go | 27 ++++++------- pkg/cmd/tenant/list/list.go | 19 ++++----- pkg/cmd/tenant/shared/shared.go | 15 +++---- pkg/cmd/worker/shared/view.go | 7 ++-- pkg/cmd/workerpool/static/view/view.go | 3 +- pkg/constants/constants.go | 1 + pkg/executionscommon/executionscommon.go | 31 ++++++++------- pkg/executor/release.go | 7 ++-- pkg/machinescommon/proxy.go | 5 ++- pkg/machinescommon/ssh_common.go | 19 ++++----- pkg/question/select.go | 7 ++-- pkg/question/selectors/channels.go | 5 ++- pkg/question/selectors/environments.go | 13 ++++--- pkg/question/selectors/lifecycles.go | 3 +- pkg/question/selectors/projects.go | 5 ++- pkg/question/selectors/selectors.go | 7 ++-- pkg/util/util.go | 12 +++--- 46 files changed, 308 insertions(+), 253 deletions(-) diff --git a/cmd/octopus/main.go b/cmd/octopus/main.go index 0cd8d834..67cb3228 100644 --- a/cmd/octopus/main.go +++ b/cmd/octopus/main.go @@ -5,8 +5,10 @@ import ( "fmt" "github.com/AlecAivazis/survey/v2/terminal" version "github.com/OctopusDeploy/cli" + "github.com/OctopusDeploy/cli/pkg/constants" "github.com/briandowns/spinner" "github.com/spf13/viper" + "github.com/ztrue/tracerr" "os" "strings" "time" @@ -71,8 +73,11 @@ func main() { cmd.SetErr(terminal.NewAnsiStderr(os.Stderr)) if err := cmd.Execute(); err != nil { - cmd.PrintErr(err) - cmd.Println() + if cmd.Flag(constants.FlagDebug).Value.String() == fmt.Sprintf("%v", true) { + cmd.PrintErr(tracerr.Sprint(err)) + } else { + cmd.PrintErr(err) + } if usageError, ok := err.(*usage.UsageError); ok { // if the code returns a UsageError, print the usage information diff --git a/go.mod b/go.mod index b47078c1..78cb83b6 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/spf13/pflag v1.0.5 github.com/spf13/viper v1.14.0 github.com/stretchr/testify v1.8.1 + github.com/ztrue/tracerr v0.3.0 golang.org/x/exp v0.0.0-20221217163422-3c43f8badb15 golang.org/x/term v0.3.0 ) @@ -37,6 +38,7 @@ require ( github.com/hashicorp/hcl v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/leodido/go-urn v1.2.1 // indirect + github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e // indirect github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect diff --git a/go.sum b/go.sum index 16c27a47..5125a3a1 100644 --- a/go.sum +++ b/go.sum @@ -185,6 +185,8 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e h1:9MlwzLdW7QSDrhDjFlsEYmxpFyIoXmYRon3dt0io31k= +github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4= github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY= github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= @@ -258,6 +260,8 @@ github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/ztrue/tracerr v0.3.0 h1:lDi6EgEYhPYPnKcjsYzmWw4EkFEoA/gfe+I9Y5f+h6Y= +github.com/ztrue/tracerr v0.3.0/go.mod h1:qEalzze4VN9O8tnhBXScfCrmoJo10o8TN5ciKjm6Mww= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= diff --git a/pkg/apiclient/client_factory.go b/pkg/apiclient/client_factory.go index 578a1fd3..6655a809 100644 --- a/pkg/apiclient/client_factory.go +++ b/pkg/apiclient/client_factory.go @@ -3,6 +3,7 @@ package apiclient import ( "errors" "fmt" + "github.com/ztrue/tracerr" "net/url" "strings" @@ -85,7 +86,7 @@ func NewClientFactory(httpClient *http.Client, host string, apiKey string, space hostUrl, err := url.Parse(host) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } clientImpl := &Client{ @@ -108,9 +109,9 @@ func NewClientFactoryFromConfig(ask question.AskProvider) (ClientFactory, error) apiKey := viper.GetString(constants.ConfigApiKey) spaceNameOrID := viper.GetString(constants.ConfigSpace) - errs := ValidateMandatoryEnvironment(host, apiKey) - if errs != nil { - return nil, errs + err := ValidateMandatoryEnvironment(host, apiKey) + if err != nil { + return nil, tracerr.Wrap(err) } var httpClient *http.Client @@ -167,7 +168,7 @@ func (c *Client) GetSpacedClient(requester Requester) (*octopusApiClient.Client, // We could have been given either a space name, or a space ID, so we need to use the SystemClient to go look it up. systemClient, err := c.GetSystemClient(requester) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } // if the caller has not specified a space, prompt interactively @@ -180,7 +181,7 @@ func (c *Client) GetSpacedClient(requester Requester) (*octopusApiClient.Client, allSpaces, err := systemClient.Spaces.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } switch len(allSpaces) { @@ -197,7 +198,7 @@ func (c *Client) GetSpacedClient(requester Requester) (*octopusApiClient.Client, "You have not specified a Space. Please select one:", allSpaces, func(item *spaces.Space) string { return item.GetName() }) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } c.ActiveSpace = selectedSpace c.SpaceNameOrID = selectedSpace.ID @@ -211,7 +212,7 @@ func (c *Client) GetSpacedClient(requester Requester) (*octopusApiClient.Client, // for that logic so the most pragmatic way to achieve that is to iterate the list of spaces client-side allSpaces, err := systemClient.Spaces.GetAll() if err != nil { - return nil, fmt.Errorf("cannot load spaces. Error: %v", err) + return nil, tracerr.Wrap(fmt.Errorf("cannot load spaces. Error: %v", err)) } var foundSpace *spaces.Space = nil @@ -240,7 +241,7 @@ func (c *Client) GetSpacedClient(requester Requester) (*octopusApiClient.Client, scopedClient, err := octopusApiClient.NewClientForTool(c.HttpClient, c.ApiUrl, c.ApiKey, foundSpaceID, requester.GetRequester()) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } // stash for future use c.SpaceScopedClient = scopedClient @@ -267,7 +268,7 @@ func (c *Client) GetSystemClient(requester Requester) (*octopusApiClient.Client, systemClient, err := octopusApiClient.NewClientForTool(c.HttpClient, c.ApiUrl, c.ApiKey, "", requester.GetRequester()) // deliberate empty string for space here if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } // stash for future use c.SystemClient = systemClient diff --git a/pkg/cmd/account/helper/helper.go b/pkg/cmd/account/helper/helper.go index ea253507..59d48d11 100644 --- a/pkg/cmd/account/helper/helper.go +++ b/pkg/cmd/account/helper/helper.go @@ -1,6 +1,7 @@ package helper import ( + "github.com/ztrue/tracerr" "strings" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" @@ -18,11 +19,11 @@ loop: Name: envName, }) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } allMatches, err := matches.GetAllPages(octopus.Environments.GetClient()) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, match := range allMatches { if strings.EqualFold(envName, match.Name) { diff --git a/pkg/cmd/package/nuget/create/create.go b/pkg/cmd/package/nuget/create/create.go index 599b56da..8447e37c 100644 --- a/pkg/cmd/package/nuget/create/create.go +++ b/pkg/cmd/package/nuget/create/create.go @@ -3,6 +3,7 @@ package create import ( "errors" "fmt" + "github.com/ztrue/tracerr" "os" "path/filepath" "strings" @@ -245,12 +246,12 @@ func applyDefaultsToUnspecifiedPackageOptions(opts *NuPkgCreateOptions) error { func getReleaseNotesFromFile(filePath string) (string, error) { _, err := os.Stat(filePath) if err != nil { - return "", err + return "", tracerr.Wrap(err) } notes, err := os.ReadFile(filePath) if err != nil { - return "", err + return "", tracerr.Wrap(err) } return string(notes), nil @@ -282,7 +283,7 @@ func GenerateNuSpec(opts *NuPkgCreateOptions) (string, error) { notes, err := getReleaseNotesFromFile(opts.ReleaseNotesFile.Value) releaseNotes = notes if err != nil { - return "", err + return "", tracerr.Wrap(err) } } @@ -304,12 +305,12 @@ func GenerateNuSpec(opts *NuPkgCreateOptions) (string, error) { file, err := os.Create(filePath) if err != nil { - return "", err + return "", tracerr.Wrap(err) } _, err = file.WriteString(sb.String()) if err != nil { - return "", err + return "", tracerr.Wrap(err) } return filePath, file.Close() diff --git a/pkg/cmd/package/support/pack.go b/pkg/cmd/package/support/pack.go index cd323b38..d3e97cc9 100644 --- a/pkg/cmd/package/support/pack.go +++ b/pkg/cmd/package/support/pack.go @@ -11,6 +11,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/util/flag" "github.com/bmatcuk/doublestar/v4" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" "io" "os" "path/filepath" @@ -261,7 +262,7 @@ func getDistinctPatternMatches(basePath string, patterns []string) ([]string, er for _, pattern := range patterns { paths, err := doublestar.Glob(fileSys, filepath.ToSlash(pattern)) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } filePaths = append(filePaths, paths...) } diff --git a/pkg/cmd/package/upload/upload.go b/pkg/cmd/package/upload/upload.go index 8bee3b77..13f7c246 100644 --- a/pkg/cmd/package/upload/upload.go +++ b/pkg/cmd/package/upload/upload.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "github.com/OctopusDeploy/cli/pkg/apiclient" + "github.com/ztrue/tracerr" "io" "os" "path/filepath" @@ -160,7 +161,7 @@ func uploadRun(cmd *cobra.Command, f factory.Factory, flags *UploadFlags) error } if !continueOnError { - return err + return tracerr.Wrap(err) } // else keep going to the next file. // side-effect: If there is a single failed upload, and you specify --continue-on-error, then @@ -192,15 +193,15 @@ func uploadRun(cmd *cobra.Command, f factory.Factory, flags *UploadFlags) error if err == nil && globMatches == nil { err = doUpload(pkgString) if err != nil { - return err + return tracerr.Wrap(err) } } else if err != nil { // invalid glob pattern - return err + return tracerr.Wrap(err) } else { // glob matched at least 1 thing for _, globMatch := range globMatches { err = doUpload(globMatch) if err != nil { - return err + return tracerr.Wrap(err) } } } @@ -229,12 +230,12 @@ func uploadFileAtPath(octopus newclient.Client, space *spaces.Space, path string fileReader, err := opener(path) if err != nil { - return false, err + return false, tracerr.Wrap(err) } // Note: the PackageUploadResponse has a lot of information in it, but we've chosen not to do anything // with it in the CLI at this time. _, created, err := packages.Upload(octopus, space.ID, filepath.Base(path), fileReader, overwriteMode) _ = fileReader.Close() - return created, err + return created, tracerr.Wrap(err) } diff --git a/pkg/cmd/project/convert/convert.go b/pkg/cmd/project/convert/convert.go index 97b106b0..23cc0af3 100644 --- a/pkg/cmd/project/convert/convert.go +++ b/pkg/cmd/project/convert/convert.go @@ -18,6 +18,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" "github.com/spf13/cobra" "github.com/spf13/pflag" + "github.com/ztrue/tracerr" "golang.org/x/exp/slices" "net/url" "strings" @@ -162,18 +163,18 @@ func PromptMissing(opts *ConvertOptions) error { if opts.Project.Value == "" { allProjects, err := opts.GetAllProjectsCallback() if err != nil { - return err + return tracerr.Wrap(err) } project, err := question.SelectMap(opts.Ask, "You have not specified a project. Please select one:", allProjects, func(p *projects.Project) string { return p.GetName() }) if err != nil { - return err + return tracerr.Wrap(err) } opts.Project.Value = project.GetName() } _, err := PromptForConfigAsCode(opts) if err != nil { - return err + return tracerr.Wrap(err) } return nil @@ -230,7 +231,7 @@ func PromptForConfigAsCode(opts *ConvertOptions) (cmd.Dependable, error) { selectedOption, err := selectors.SelectOptions(opts.Ask, "Select where to store the Git credentials", getGitStorageOptions) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } opts.GitStorage.Value = selectedOption.Value } @@ -238,12 +239,12 @@ func PromptForConfigAsCode(opts *ConvertOptions) (cmd.Dependable, error) { if opts.GitStorage.Value == GitStorageLibrary { err := promptLibraryGitCredentials(opts, opts.GetAllGitCredentialsCallback) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } } else { err := promptProjectGitCredentials(opts) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } } @@ -255,7 +256,7 @@ func PromptForConfigAsCode(opts *ConvertOptions) (cmd.Dependable, error) { survey.MaxLength(200), survey.Required, ))); err != nil { - return nil, err + return nil, tracerr.Wrap(err) } } @@ -267,7 +268,7 @@ func PromptForConfigAsCode(opts *ConvertOptions) (cmd.Dependable, error) { }, &opts.GitBasePath.Value, survey.WithValidator(survey.ComposeValidators( survey.MaxLength(200), ))); err != nil { - return nil, err + return nil, tracerr.Wrap(err) } } @@ -279,7 +280,7 @@ func PromptForConfigAsCode(opts *ConvertOptions) (cmd.Dependable, error) { }, &opts.GitBranch.Value, survey.WithValidator(survey.ComposeValidators( survey.MaxLength(200), ))); err != nil { - return nil, err + return nil, tracerr.Wrap(err) } } @@ -290,7 +291,7 @@ func PromptForConfigAsCode(opts *ConvertOptions) (cmd.Dependable, error) { Message: "Enter a protected branch pattern (enter blank to end)", Help: "This setting only applies within Octopus and will not affect your protected branches in Git. Use wildcard syntax to specify the range of branches to include. Multiple patterns can be supplied", }, &pattern, survey.WithValidator(survey.MaxLength(200))); err != nil { - return nil, err + return nil, tracerr.Wrap(err) } if pattern == "" { @@ -309,7 +310,7 @@ func PromptForConfigAsCode(opts *ConvertOptions) (cmd.Dependable, error) { survey.Required, survey.MaxLength(200), ))); err != nil { - return nil, err + return nil, tracerr.Wrap(err) } } @@ -321,7 +322,7 @@ func PromptForConfigAsCode(opts *ConvertOptions) (cmd.Dependable, error) { }, &opts.GitInitialCommitMessage.Value, survey.WithValidator(survey.ComposeValidators( survey.MaxLength(50), ))); err != nil { - return nil, err + return nil, tracerr.Wrap(err) } } @@ -341,7 +342,7 @@ func promptProjectGitCredentials(opts *ConvertOptions) error { survey.MaxLength(200), survey.Required, ))); err != nil { - return err + return tracerr.Wrap(err) } } @@ -353,7 +354,7 @@ func promptProjectGitCredentials(opts *ConvertOptions) error { survey.MaxLength(200), survey.Required, ))); err != nil { - return err + return tracerr.Wrap(err) } } return nil @@ -364,7 +365,7 @@ func promptLibraryGitCredentials(opts *ConvertOptions, gitCredentialsCallback Ge selectedOption, err := selectors.Select(opts.Ask, "Select which Git credentials to use", gitCredentialsCallback, func(resource *credentials.Resource) string { return resource.Name }) if err != nil { - return err + return tracerr.Wrap(err) } opts.GitCredentials.Value = selectedOption.GetName() } @@ -381,7 +382,7 @@ func getGitStorageOptions() []*selectors.SelectOption[string] { func createGetAllGitCredentialsCallback(client client.Client) ([]*credentials.Resource, error) { res, err := client.GitCredentials.Get(credentials.Query{}) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res.Items, nil } @@ -392,17 +393,17 @@ func (co *ConvertOptions) buildGitPersistenceSettings() (projects.GitPersistence if strings.EqualFold(co.GitStorage.Value, GitStorageLibrary) { credentials, err = co.buildLibraryGitVersionControlSettings() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } } else { credentials, err = co.buildProjectGitVersionControlSettings() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } } url, err := url.Parse(co.GitUrl.Value) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } vcs := projects.NewGitPersistenceSettings(co.GitBasePath.Value, credentials, co.GitBranch.Value, co.GitProtectedBranchPatterns.Value, url) @@ -412,7 +413,7 @@ func (co *ConvertOptions) buildGitPersistenceSettings() (projects.GitPersistence func (co *ConvertOptions) buildLibraryGitVersionControlSettings() (credentials.GitCredential, error) { creds, err := co.Client.GitCredentials.GetByIDOrName(co.GitCredentials.Value) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } credentials := credentials.NewReference(creds.GetID()) diff --git a/pkg/cmd/project/create/create.go b/pkg/cmd/project/create/create.go index 8755e7b5..7a09e876 100644 --- a/pkg/cmd/project/create/create.go +++ b/pkg/cmd/project/create/create.go @@ -13,6 +13,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/util/flag" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projectgroups" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" ) const ( @@ -81,7 +82,7 @@ func createRun(opts *CreateOptions) error { if !opts.NoPrompt { optsArray, err = PromptMissing(opts) if err != nil { - return err + return tracerr.Wrap(err) } } else { optsArray = append(optsArray, opts) @@ -115,14 +116,14 @@ func PromptMissing(opts *CreateOptions) ([]cmd.Dependable, error) { if opts.Lifecycle.Value == "" { lc, err := selectors.Lifecycle("You have not specified a Lifecycle for this project. Please select one:", opts.Client, opts.Ask) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } opts.Lifecycle.Value = lc.Name } value, projectGroupOpt, err := AskProjectGroups(opts.Ask, opts.Group.Value, opts.GetAllGroupsCallback, opts.CreateProjectGroupCallback) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } opts.Group.Value = value if projectGroupOpt != nil { @@ -134,7 +135,7 @@ func PromptMissing(opts *CreateOptions) ([]cmd.Dependable, error) { configAsCodeOpts, err := PromptForConfigAsCode(opts) opts.ConvertOptions.Project.Value = opts.Name.Value if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } if configAsCodeOpts != nil { nestedOpts = append(nestedOpts, configAsCodeOpts) @@ -151,7 +152,7 @@ func AskProjectGroups(ask question.Asker, value string, getAllGroupsCallback Get return pg.Name }) if err != nil { - return "", nil, err + return "", nil, tracerr.Wrap(err) } if shouldCreateNew { return createProjectGroupCallback() diff --git a/pkg/cmd/project/create/create_opts.go b/pkg/cmd/project/create/create_opts.go index ac43cf5b..9aa7ee5f 100644 --- a/pkg/cmd/project/create/create_opts.go +++ b/pkg/cmd/project/create/create_opts.go @@ -10,6 +10,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projectgroups" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" + "github.com/ztrue/tracerr" ) type CreateProjectGroupCallback func() (string, cmd.Dependable, error) @@ -42,7 +43,7 @@ func NewCreateOptions(createFlags *CreateFlags, dependencies *cmd.Dependencies) func getAllGroups(client client.Client) ([]*projectgroups.ProjectGroup, error) { res, err := client.ProjectGroups.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res, nil } @@ -67,12 +68,12 @@ func convertProjectCallback(opts *projectConvert.ConvertOptions) (cmd.Dependable func (co *CreateOptions) Commit() error { lifecycle, err := co.Client.Lifecycles.GetByIDOrName(co.Lifecycle.Value) if err != nil { - return err + return tracerr.Wrap(err) } projectGroup, err := co.Client.ProjectGroups.GetByIDOrName(co.Group.Value) if err != nil { - return err + return tracerr.Wrap(err) } project := projects.NewProject(co.Name.Value, lifecycle.GetID(), projectGroup.GetID()) @@ -80,12 +81,12 @@ func (co *CreateOptions) Commit() error { createdProject, err := co.Client.Projects.Add(project) if err != nil { - return err + return tracerr.Wrap(err) } _, err = fmt.Fprintf(co.Out, "\nSuccessfully created project '%s' (%s), with lifecycle '%s' in project group '%s'.\n", createdProject.Name, createdProject.Slug, co.Lifecycle.Value, co.Group.Value) if err != nil { - return err + return tracerr.Wrap(err) } link := output.Bluef("%s/app#/%s/projects/%s", co.Host, co.Space.GetID(), createdProject.GetID()) diff --git a/pkg/cmd/project/variables/create/create.go b/pkg/cmd/project/variables/create/create.go index e64b1899..01c3d99a 100644 --- a/pkg/cmd/project/variables/create/create.go +++ b/pkg/cmd/project/variables/create/create.go @@ -16,6 +16,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/variables" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" "strings" ) @@ -263,7 +264,7 @@ func PromptMissing(opts *CreateOptions) error { if opts.PromptType.Value == "" { selectedPromptType, err := selectors.SelectOptions(opts.Ask, "Select the control type of the prompted variable", getControlTypeOptions) if err != nil { - return err + return tracerr.Wrap(err) } opts.PromptType.Value = selectedPromptType.Value } @@ -307,28 +308,28 @@ func PromptMissing(opts *CreateOptions) error { if opts.Value.Value == "" { variableType, err := mapVariableType(opts.Type.Value) if err != nil { - return err + return tracerr.Wrap(err) } opts.Value.Value, err = sharedVariable.PromptValue(opts.Ask, variableType, opts.VariableCallbacks) if err != nil { - return err + return tracerr.Wrap(err) } } projectVariables, err := opts.GetProjectVariables(project.GetID()) if err != nil { - return err + return tracerr.Wrap(err) } scope, err := sharedVariable.ToVariableScope(projectVariables, opts.ScopeFlags, project) if err != nil { - return err + return tracerr.Wrap(err) } if scope.IsEmpty() { err = sharedVariable.PromptScopes(opts.Ask, projectVariables, opts.ScopeFlags, opts.IsPrompted.Value) if err != nil { - return err + return tracerr.Wrap(err) } } @@ -359,7 +360,7 @@ func getControlTypeOptions() []*selectors.SelectOption[string] { func projectSelector(questionText string, getAllProjectsCallback shared.GetAllProjectsCallback, ask question.Asker) (*projects.Project, error) { existingProjects, err := getAllProjectsCallback() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.SelectMap(ask, questionText, existingProjects, func(p *projects.Project) string { return p.GetName() }) diff --git a/pkg/cmd/project/variables/exclude/exclude.go b/pkg/cmd/project/variables/exclude/exclude.go index 9abe25f3..ba72760a 100644 --- a/pkg/cmd/project/variables/exclude/exclude.go +++ b/pkg/cmd/project/variables/exclude/exclude.go @@ -15,6 +15,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/variables" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" "strings" ) @@ -142,13 +143,13 @@ func PromptMissing(opts *ExcludeOptions) error { if opts.Project.Value == "" { project, err = projectSelector("You have not specified a Project. Please select one:", opts.GetAllProjectsCallback, opts.Ask) if err != nil { - return nil + return tracerr.Wrap(err) } opts.Project.Value = project.GetName() } else { project, err = opts.GetProjectCallback(opts.Project.Value) if err != nil { - return err + return tracerr.Wrap(err) } } @@ -172,7 +173,7 @@ func PromptMissing(opts *ExcludeOptions) error { }, false) if err != nil { - return err + return tracerr.Wrap(err) } if util.Empty(selectedVariableSets) { @@ -187,7 +188,7 @@ func PromptMissing(opts *ExcludeOptions) error { func projectSelector(questionText string, getAllProjectsCallback shared.GetAllProjectsCallback, ask question.Asker) (*projects.Project, error) { existingProjects, err := getAllProjectsCallback() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.SelectMap(ask, questionText, existingProjects, func(p *projects.Project) string { return p.GetName() }) diff --git a/pkg/cmd/project/variables/include/include.go b/pkg/cmd/project/variables/include/include.go index 304ef088..ac37cff0 100644 --- a/pkg/cmd/project/variables/include/include.go +++ b/pkg/cmd/project/variables/include/include.go @@ -15,6 +15,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/variables" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" "strings" ) @@ -85,18 +86,18 @@ func includeRun(opts *IncludeOptions) error { if !opts.NoPrompt { err := PromptMissing(opts) if err != nil { - return err + return tracerr.Wrap(err) } } project, err := opts.GetProjectCallback(opts.Project.Value) if err != nil { - return err + return tracerr.Wrap(err) } libraryVariableSets, err := opts.GetAllLibraryVariableSetsCallback() if err != nil { - return err + return tracerr.Wrap(err) } projectModified := false @@ -122,7 +123,7 @@ func includeRun(opts *IncludeOptions) error { if projectModified { _, err = opts.Client.Projects.Update(project) if err != nil { - return err + return tracerr.Wrap(err) } fmt.Fprintf(opts.Out, "Successfully updated included library variable sets\n") @@ -142,13 +143,13 @@ func PromptMissing(opts *IncludeOptions) error { if opts.Project.Value == "" { project, err = projectSelector("You have not specified a Project. Please select one:", opts.GetAllProjectsCallback, opts.Ask) if err != nil { - return nil + return tracerr.Wrap(err) } opts.Project.Value = project.GetName() } else { project, err = opts.GetProjectCallback(opts.Project.Value) if err != nil { - return err + return tracerr.Wrap(err) } } @@ -172,7 +173,7 @@ func PromptMissing(opts *IncludeOptions) error { }, false) if err != nil { - return err + return tracerr.Wrap(err) } if util.Empty(selectedVariableSets) { @@ -187,7 +188,7 @@ func PromptMissing(opts *IncludeOptions) error { func projectSelector(questionText string, getAllProjectsCallback shared.GetAllProjectsCallback, ask question.Asker) (*projects.Project, error) { existingProjects, err := getAllProjectsCallback() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.SelectMap(ask, questionText, existingProjects, func(p *projects.Project) string { return p.GetName() }) diff --git a/pkg/cmd/project/variables/shared/input.go b/pkg/cmd/project/variables/shared/input.go index 8712a75d..ecd7e246 100644 --- a/pkg/cmd/project/variables/shared/input.go +++ b/pkg/cmd/project/variables/shared/input.go @@ -13,6 +13,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/resources" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/variables" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/workerpools" + "github.com/ztrue/tracerr" ) type GetAccountsByTypeCallback func(accountType accounts.AccountType) ([]accounts.IAccount, error) @@ -173,7 +174,7 @@ func PromptScope(ask question.Asker, scopeDescription string, items []*resources }, &selectedItems) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return selectedItems, nil @@ -198,11 +199,11 @@ func getAccountsByType(client *client.Client, accountType accounts.AccountType) AccountType: accountType, }) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } items, err := accountResources.GetAllPages(client.Accounts.GetClient()) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return items, nil } @@ -210,7 +211,7 @@ func getAccountsByType(client *client.Client, accountType accounts.AccountType) func getAllCertificates(client *client.Client) ([]*certificates.CertificateResource, error) { certs, err := client.Certificates.Get(certificates.CertificatesQuery{}) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return certs.GetAllPages(client.Sling()) } @@ -218,7 +219,7 @@ func getAllCertificates(client *client.Client) ([]*certificates.CertificateResou func getAllWorkerPools(client *client.Client) ([]*workerpools.WorkerPoolListResult, error) { res, err := client.WorkerPools.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res, nil @@ -226,7 +227,7 @@ func getAllWorkerPools(client *client.Client) ([]*workerpools.WorkerPoolListResu func getProjectVariables(client *client.Client, id string) (*variables.VariableSet, error) { variableSet, err := client.Variables.GetAll(id) - return &variableSet, err + return &variableSet, tracerr.Wrap(err) } func getVariableById(client *client.Client, ownerId string, variableId string) (*variables.Variable, error) { @@ -236,7 +237,7 @@ func getVariableById(client *client.Client, ownerId string, variableId string) ( func GetAllLibraryVariableSets(client *client.Client) ([]*variables.LibraryVariableSet, error) { res, err := client.LibraryVariableSets.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return util.SliceFilter(res, func(item *variables.LibraryVariableSet) bool { return item.ContentType == "Variables" }), nil diff --git a/pkg/cmd/project/variables/update/update.go b/pkg/cmd/project/variables/update/update.go index 8e6c01c0..6bdf079f 100644 --- a/pkg/cmd/project/variables/update/update.go +++ b/pkg/cmd/project/variables/update/update.go @@ -17,6 +17,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/variables" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" "strings" ) @@ -168,7 +169,7 @@ func getVariable(opts *UpdateOptions, project *projects.Project, projectVariable if opts.Id.Value != "" { variable, err = opts.GetVariableById(project.GetID(), opts.Id.Value) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } if variable == nil { @@ -203,13 +204,13 @@ func PromptMissing(opts *UpdateOptions) error { } else { project, err = opts.GetProjectCallback(opts.Project.Value) if err != nil { - return err + return tracerr.Wrap(err) } } projectVariables, err := opts.GetProjectVariables(project.GetID()) if err != nil { - return err + return tracerr.Wrap(err) } var variable *variables.Variable diff --git a/pkg/cmd/release/create/create.go b/pkg/cmd/release/create/create.go index 08fc9462..e2828942 100644 --- a/pkg/cmd/release/create/create.go +++ b/pkg/cmd/release/create/create.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "github.com/OctopusDeploy/cli/pkg/apiclient" + "github.com/ztrue/tracerr" "io" "os" "regexp" @@ -231,7 +232,7 @@ func createRun(cmd *cobra.Command, f factory.Factory, flags *CreateFlags) error if f.IsPromptEnabled() { err = AskQuestions(octopus, cmd.OutOrStdout(), f.Ask, options) if err != nil { - return err + return tracerr.Wrap(err) } if !constants.IsProgrammaticOutputFormat(outputFormat) { @@ -268,7 +269,7 @@ func createRun(cmd *cobra.Command, f factory.Factory, flags *CreateFlags) error executor.NewTask(executor.TaskTypeCreateRelease, options), }) if err != nil { - return err + return tracerr.Wrap(err) } if options.Response != nil { @@ -381,14 +382,14 @@ func BuildPackageVersionBaseline(octopus *octopusApiClient.Client, deploymentPro sort.Strings(feedIds) // we need to sort them otherwise the order is indeterminate. Server doesn't care but our unit tests fail foundFeeds, err := octopus.Feeds.Get(feeds.FeedsQuery{IDs: feedIds, Take: len(feedIds)}) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } // step 3: for each package within a feed, ask the server to select the best package version for it, applying the channel rules for _, feed := range foundFeeds.Items { packageRefsInFeed, ok := feedsToQuery[feed.GetID()] if !ok { - return nil, errors.New("internal consistency error; feed ID not found in feedsToQuery") // should never happen + return nil, tracerr.Wrap(errors.New("internal consistency error; feed ID not found in feedsToQuery")) // should never happen } cache := make(map[feeds.SearchPackageVersionsQuery]string) // cache value is the package version @@ -423,7 +424,7 @@ func BuildPackageVersionBaseline(octopus *octopusApiClient.Client, deploymentPro } else { // uncached; ask the server versions, err := octopus.Feeds.SearchFeedPackageVersions(feed, query) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } switch len(versions.Items) { @@ -446,7 +447,7 @@ func BuildPackageVersionBaseline(octopus *octopusApiClient.Client, deploymentPro }) default: - return nil, errors.New("internal error; more than one package returned when only 1 specified") + return nil, tracerr.Wrap(errors.New("internal error; more than one package returned when only 1 specified")) } } } @@ -807,12 +808,12 @@ func AskQuestions(octopus *octopusApiClient.Client, stdout io.Writer, asker ques if options.ProjectName == "" { selectedProject, err = selectors.Project("Select the project in which the release will be created", octopus, asker) if err != nil { - return err + return tracerr.Wrap(err) } } else { // project name is already provided, fetch the object because it's needed for further questions selectedProject, err = selectors.FindProject(octopus, options.ProjectName) if err != nil { - return err + return tracerr.Wrap(err) } _, _ = fmt.Fprintf(stdout, "Project %s\n", output.Cyan(selectedProject.Name)) } @@ -856,25 +857,25 @@ func AskQuestions(octopus *octopusApiClient.Client, stdout io.Writer, asker ques // we've figured out how to load the dep process; go load it deploymentProcess, err := octopus.DeploymentProcesses.Get(selectedProject, gitReferenceKey) if err != nil { - return err + return tracerr.Wrap(err) } var selectedChannel *channels.Channel if options.ChannelName == "" { selectedChannel, err = selectors.Channel(octopus, asker, stdout, "Select the channel in which the release will be created", selectedProject) if err != nil { - return err + return tracerr.Wrap(err) } } else { selectedChannel, err = selectors.FindChannel(octopus, selectedProject, options.ChannelName) if err != nil { - return err + return tracerr.Wrap(err) } _, _ = fmt.Fprintf(stdout, "Channel %s\n", output.Cyan(selectedChannel.Name)) } options.ChannelName = selectedChannel.Name if err != nil { - return err + return tracerr.Wrap(err) } // immediately load the deployment process template @@ -882,12 +883,12 @@ func AskQuestions(octopus *octopusApiClient.Client, stdout io.Writer, asker ques deploymentProcessTemplate, err := octopus.DeploymentProcesses.GetTemplate(deploymentProcess, selectedChannel.ID, "") // don't stop the spinner, BuildPackageVersionBaseline does more networking if err != nil { - return err + return tracerr.Wrap(err) } packageVersionBaseline, err := BuildPackageVersionBaseline(octopus, deploymentProcessTemplate, selectedChannel) if err != nil { - return err + return tracerr.Wrap(err) } var overriddenPackageVersions []*StepPackageVersion @@ -900,7 +901,7 @@ func AskQuestions(octopus *octopusApiClient.Client, stdout io.Writer, asker ques stdout) if err != nil { - return err + return tracerr.Wrap(err) } overriddenPackageVersions = opv @@ -927,7 +928,7 @@ func AskQuestions(octopus *octopusApiClient.Client, stdout io.Writer, asker ques } else { deploymentSettings, err := octopus.Deployments.GetDeploymentSettings(selectedProject, gitReferenceKey) if err != nil { - return err + return tracerr.Wrap(err) } versioningStrategy = deploymentSettings.VersioningStrategy } @@ -952,7 +953,7 @@ func AskQuestions(octopus *octopusApiClient.Client, stdout io.Writer, asker ques versionMetadata, err := askVersionMetadata(asker, donorPackage.PackageID, donorPackage.Version) if err != nil { - return err + return tracerr.Wrap(err) } if versionMetadata == "" { options.Version = donorPackage.Version @@ -963,7 +964,7 @@ func AskQuestions(octopus *octopusApiClient.Client, stdout io.Writer, asker ques // we already loaded the deployment process template when we were looking for packages options.Version, err = askVersion(asker, deploymentProcessTemplate.NextVersionIncrement) if err != nil { - return err + return tracerr.Wrap(err) } } @@ -1152,13 +1153,13 @@ func askReleaseNotes(ask question.Asker) (string, error) { func selectGitReference(octopus *octopusApiClient.Client, ask question.Asker, project *projects.Project) (*projects.GitReference, error) { branches, err := octopus.Projects.GetGitBranches(project) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } tags, err := octopus.Projects.GetGitTags(project) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } allRefs := append(branches, tags...) diff --git a/pkg/cmd/root/root.go b/pkg/cmd/root/root.go index 6124cb15..1aa7ac8e 100644 --- a/pkg/cmd/root/root.go +++ b/pkg/cmd/root/root.go @@ -76,6 +76,7 @@ func NewCmdRoot(f factory.Factory, clientFactory apiclient.ClientFactory, askPro cmdPFlags.StringP(constants.FlagOutputFormat, "f", constants.OutputFormatTable, `Specify the output format for a command ("json", "table", or "basic")`) cmdPFlags.BoolP(constants.FlagNoPrompt, "", false, "Disable prompting in interactive mode") + cmdPFlags.Bool(constants.FlagDebug, false, "Debug output for troubleshooting") // Legacy flags brought across from the .NET CLI. // Consumers of these flags will have to explicitly check for them as well as the new diff --git a/pkg/cmd/runbook/run/run.go b/pkg/cmd/runbook/run/run.go index 538b94c9..d49bf096 100644 --- a/pkg/cmd/runbook/run/run.go +++ b/pkg/cmd/runbook/run/run.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "github.com/OctopusDeploy/cli/pkg/apiclient" + "github.com/ztrue/tracerr" "io" "math" "strings" @@ -538,7 +539,7 @@ func askRunbookTargets(octopus *octopusApiClient.Client, asker question.Asker, s for _, env := range selectedEnvironments { preview, err := runbooks.GetRunbookSnapshotRunPreview(octopus, spaceID, runbookSnapshotID, env.ID, true) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, step := range preview.StepsToExecute { for _, m := range step.MachineNames { @@ -561,7 +562,7 @@ func askRunbookTargets(octopus *octopusApiClient.Client, asker question.Asker, s Options: results, }, &selectedDeploymentTargetNames) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return selectedDeploymentTargetNames, nil @@ -573,7 +574,7 @@ func askRunbookTargets(octopus *octopusApiClient.Client, asker question.Asker, s func selectRunEnvironment(ask question.Asker, octopus *octopusApiClient.Client, space *spaces.Space, project *projects.Project, runbook *runbooks.Runbook) (*environments.Environment, error) { envs, err := runbooks.ListEnvironments(octopus, space.ID, project.ID, runbook.ID) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.SelectMap(ask, "Select an environment", envs, func(p *environments.Environment) string { @@ -585,7 +586,7 @@ func selectRunEnvironment(ask question.Asker, octopus *octopusApiClient.Client, func selectRunEnvironments(ask question.Asker, octopus *octopusApiClient.Client, space *spaces.Space, project *projects.Project, runbook *runbooks.Runbook) ([]*environments.Environment, error) { envs, err := runbooks.ListEnvironments(octopus, space.ID, project.ID, runbook.ID) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.MultiSelectMap(ask, "Select one or more environments", envs, func(p *environments.Environment) string { @@ -648,11 +649,11 @@ func PrintAdvancedSummary(stdout io.Writer, options *executor.TaskOptionsRunbook func selectRunbook(octopus *octopusApiClient.Client, ask question.Asker, questionText string, space *spaces.Space, project *projects.Project) (*runbooks.Runbook, error) { foundRunbooks, err := runbooks.List(octopus, space.ID, project.ID, "", math.MaxInt32) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } if len(foundRunbooks.Items) == 0 { - return nil, fmt.Errorf("no runbooks found for selected project: %s", project.Name) + return nil, tracerr.Wrap(fmt.Errorf("no runbooks found for selected project: %s", project.Name)) } return question.SelectMap(ask, questionText, foundRunbooks.Items, func(p *runbooks.Runbook) string { @@ -664,24 +665,24 @@ func selectRunbook(octopus *octopusApiClient.Client, ask question.Asker, questio func findRunbook(octopus *octopusApiClient.Client, spaceID string, projectID string, runbookName string) (*runbooks.Runbook, error) { result, err := runbooks.GetByName(octopus, spaceID, projectID, runbookName) if result == nil && err == nil { - return nil, fmt.Errorf("no runbook found with Name of %s", runbookName) + return nil, tracerr.Wrap(fmt.Errorf("no runbook found with Name of %s", runbookName)) } - return result, err + return result, tracerr.Wrap(err) } // findRunbookSnapshot wraps the API client, such that we are always guaranteed to get a result, or error. The "successfully can't find matching name" case doesn't exist func findRunbookSnapshot(octopus *octopusApiClient.Client, spaceID string, projectID string, snapshotIDorName string) (*runbooks.RunbookSnapshot, error) { result, err := runbooks.GetSnapshot(octopus, spaceID, projectID, snapshotIDorName) if result == nil && err == nil { - return nil, fmt.Errorf("no snapshot found with ID or Name of %s", snapshotIDorName) + return nil, tracerr.Wrap(fmt.Errorf("no snapshot found with ID or Name of %s", snapshotIDorName)) } - return result, err + return result, tracerr.Wrap(err) } // findRunbookPublishedSnapshot finds the published snapshot ID. If it cannot be found, an error is returned, you'll never get nil, nil func findRunbookPublishedSnapshot(octopus *octopusApiClient.Client, space *spaces.Space, project *projects.Project, runbook *runbooks.Runbook) (*runbooks.RunbookSnapshot, error) { if runbook.PublishedRunbookSnapshotID == "" { - return nil, fmt.Errorf("cannot run runbook %s, it has no published snapshot", runbook.Name) + return nil, tracerr.Wrap(fmt.Errorf("cannot run runbook %s, it has no published snapshot", runbook.Name)) } return findRunbookSnapshot(octopus, space.ID, project.ID, runbook.PublishedRunbookSnapshotID) } diff --git a/pkg/cmd/space/create/create.go b/pkg/cmd/space/create/create.go index ec153710..6f7e1a35 100644 --- a/pkg/cmd/space/create/create.go +++ b/pkg/cmd/space/create/create.go @@ -4,6 +4,7 @@ import ( "errors" "fmt" "github.com/OctopusDeploy/cli/pkg/apiclient" + "github.com/ztrue/tracerr" "strings" "github.com/OctopusDeploy/cli/pkg/cmd" @@ -98,25 +99,25 @@ func NewCmdCreate(f factory.Factory) *cobra.Command { func createRun(opts *CreateOptions) error { if !opts.NoPrompt { if err := PromptMissing(opts); err != nil { - return err + return tracerr.Wrap(err) } } space := spaces.NewSpace(opts.Name.Value) allTeams, err := opts.Client.Teams.GetAll() if err != nil { - return err + return tracerr.Wrap(err) } allUsers, err := opts.Client.Users.GetAll() if err != nil { - return err + return tracerr.Wrap(err) } for _, team := range opts.Teams.Value { team, err := findTeam(allTeams, team) if err != nil { - return err + return tracerr.Wrap(err) } space.SpaceManagersTeams = append(space.SpaceManagersTeams, team.ID) @@ -125,7 +126,7 @@ func createRun(opts *CreateOptions) error { for _, user := range opts.Users.Value { user, err := findUser(allUsers, user) if err != nil { - return err + return tracerr.Wrap(err) } space.SpaceManagersTeamMembers = append(space.SpaceManagersTeamMembers, user.GetID()) @@ -135,7 +136,7 @@ func createRun(opts *CreateOptions) error { createdSpace, err := opts.Client.Spaces.Add(space) if err != nil { - return err + return tracerr.Wrap(err) } fmt.Printf("%s The space, \"%s\" %s was created successfully.\n", output.Green("✔"), createdSpace.Name, output.Dimf("(%s)", createdSpace.ID)) @@ -154,7 +155,7 @@ func findTeam(allTeams []*teams.Team, identifier string) (*teams.Team, error) { } } - return nil, errors.New(fmt.Sprintf("Cannot find team '%s'", identifier)) + return nil, tracerr.Wrap(errors.New(fmt.Sprintf("Cannot find team '%s'", identifier))) } func findUser(allUsers []*users.User, identifier string) (*users.User, error) { @@ -164,13 +165,13 @@ func findUser(allUsers []*users.User, identifier string) (*users.User, error) { } } - return nil, errors.New(fmt.Sprintf("Cannot find user '%s'", identifier)) + return nil, tracerr.Wrap(errors.New(fmt.Sprintf("Cannot find user '%s'", identifier))) } func selectTeams(ask question.Asker, getAllTeamsCallback shared.GetAllTeamsCallback, existingSpaces []*spaces.Space, message string) ([]*teams.Team, error) { systemTeams, err := getAllTeamsCallback() if err != nil { - return []*teams.Team{}, err + return []*teams.Team{}, tracerr.Wrap(err) } return question.MultiSelectMap(ask, message, systemTeams, func(team *teams.Team) string { @@ -189,7 +190,7 @@ func selectTeams(ask question.Asker, getAllTeamsCallback shared.GetAllTeamsCallb func selectUsers(ask question.Asker, getAllUsersCallback shared.GetAllUsersCallback, message string) ([]*users.User, error) { existingUsers, err := getAllUsersCallback() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.MultiSelectMap(ask, message, existingUsers, func(existingUser *users.User) string { @@ -200,7 +201,7 @@ func selectUsers(ask question.Asker, getAllUsersCallback shared.GetAllUsersCallb func PromptMissing(opts *CreateOptions) error { existingSpaces, err := opts.GetAllSpacesCallback() if err != nil { - return err + return tracerr.Wrap(err) } spaceNames := util.SliceTransform(existingSpaces, func(s *spaces.Space) string { return s.Name }) @@ -215,19 +216,19 @@ func PromptMissing(opts *CreateOptions) error { validation.NotEquals(spaceNames, "a space with this name already exists"), ))) if err != nil { - return err + return tracerr.Wrap(err) } } err = question.AskDescription(opts.Ask, "", "space", &opts.Description.Value) if err != nil { - return err + return tracerr.Wrap(err) } if len(opts.Teams.Value) == 0 { selectedTeams, err := selectTeams(opts.Ask, opts.GetAllTeamsCallback, existingSpaces, "Select one or more teams to manage this space:") if err != nil { - return err + return tracerr.Wrap(err) } for _, team := range selectedTeams { @@ -238,7 +239,7 @@ func PromptMissing(opts *CreateOptions) error { if len(opts.Users.Value) == 0 { selectedUsers, err := selectUsers(opts.Ask, opts.GetAllUsersCallback, "Select one or more users to manage this space:") if err != nil { - return err + return tracerr.Wrap(err) } for _, user := range selectedUsers { diff --git a/pkg/cmd/target/cloud-region/create/create.go b/pkg/cmd/target/cloud-region/create/create.go index e358ecd0..cffb1555 100644 --- a/pkg/cmd/target/cloud-region/create/create.go +++ b/pkg/cmd/target/cloud-region/create/create.go @@ -2,6 +2,7 @@ package create import ( "fmt" + "github.com/ztrue/tracerr" "github.com/MakeNowJust/heredoc/v2" "github.com/OctopusDeploy/cli/pkg/cmd" @@ -98,7 +99,7 @@ func createRun(opts *CreateOptions) error { envs, err := executionscommon.FindEnvironments(opts.Client, opts.Environments.Value) if err != nil { - return err + return tracerr.Wrap(err) } environmentIds := util.SliceTransform(envs, func(e *environments.Environment) string { return e.ID }) @@ -106,7 +107,7 @@ func createRun(opts *CreateOptions) error { if opts.WorkerPool.Value != "" { workerPoolId, err := shared.FindWorkerPoolId(opts.GetAllWorkerPoolsCallback, opts.WorkerPool.Value) if err != nil { - return err + return tracerr.Wrap(err) } endpoint.DefaultWorkerPoolID = workerPoolId } @@ -114,12 +115,12 @@ func createRun(opts *CreateOptions) error { target := machines.NewDeploymentTarget(opts.Name.Value, endpoint, environmentIds, util.SliceDistinct(opts.Roles.Value)) err = shared.ConfigureTenant(target, opts.CreateTargetTenantFlags, opts.CreateTargetTenantOptions) if err != nil { - return err + return tracerr.Wrap(err) } createdTarget, err := opts.Client.Machines.Add(target) if err != nil { - return err + return tracerr.Wrap(err) } fmt.Fprintf(opts.Out, "Successfully created cloud region '%s'.\n", target.Name) if !opts.NoPrompt { diff --git a/pkg/cmd/target/list/list.go b/pkg/cmd/target/list/list.go index 0b324891..8d0a66ea 100644 --- a/pkg/cmd/target/list/list.go +++ b/pkg/cmd/target/list/list.go @@ -10,6 +10,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/output" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" ) type ListOptions struct { @@ -124,7 +125,7 @@ func GetEnvironmentMap(opts *ListOptions) (map[string]string, error) { environmentMap := make(map[string]string) allEnvs, err := opts.Client.Environments.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, e := range allEnvs { environmentMap[e.GetID()] = e.GetName() @@ -136,7 +137,7 @@ func GetTenantMap(opts *ListOptions) (map[string]string, error) { tenantMap := make(map[string]string) allEnvs, err := opts.Client.Tenants.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, e := range allEnvs { tenantMap[e.GetID()] = e.Name diff --git a/pkg/cmd/target/shared/environment.go b/pkg/cmd/target/shared/environment.go index 98ac24fb..83a94c46 100644 --- a/pkg/cmd/target/shared/environment.go +++ b/pkg/cmd/target/shared/environment.go @@ -7,6 +7,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/util/flag" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/environments" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" ) const ( @@ -46,7 +47,7 @@ func PromptForEnvironments(opts *CreateTargetEnvironmentOptions, flags *CreateTa envs, err := selectors.EnvironmentsMultiSelect(opts.Ask, opts.GetAllEnvironmentsCallback, "Choose at least one environment for the deployment target.\n", true) if err != nil { - return err + return tracerr.Wrap(err) } flags.Environments.Value = util.SliceTransform(envs, func(e *environments.Environment) string { return e.Name }) } diff --git a/pkg/cmd/target/shared/role.go b/pkg/cmd/target/shared/role.go index f46af898..e7f42305 100644 --- a/pkg/cmd/target/shared/role.go +++ b/pkg/cmd/target/shared/role.go @@ -7,6 +7,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/util/flag" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" ) const ( @@ -49,12 +50,12 @@ func PromptForRoles(opts *CreateTargetRoleOptions, flags *CreateTargetRoleFlags) if util.Empty(flags.Roles.Value) { availableRoles, err := opts.GetAllRolesCallback() if err != nil { - return err + return tracerr.Wrap(err) } roles, err := question.MultiSelectWithAddMap(opts.Ask, "Choose at least one role for the deployment target.\n", availableRoles, true) if err != nil { - return err + return tracerr.Wrap(err) } flags.Roles.Value = roles } @@ -64,7 +65,7 @@ func PromptForRoles(opts *CreateTargetRoleOptions, flags *CreateTargetRoleFlags) func getAllMachineRoles(client client.Client) ([]string, error) { res, err := client.MachineRoles.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } var roles []string diff --git a/pkg/cmd/target/shared/view.go b/pkg/cmd/target/shared/view.go index 3d95de80..bf4d8acd 100644 --- a/pkg/cmd/target/shared/view.go +++ b/pkg/cmd/target/shared/view.go @@ -7,6 +7,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/output" "github.com/OctopusDeploy/cli/pkg/util" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines" + "github.com/ztrue/tracerr" ) type ContributeEndpointCallback func(opts *ViewOptions, endpoint machines.IEndpoint) ([]*output.DataRow, error) @@ -38,7 +39,7 @@ func NewViewOptions(viewFlags *ViewFlags, dependencies *cmd.Dependencies, args [ func ViewRun(opts *ViewOptions, contributeEndpoint ContributeEndpointCallback, description string) error { var target, err = opts.Client.Machines.GetByIdentifier(opts.IdOrName) if err != nil { - return err + return tracerr.Wrap(err) } data := []*output.DataRow{} @@ -50,7 +51,7 @@ func ViewRun(opts *ViewOptions, contributeEndpoint ContributeEndpointCallback, d if contributeEndpoint != nil { newRows, err := contributeEndpoint(opts, target.Endpoint) if err != nil { - return err + return tracerr.Wrap(err) } for _, r := range newRows { data = append(data, r) @@ -59,7 +60,7 @@ func ViewRun(opts *ViewOptions, contributeEndpoint ContributeEndpointCallback, d environmentMap, err := GetEnvironmentMap(opts) if err != nil { - return err + return tracerr.Wrap(err) } environmentNames := resolveValues(target.EnvironmentIDs, environmentMap) @@ -69,7 +70,7 @@ func ViewRun(opts *ViewOptions, contributeEndpoint ContributeEndpointCallback, d if !util.Empty(target.TenantIDs) { tenantMap, err := GetTenantMap(opts) if err != nil { - return err + return tracerr.Wrap(err) } tenantNames := resolveValues(target.TenantIDs, tenantMap) @@ -101,7 +102,7 @@ func ContributeProxy(opts *ViewOptions, proxyID string) ([]*output.DataRow, erro if proxyID != "" { proxy, err := opts.Client.Proxies.GetById(proxyID) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return []*output.DataRow{output.NewDataRow("Proxy", proxy.GetName())}, nil } @@ -112,7 +113,7 @@ func ContributeProxy(opts *ViewOptions, proxyID string) ([]*output.DataRow, erro func ContributeAccount(opts *ViewOptions, accountID string) ([]*output.DataRow, error) { account, err := opts.Client.Accounts.GetByID(accountID) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } data := []*output.DataRow{output.NewDataRow("Account", account.GetName())} return data, nil @@ -133,7 +134,7 @@ func GetEnvironmentMap(opts *ViewOptions) (map[string]string, error) { environmentMap := make(map[string]string) allEnvs, err := opts.Client.Environments.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, e := range allEnvs { environmentMap[e.GetID()] = e.GetName() @@ -145,7 +146,7 @@ func GetTenantMap(opts *ViewOptions) (map[string]string, error) { tenantMap := make(map[string]string) allEnvs, err := opts.Client.Tenants.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, e := range allEnvs { tenantMap[e.GetID()] = e.Name diff --git a/pkg/cmd/target/ssh/view/view.go b/pkg/cmd/target/ssh/view/view.go index 6c25ff32..5457f8bc 100644 --- a/pkg/cmd/target/ssh/view/view.go +++ b/pkg/cmd/target/ssh/view/view.go @@ -11,6 +11,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/usage" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" ) func NewCmdView(f factory.Factory) *cobra.Command { @@ -47,14 +48,14 @@ func contributeEndpoint(opts *shared.ViewOptions, targetEndpoint machines.IEndpo data = append(data, output.NewDataRow("Runtime architecture", getRuntimeArchitecture(endpoint))) accountRows, err := shared.ContributeAccount(opts, endpoint.AccountID) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } data = append(data, accountRows...) proxy, err := shared.ContributeProxy(opts, endpoint.ProxyID) data = append(data, proxy...) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return data, nil diff --git a/pkg/cmd/task/wait/wait.go b/pkg/cmd/task/wait/wait.go index c3dbd34a..e9268bd7 100644 --- a/pkg/cmd/task/wait/wait.go +++ b/pkg/cmd/task/wait/wait.go @@ -2,6 +2,7 @@ package wait import ( "fmt" + "github.com/ztrue/tracerr" "io" "time" @@ -68,7 +69,7 @@ func WaitRun(out io.Writer, taskIDs []string, getServerTasksCallback ServerTasks } tasks, err := getServerTasksCallback(taskIDs) if err != nil { - return err + return tracerr.Wrap(err) } if len(tasks) == 0 { @@ -126,12 +127,12 @@ func GetServerTasksCallback(octopus *client.Client) ServerTasksCallback { resourceTasks, err := octopus.Tasks.Get(query) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } tasks, err := resourceTasks.GetAllPages(octopus.Sling()) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return tasks, nil diff --git a/pkg/cmd/tenant/connect/connect.go b/pkg/cmd/tenant/connect/connect.go index ad9f325d..a5503f02 100644 --- a/pkg/cmd/tenant/connect/connect.go +++ b/pkg/cmd/tenant/connect/connect.go @@ -3,6 +3,7 @@ package connect import ( "errors" "fmt" + "github.com/ztrue/tracerr" "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc/v2" @@ -65,7 +66,7 @@ func NewConnectOptions(connectFlags *ConnectFlags, dependencies *cmd.Dependencie func getProjectProgression(client client.Client, project *projects.Project) (*projects.Progression, error) { res, err := client.Projects.GetProgression(project) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res, nil @@ -119,12 +120,12 @@ func ConnectRun(opts *ConnectOptions) error { tenant, err := opts.Client.Tenants.GetByIdentifier(opts.Tenant.Value) if err != nil { - return err + return tracerr.Wrap(err) } project, err := opts.Client.Projects.GetByIdentifier(opts.Project.Value) if err != nil { - return err + return tracerr.Wrap(err) } if !supportsTenantedDeployments(project) { @@ -137,7 +138,7 @@ func ConnectRun(opts *ConnectOptions) error { environments, err := executionscommon.FindEnvironments(opts.Client, opts.Environments.Value) if err != nil { - return err + return tracerr.Wrap(err) } var environmentIds []string @@ -148,7 +149,7 @@ func ConnectRun(opts *ConnectOptions) error { tenant.ProjectEnvironments[project.GetID()] = environmentIds tenant, err = opts.Client.Tenants.Update(tenant) if err != nil { - return err + return tracerr.Wrap(err) } fmt.Fprintf(opts.Out, "Successfully connected '%s' to '%s'.\n", tenant.Name, project.GetName()) @@ -165,7 +166,7 @@ func PromptMissing(opts *ConnectOptions) error { return tenant.Name }) if err != nil { - return err + return tracerr.Wrap(err) } opts.Tenant.Value = tenant.Name @@ -174,20 +175,20 @@ func PromptMissing(opts *ConnectOptions) error { if opts.Project.Value == "" { project, err := projectSelector("You have not specified a Project. Please select one:", opts.GetAllProjectsCallback, opts.Ask) if err != nil { - return err + return tracerr.Wrap(err) } opts.Project.Value = project.GetName() } err := PromptForEnablingTenantedDeployments(opts, opts.GetProjectCallback) if err != nil { - return err + return tracerr.Wrap(err) } if opts.Environments.Value == nil || len(opts.Environments.Value) == 0 { project, err := opts.GetProjectCallback(opts.Project.Value) if err != nil { - return err + return tracerr.Wrap(err) } var progression *projects.Progression progression, err = opts.GetProjectProgressionCallback(project) @@ -209,7 +210,7 @@ func PromptForEnablingTenantedDeployments(opts *ConnectOptions, getProjectCallba if !opts.EnableTenantDeployments.Value { project, err := getProjectCallback(opts.Project.Value) if err != nil { - return err + return tracerr.Wrap(err) } if !supportsTenantedDeployments(project) { opts.Ask(&survey.Confirm{ @@ -233,7 +234,7 @@ func getFailureMessageForUntenantedProject(project *projects.Project) string { func projectSelector(questionText string, getAllProjectsCallback shared.GetAllProjectsCallback, ask question.Asker) (*projects.Project, error) { existingProjects, err := getAllProjectsCallback() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.SelectMap(ask, questionText, existingProjects, getProjectDisplay()) diff --git a/pkg/cmd/tenant/create/create.go b/pkg/cmd/tenant/create/create.go index 5d17500a..644fa7f3 100644 --- a/pkg/cmd/tenant/create/create.go +++ b/pkg/cmd/tenant/create/create.go @@ -2,6 +2,7 @@ package create import ( "fmt" + "github.com/ztrue/tracerr" "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc/v2" @@ -63,7 +64,7 @@ func createRun(opts *CreateOptions) error { if !opts.NoPrompt { optsArray, err = PromptMissing(opts) if err != nil { - return err + return tracerr.Wrap(err) } } else { optsArray = append(optsArray, opts) @@ -93,7 +94,7 @@ func PromptMissing(opts *CreateOptions) ([]cmd.Dependable, error) { tags, err := AskTags(opts.Ask, opts.Tag.Value, opts.GetAllTagsCallback) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } opts.Tag.Value = tags @@ -107,7 +108,7 @@ func AskTags(ask question.Asker, value []string, getAllTagSetsCallback GetAllTag } tagSets, err := getAllTagSetsCallback() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } canonicalTagName := []string{} @@ -122,7 +123,7 @@ func AskTags(ask question.Asker, value []string, getAllTagSetsCallback GetAllTag Message: "Tags", }, &tags) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return tags, nil } diff --git a/pkg/cmd/tenant/disconnect/disconnect.go b/pkg/cmd/tenant/disconnect/disconnect.go index 4cc292d1..0b310359 100644 --- a/pkg/cmd/tenant/disconnect/disconnect.go +++ b/pkg/cmd/tenant/disconnect/disconnect.go @@ -3,6 +3,7 @@ package disconnect import ( "errors" "fmt" + "github.com/ztrue/tracerr" "sort" "strings" @@ -104,12 +105,12 @@ func DisconnectRun(opts *DisconnectOptions) error { tenant, err := opts.GetTenantCallback(opts.Tenant.Value) if err != nil { - return err + return tracerr.Wrap(err) } project, err := opts.GetProjectCallback(opts.Project.Value) if err != nil { - return err + return tracerr.Wrap(err) } if len(tenant.ProjectEnvironments) == 0 { @@ -123,7 +124,7 @@ func DisconnectRun(opts *DisconnectOptions) error { delete(tenant.ProjectEnvironments, project.GetID()) tenant, err = opts.Client.Tenants.Update(tenant) if err != nil { - return err + return tracerr.Wrap(err) } fmt.Fprintf(opts.Out, "Successfully disconnected '%s' from '%s'.\n", tenant.Name, project.GetName()) @@ -142,7 +143,7 @@ func PromptMissing(opts *DisconnectOptions) error { return tenant.Name }) if err != nil { - return err + return tracerr.Wrap(err) } opts.Tenant.Value = tenant.Name @@ -150,13 +151,13 @@ func PromptMissing(opts *DisconnectOptions) error { } else { selectedTenant, err = opts.GetTenantCallback(opts.Tenant.Value) if err != nil { - return err + return tracerr.Wrap(err) } } selectedProject, err := PromptForProject(opts, selectedTenant) if err != nil { - return err + return tracerr.Wrap(err) } if !opts.Confirm.Value { @@ -175,7 +176,7 @@ func PromptForProject(opts *DisconnectOptions, selectedTenant *tenants.Tenant) ( if opts.Project.Value == "" { switch len(selectedTenant.ProjectEnvironments) { case 0: - return nil, errors.New("Not currently connected to any projects") + return nil, tracerr.Wrap(errors.New("Not currently connected to any projects")) case 1: var projectId string for i := range selectedTenant.ProjectEnvironments { @@ -184,16 +185,16 @@ func PromptForProject(opts *DisconnectOptions, selectedTenant *tenants.Tenant) ( selectedProject, err = opts.GetProjectCallback(projectId) opts.Project.Value = selectedProject.GetName() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } default: currentlyConnectedProjects, err := getCurrentlyConnectedProjects(selectedTenant, opts.GetProjectCallback) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } project, err := projectSelector("You have not specified a Project. Please select one:", func() ([]*projects.Project, error) { return currentlyConnectedProjects, nil }, opts.Ask) if err != nil { - return nil, nil + return nil, tracerr.Wrap(err) } opts.Project.Value = project.GetName() selectedProject = project @@ -202,7 +203,7 @@ func PromptForProject(opts *DisconnectOptions, selectedTenant *tenants.Tenant) ( } else { selectedProject, err = opts.GetProjectCallback(opts.Project.Value) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } } return selectedProject, nil @@ -213,7 +214,7 @@ func getCurrentlyConnectedProjects(tenant *tenants.Tenant, getProjectCallback sh for projectId := range tenant.ProjectEnvironments { project, err := getProjectCallback(projectId) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } projects = append(projects, project) } @@ -227,7 +228,7 @@ func getCurrentlyConnectedProjects(tenant *tenants.Tenant, getProjectCallback sh func projectSelector(questionText string, getAllProjectsCallback shared.GetAllProjectsCallback, ask question.Asker) (*projects.Project, error) { existingProjects, err := getAllProjectsCallback() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.SelectMap(ask, questionText, existingProjects, func(p *projects.Project) string { return p.GetName() }) diff --git a/pkg/cmd/tenant/list/list.go b/pkg/cmd/tenant/list/list.go index b5e0cbc1..42db8456 100644 --- a/pkg/cmd/tenant/list/list.go +++ b/pkg/cmd/tenant/list/list.go @@ -12,6 +12,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/tenants" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" ) type ProjectEnvironment struct { @@ -45,22 +46,22 @@ func NewCmdList(f factory.Factory) *cobra.Command { func listRun(cmd *cobra.Command, f factory.Factory) error { client, err := f.GetSpacedClient(apiclient.NewRequester(cmd)) if err != nil { - return err + return tracerr.Wrap(err) } allTenants, err := client.Tenants.GetAll() if err != nil { - return err + return tracerr.Wrap(err) } environmentMap, err := getEnvironmentMap(client, allTenants) if err != nil { - return err + return tracerr.Wrap(err) } projectMap, err := getProjectMap(client, allTenants) if err != nil { - return err + return tracerr.Wrap(err) } return output.PrintArray(allTenants, cmd, output.Mappers[*tenants.Tenant]{ @@ -72,7 +73,7 @@ func listRun(cmd *cobra.Command, f factory.Factory) error { projectEntity := output.IdAndName{Id: p, Name: projectMap[p]} environments, err := resolveEntities(t.ProjectEnvironments[p], environmentMap) if err != nil { - return err + return tracerr.Wrap(err) } projectEnvironments = append(projectEnvironments, ProjectEnvironment{Project: projectEntity, Environments: environments}) } @@ -117,15 +118,15 @@ func getEnvironmentMap(client *client.Client, tenants []*tenants.Tenant) (map[st environmentMap := make(map[string]string) queryResult, err := client.Environments.Get(environments.EnvironmentsQuery{IDs: environmentIds}) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } allEnvs, err := queryResult.GetAllPages(client.Environments.GetClient()) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, e := range allEnvs { environmentMap[e.GetID()] = e.GetName() @@ -146,7 +147,7 @@ func getProjectMap(client *client.Client, tenants []*tenants.Tenant) (map[string queryResult, err := client.Projects.Get(projects.ProjectsQuery{IDs: projectIds}) allProjects, err := queryResult.GetAllPages(client.Projects.GetClient()) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, e := range allProjects { projectMap[e.GetID()] = e.GetName() diff --git a/pkg/cmd/tenant/shared/shared.go b/pkg/cmd/tenant/shared/shared.go index 8cc8661b..1e0f8120 100644 --- a/pkg/cmd/tenant/shared/shared.go +++ b/pkg/cmd/tenant/shared/shared.go @@ -7,6 +7,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/teams" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/tenants" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/users" + "github.com/ztrue/tracerr" ) type GetAllSpacesCallback func() ([]*spaces.Space, error) @@ -21,7 +22,7 @@ type GetProjectProgression func(project *projects.Project) (*projects.Progressio func GetAllTeams(client client.Client) ([]*teams.Team, error) { res, err := client.Teams.Get(teams.TeamsQuery{IncludeSystem: true}) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res.Items, nil } @@ -29,7 +30,7 @@ func GetAllTeams(client client.Client) ([]*teams.Team, error) { func GetAllUsers(client client.Client) ([]*users.User, error) { res, err := client.Users.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res, nil @@ -38,7 +39,7 @@ func GetAllUsers(client client.Client) ([]*users.User, error) { func GetAllSpaces(client client.Client) ([]*spaces.Space, error) { res, err := client.Spaces.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res, nil @@ -47,7 +48,7 @@ func GetAllSpaces(client client.Client) ([]*spaces.Space, error) { func GetAllTenants(client *client.Client) ([]*tenants.Tenant, error) { res, err := client.Tenants.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res, nil @@ -56,7 +57,7 @@ func GetAllTenants(client *client.Client) ([]*tenants.Tenant, error) { func GetTenant(client *client.Client, identifier string) (*tenants.Tenant, error) { res, err := client.Tenants.GetByIdentifier(identifier) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res, nil @@ -65,7 +66,7 @@ func GetTenant(client *client.Client, identifier string) (*tenants.Tenant, error func GetAllProjects(client *client.Client) ([]*projects.Project, error) { res, err := client.Projects.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res, nil @@ -74,7 +75,7 @@ func GetAllProjects(client *client.Client) ([]*projects.Project, error) { func GetProject(client *client.Client, identifier string) (*projects.Project, error) { res, err := client.Projects.GetByIdentifier(identifier) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res, nil diff --git a/pkg/cmd/worker/shared/view.go b/pkg/cmd/worker/shared/view.go index 5364e14e..2a553e14 100644 --- a/pkg/cmd/worker/shared/view.go +++ b/pkg/cmd/worker/shared/view.go @@ -6,6 +6,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/machinescommon" "github.com/OctopusDeploy/cli/pkg/output" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines" + "github.com/ztrue/tracerr" ) type ContributeEndpointCallback func(opts *ViewOptions, endpoint machines.IEndpoint) ([]*output.DataRow, error) @@ -73,7 +74,7 @@ func ContributeProxy(opts *ViewOptions, proxyID string) ([]*output.DataRow, erro if proxyID != "" { proxy, err := opts.Client.Proxies.GetById(proxyID) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return []*output.DataRow{output.NewDataRow("Proxy", proxy.GetName())}, nil } @@ -84,7 +85,7 @@ func ContributeProxy(opts *ViewOptions, proxyID string) ([]*output.DataRow, erro func ContributeAccount(opts *ViewOptions, accountID string) ([]*output.DataRow, error) { account, err := opts.Client.Accounts.GetByID(accountID) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } data := []*output.DataRow{output.NewDataRow("Account", account.GetName())} return data, nil @@ -106,7 +107,7 @@ func GetWorkerPoolMap(opts *ViewOptions) (map[string]string, error) { allEnvs, err := opts.Client.WorkerPools.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, e := range allEnvs { workerPoolMap[e.ID] = e.Name diff --git a/pkg/cmd/workerpool/static/view/view.go b/pkg/cmd/workerpool/static/view/view.go index c84733a2..b8eb1f7a 100644 --- a/pkg/cmd/workerpool/static/view/view.go +++ b/pkg/cmd/workerpool/static/view/view.go @@ -14,6 +14,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/machines" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/workerpools" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" ) func NewCmdView(f factory.Factory) *cobra.Command { @@ -44,7 +45,7 @@ func ViewRun(opts *shared.ViewOptions) error { func contributeDetails(opts *shared.ViewOptions, workerPool workerpools.IWorkerPool) ([]*output.DataRow, error) { workers, err := opts.Client.WorkerPools.GetWorkers(workerPool) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } data := []*output.DataRow{} diff --git a/pkg/constants/constants.go b/pkg/constants/constants.go index 2ee08013..55d8f9a8 100644 --- a/pkg/constants/constants.go +++ b/pkg/constants/constants.go @@ -11,6 +11,7 @@ const ( FlagOutputFormat = "output-format" FlagOutputFormatLegacy = "outputFormat" FlagNoPrompt = "no-prompt" + FlagDebug = "debug" ) // flags for storing things in the go context diff --git a/pkg/executionscommon/executionscommon.go b/pkg/executionscommon/executionscommon.go index 6952c845..7a17197c 100644 --- a/pkg/executionscommon/executionscommon.go +++ b/pkg/executionscommon/executionscommon.go @@ -15,6 +15,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/environments" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/tenants" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/variables" + "github.com/ztrue/tracerr" "sort" "strconv" "strings" @@ -27,7 +28,7 @@ func findTenantsAndTags(octopus *octopusApiClient.Client, projectID string, envi page, err := octopus.Tenants.Get(tenants.TenantsQuery{ProjectID: projectID}) if err != nil { - return nil, nil, err + return nil, nil, tracerr.Wrap(err) } for page != nil { tenantsForMyEnvironments := make([]*tenants.Tenant, 0) @@ -51,7 +52,7 @@ func findTenantsAndTags(octopus *octopusApiClient.Client, projectID string, envi page, err = page.GetNextPage(octopus.Tenants.GetClient()) if err != nil { - return nil, nil, err + return nil, nil, tracerr.Wrap(err) } } @@ -66,7 +67,7 @@ func AskTenantsAndTags(asker question.Asker, octopus *octopusApiClient.Client, p }) foundTenants, foundTags, err := findTenantsAndTags(octopus, projectID, envIDs) if err != nil { - return nil, nil, err + return nil, nil, tracerr.Wrap(err) } // sort because otherwise they may appear in weird order @@ -84,7 +85,7 @@ func AskTenantsAndTags(asker question.Asker, octopus *octopusApiClient.Client, p Options: combinedList, }, &selection, survey.WithValidator(survey.Required)) if err != nil { - return nil, nil, err + return nil, nil, tracerr.Wrap(err) } } else { err = asker(&survey.MultiSelect{ @@ -92,7 +93,7 @@ func AskTenantsAndTags(asker question.Asker, octopus *octopusApiClient.Client, p Options: combinedList, }, &selection) if err != nil { - return nil, nil, err + return nil, nil, tracerr.Wrap(err) } } @@ -124,7 +125,7 @@ func AskExcludedSteps(asker question.Asker, steps []*deployments.DeploymentStep) return s.Name }, false) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return util.SliceTransform(stepsToExclude, func(s *deployments.DeploymentStep) string { return s.Name // server expects us to send a list of step names @@ -135,7 +136,7 @@ func AskPackageDownload(asker question.Asker) (bool, error) { result, err := question.SelectMap(asker, "Package download", []bool{true, false}, LookupPackageDownloadString) // our question is phrased such that "Use cached packages" (the do-nothing option) is true, // but we want to set the --force-package-download flag, so we need to invert the response - return !result, err + return !result, tracerr.Wrap(err) } func AskGuidedFailureMode(asker question.Asker) (string, error) { @@ -188,7 +189,7 @@ func AskVariables(asker question.Asker, variableSet *variables.VariableSet, vari if v.Type == "String" || v.Type == "Sensitive" { responseString, err := askVariableSpecificPrompt(asker, promptMessage, v.Type, v.Value, v.Prompt.IsRequired, v.IsSensitive, v.Prompt.DisplaySettings) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } result[v.Name] = responseString } @@ -233,14 +234,14 @@ func askVariableSpecificPrompt(asker question.Asker, message string, variableTyp Message: message, Default: defaultValue, }, &response, askOpt) - return response, err + return response, tracerr.Wrap(err) case variables.ControlTypeSensitive: var response string err := asker(&survey.Password{ Message: message, }, &response, askOpt) - return response, err + return response, tracerr.Wrap(err) case variables.ControlTypeMultiLineText: // not clear if the server ever does this var response string @@ -250,7 +251,7 @@ func askVariableSpecificPrompt(asker question.Asker, message string, variableTyp FileName: "*.txt", }, Optional: !isRequired}, &response) - return response, err + return response, tracerr.Wrap(err) case variables.ControlTypeSelect: if displaySettings == nil { @@ -273,7 +274,7 @@ func askVariableSpecificPrompt(asker question.Asker, message string, variableTyp Options: optionStrings, }, &response, askOpt) if err != nil { - return "", err + return "", tracerr.Wrap(err) } return reverseLookup[response], nil @@ -289,7 +290,7 @@ func askVariableSpecificPrompt(asker question.Asker, message string, variableTyp Default: defTrueFalse, Options: []string{"True", "False"}, // Yes/No would read more nicely, but doesn't fit well with cmdline which expects True/False }, &response, askOpt) - return response, err + return response, tracerr.Wrap(err) default: return "", fmt.Errorf("unhandled control type %s", displaySettings.ControlType) @@ -403,7 +404,7 @@ func FindEnvironments(client *octopusApiClient.Client, environmentNamesOrIds []s // it's probably going to be cheaper to just list out all the environments and match them client side, so we'll do that for simplicity's sake allEnvs, err := client.Environments.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } nameLookup := make(map[string]*environments.Environment, len(allEnvs)) @@ -425,7 +426,7 @@ func FindEnvironments(client *octopusApiClient.Client, environmentNamesOrIds []s if env != nil { result = append(result, env) } else { - return nil, fmt.Errorf("cannot find environment %s", nameOrId) + return nil, tracerr.Wrap(fmt.Errorf("cannot find environment %s", nameOrId)) } } } diff --git a/pkg/executor/release.go b/pkg/executor/release.go index 6564d3bb..5c83bd70 100644 --- a/pkg/executor/release.go +++ b/pkg/executor/release.go @@ -7,6 +7,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/deployments" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/releases" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/spaces" + "github.com/ztrue/tracerr" "strconv" "strings" ) @@ -71,7 +72,7 @@ func releaseCreate(octopus *client.Client, space *spaces.Space, input any) error createReleaseResponse, err := releases.CreateReleaseV1(octopus, createReleaseParams) if err != nil { - return err + return tracerr.Wrap(err) } params.Response = createReleaseResponse @@ -178,7 +179,7 @@ func releaseDeploy(octopus *client.Client, space *spaces.Space, input any) error createDeploymentResponse, err := deployments.CreateDeploymentTenantedV1(octopus, tenantedCommand) if err != nil { - return err + return tracerr.Wrap(err) } params.Response = createDeploymentResponse } else { @@ -191,7 +192,7 @@ func releaseDeploy(octopus *client.Client, space *spaces.Space, input any) error createDeploymentResponse, err := deployments.CreateDeploymentUntenantedV1(octopus, untenantedCommand) if err != nil { - return err + return tracerr.Wrap(err) } params.Response = createDeploymentResponse } diff --git a/pkg/machinescommon/proxy.go b/pkg/machinescommon/proxy.go index 9442be7f..11b73375 100644 --- a/pkg/machinescommon/proxy.go +++ b/pkg/machinescommon/proxy.go @@ -9,6 +9,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/proxies" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" "strings" ) @@ -65,7 +66,7 @@ func RegisterCreateTargetProxyFlags(cmd *cobra.Command, proxyFlags *CreateTarget func FindProxy(opts *CreateTargetProxyOptions, flags *CreateTargetProxyFlags) (*proxies.Proxy, error) { allProxy, err := opts.Client.Proxies.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } var proxy *proxies.Proxy for _, p := range allProxy { @@ -83,7 +84,7 @@ func FindProxy(opts *CreateTargetProxyOptions, flags *CreateTargetProxyFlags) (* func getAllProxies(client client.Client) ([]*proxies.Proxy, error) { res, err := client.Proxies.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return res, nil diff --git a/pkg/machinescommon/ssh_common.go b/pkg/machinescommon/ssh_common.go index ae2a859d..92be7df1 100644 --- a/pkg/machinescommon/ssh_common.go +++ b/pkg/machinescommon/ssh_common.go @@ -9,6 +9,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/accounts" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" "github.com/spf13/cobra" + "github.com/ztrue/tracerr" "strconv" "strings" ) @@ -84,7 +85,7 @@ func PromptForSshEndpoint(opts *SshCommonOptions, flags *SshCommonFlags, entityT Message: "Host", Help: fmt.Sprintf("The hostname or IP address at which the %s can be reached.", entityType), }, &flags.HostName.Value, survey.WithValidator(survey.Required)); err != nil { - return err + return tracerr.Wrap(err) } } @@ -95,7 +96,7 @@ func PromptForSshEndpoint(opts *SshCommonOptions, flags *SshCommonFlags, entityT Help: fmt.Sprintf("Port number to connect over SSH to the %s. Default is %d", entityType, DefaultPort), Default: fmt.Sprintf("%d", DefaultPort), }, &port); err != nil { - return err + return tracerr.Wrap(err) } if port == "" { @@ -105,7 +106,7 @@ func PromptForSshEndpoint(opts *SshCommonOptions, flags *SshCommonFlags, entityT if p, err := strconv.Atoi(port); err == nil { flags.Port.Value = p } else { - return err + return tracerr.Wrap(err) } } @@ -125,7 +126,7 @@ func PromptForDotNetConfig(opts *SshCommonOptions, flags *SshCommonFlags, entity if flags.Runtime.Value == "" { selectedRuntime, err := selectors.SelectOptions(opts.Ask, fmt.Sprintf("Select the %s runtime\n", entityType), getTargetRuntimeOptions) if err != nil { - return err + return tracerr.Wrap(err) } flags.Runtime.Value = selectedRuntime.Value } @@ -134,7 +135,7 @@ func PromptForDotNetConfig(opts *SshCommonOptions, flags *SshCommonFlags, entity if flags.Platform.Value == "" { selectedPlatform, err := selectors.SelectOptions(opts.Ask, fmt.Sprintf("Select the %s platform\n", entityType), getTargetPlatformOptions) if err != nil { - return err + return tracerr.Wrap(err) } flags.Platform.Value = selectedPlatform.Value } @@ -154,13 +155,13 @@ func PromptForSshAccount(opts *SshCommonOptions, flags *SshCommonFlags) error { return a.GetName() }) if err != nil { - return err + return tracerr.Wrap(err) } account = selectedAccount } else { a, err := GetSshAccount(opts, flags) if err != nil { - return err + return tracerr.Wrap(err) } account = a } @@ -188,7 +189,7 @@ func getTargetPlatformOptions() []*selectors.SelectOption[string] { func getAllAccountsForSshMachine(client *client.Client) ([]accounts.IAccount, error) { allAccounts, err := client.Accounts.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } var accounts []accounts.IAccount @@ -210,7 +211,7 @@ func GetSshAccount(opts *SshCommonOptions, flags *SshCommonFlags) (accounts.IAcc idOrName := flags.Account.Value allAccounts, err := opts.GetAllAccountsForSshMachine() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, a := range allAccounts { diff --git a/pkg/question/select.go b/pkg/question/select.go index 2da0de78..546d9e25 100644 --- a/pkg/question/select.go +++ b/pkg/question/select.go @@ -3,6 +3,7 @@ package question import ( "fmt" "github.com/OctopusDeploy/cli/pkg/util" + "github.com/ztrue/tracerr" "github.com/AlecAivazis/survey/v2" "github.com/OctopusDeploy/cli/pkg/constants" @@ -22,7 +23,7 @@ func MultiSelectMap[T any](ask Asker, message string, items []T, getKey func(ite var selectedKeys []string if err := ask(&survey.MultiSelect{Message: message, Options: options}, &selectedKeys, askOpts); err != nil { - return nil, err + return nil, tracerr.Wrap(err) } selected := make([]T, 0) for _, keyName := range selectedKeys { @@ -40,7 +41,7 @@ func MultiSelectWithAddMap(ask Asker, message string, items []string, required b var selectedKeys []string if err := ask(&surveyext.MultiSelectWithAdd{Message: message, Options: items}, &selectedKeys, askOpts); err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return selectedKeys, nil } @@ -56,7 +57,7 @@ func SelectMap[T any](ask Asker, message string, items []T, getKey func(item T) Message: message, Options: options, }, &selectedKey); err != nil { - return selectedValue, err + return selectedValue, tracerr.Wrap(err) } selectedValue, ok := optionMap[selectedKey] if !ok { // without this explict check SelectMap can return nil, nil which people don't expect diff --git a/pkg/question/selectors/channels.go b/pkg/question/selectors/channels.go index 7a5452b6..54676972 100644 --- a/pkg/question/selectors/channels.go +++ b/pkg/question/selectors/channels.go @@ -7,6 +7,7 @@ import ( "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/channels" octopusApiClient "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" + "github.com/ztrue/tracerr" "io" "strings" ) @@ -18,7 +19,7 @@ func Channel(octopus *octopusApiClient.Client, ask question.Asker, io io.Writer, return existingChannels[0], nil } if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.SelectMap(ask, questionText, existingChannels, func(p *channels.Channel) string { @@ -29,7 +30,7 @@ func Channel(octopus *octopusApiClient.Client, ask question.Asker, io io.Writer, func FindChannel(octopus *octopusApiClient.Client, project *projects.Project, channelName string) (*channels.Channel, error) { foundChannels, err := octopus.Projects.GetChannels(project) // TODO change this to channel partial name search on server; will require go client update if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for _, c := range foundChannels { // server doesn't support channel search by exact name so we must emulate it if strings.EqualFold(c.Name, channelName) { diff --git a/pkg/question/selectors/environments.go b/pkg/question/selectors/environments.go index 0570782f..0de327f4 100644 --- a/pkg/question/selectors/environments.go +++ b/pkg/question/selectors/environments.go @@ -5,6 +5,7 @@ import ( "github.com/OctopusDeploy/cli/pkg/question" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/environments" + "github.com/ztrue/tracerr" "strings" ) @@ -13,11 +14,11 @@ type GetAllEnvironmentsCallback func() ([]*environments.Environment, error) func GetAllEnvironments(client *client.Client) ([]*environments.Environment, error) { envResources, err := client.Environments.Get(environments.EnvironmentsQuery{}) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } allEnvs, err := envResources.GetAllPages(client.Environments.GetClient()) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return allEnvs, nil @@ -26,7 +27,7 @@ func GetAllEnvironments(client *client.Client) ([]*environments.Environment, err func EnvironmentSelect(ask question.Asker, getAllEnvironmentsCallback GetAllEnvironmentsCallback, message string) (*environments.Environment, error) { allEnvs, err := getAllEnvironmentsCallback() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.SelectMap(ask, message, allEnvs, func(item *environments.Environment) string { @@ -37,7 +38,7 @@ func EnvironmentSelect(ask question.Asker, getAllEnvironmentsCallback GetAllEnvi func FindEnvironment(octopus *client.Client, environmentName string) (*environments.Environment, error) { resultPage, err := octopus.Environments.Get(environments.EnvironmentsQuery{PartialName: environmentName}) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } // environmentsQuery has "Name" but it's just an alias in the server for PartialName; we need to filter client side for resultPage != nil && len(resultPage.Items) > 0 { @@ -48,7 +49,7 @@ func FindEnvironment(octopus *client.Client, environmentName string) (*environme } resultPage, err = resultPage.GetNextPage(octopus.Environments.GetClient()) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } // if there are no more pages, then GetNextPage will return nil, which breaks us out of the loop } @@ -58,7 +59,7 @@ func FindEnvironment(octopus *client.Client, environmentName string) (*environme func EnvironmentsMultiSelect(ask question.Asker, getAllEnvironmentsCallback GetAllEnvironmentsCallback, message string, required bool) ([]*environments.Environment, error) { allEnvs, err := getAllEnvironmentsCallback() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.MultiSelectMap(ask, message, allEnvs, func(item *environments.Environment) string { return item.Name diff --git a/pkg/question/selectors/lifecycles.go b/pkg/question/selectors/lifecycles.go index 2256544f..61359060 100644 --- a/pkg/question/selectors/lifecycles.go +++ b/pkg/question/selectors/lifecycles.go @@ -4,12 +4,13 @@ import ( "github.com/OctopusDeploy/cli/pkg/question" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/lifecycles" + "github.com/ztrue/tracerr" ) func Lifecycle(questionText string, octopus *client.Client, ask question.Asker) (*lifecycles.Lifecycle, error) { existingLifecycles, err := octopus.Lifecycles.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } lifecyclesCallback := func() ([]*lifecycles.Lifecycle, error) { return existingLifecycles, nil diff --git a/pkg/question/selectors/projects.go b/pkg/question/selectors/projects.go index cbff93da..5fafde12 100644 --- a/pkg/question/selectors/projects.go +++ b/pkg/question/selectors/projects.go @@ -4,12 +4,13 @@ import ( "github.com/OctopusDeploy/cli/pkg/question" octopusApiClient "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client" "github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/projects" + "github.com/ztrue/tracerr" ) func Project(questionText string, octopus *octopusApiClient.Client, ask question.Asker) (*projects.Project, error) { existingProjects, err := octopus.Projects.GetAll() if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return question.SelectMap(ask, questionText, existingProjects, func(p *projects.Project) string { @@ -20,7 +21,7 @@ func Project(questionText string, octopus *octopusApiClient.Client, ask question func FindProject(octopus *octopusApiClient.Client, projectIdentifier string) (*projects.Project, error) { project, err := octopus.Projects.GetByIdentifier(projectIdentifier) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } return project, nil diff --git a/pkg/question/selectors/selectors.go b/pkg/question/selectors/selectors.go index 72fe5e0f..70addbca 100644 --- a/pkg/question/selectors/selectors.go +++ b/pkg/question/selectors/selectors.go @@ -2,6 +2,7 @@ package selectors import ( "github.com/OctopusDeploy/cli/pkg/question" + "github.com/ztrue/tracerr" ) type SelectOption[T any] struct { @@ -19,7 +20,7 @@ func ByName[T Nameable](ask question.Asker, list []T, message string) (T, error) return item.GetName() }) if err != nil { - return selectedItem, err + return selectedItem, tracerr.Wrap(err) } return selectedItem, nil } @@ -36,7 +37,7 @@ func Select[T any](ask question.Asker, questionText string, itemsCallback func() items, err := itemsCallback() if err != nil { var item T - return item, err + return item, tracerr.Wrap(err) } if len(items) == 1 { return items[0], nil @@ -51,7 +52,7 @@ func SelectOrNew[T any](ask question.Asker, questionText string, itemsCallback f items, err := itemsCallback() if err != nil { var item T - return item, false, err + return item, false, tracerr.Wrap(err) } return question.SelectMapWithNew(ask, questionText, items, getKey) } diff --git a/pkg/util/util.go b/pkg/util/util.go index 3eadec0e..8e1ba114 100644 --- a/pkg/util/util.go +++ b/pkg/util/util.go @@ -1,5 +1,7 @@ package util +import "github.com/ztrue/tracerr" + // SliceContains returns true if it finds an item in the slice that is equal to the target func SliceContains[T comparable](slice []T, target T) bool { for _, item := range slice { @@ -86,10 +88,10 @@ type MapCollectionCacheContainer struct { // items as it iterates the collection, and call out to lambdas to look those values up. // See the unit tests for examples which should clarify the use-cases for this. func MapCollectionWithLookups[T any, TResult any]( - cacheContainer *MapCollectionCacheContainer, // cache for keys (typically this will store a mapping of ID->[Name, Name]). - collection []T, // input (e.g. list of Releases) - keySelector func(T) []string, // fetches the keys (e.g given a Release, returns the [ChannelID, ProjectID] - mapper func(T, []string) TResult, // fetches the value to lookup (e.g given a Release and the [ChannelName,ProjectName], does the mapping to return the output struct) + cacheContainer *MapCollectionCacheContainer, // cache for keys (typically this will store a mapping of ID->[Name, Name]). + collection []T, // input (e.g. list of Releases) + keySelector func(T) []string, // fetches the keys (e.g given a Release, returns the [ChannelID, ProjectID] + mapper func(T, []string) TResult, // fetches the value to lookup (e.g given a Release and the [ChannelName,ProjectName], does the mapping to return the output struct) runLookups ...func([]string) ([]string, error), // callbacks to go fetch values for the keys (given a list of Channel IDs, it should return the list of associated Channel Names) ) ([]TResult, error) { // if the caller didn't specify an external cache, create an internal one. @@ -134,7 +136,7 @@ func MapCollectionWithLookups[T any, TResult any]( if keysToLookup != nil { lookedUpValues, err := runLookups[lookupIdx](keysToLookup) if err != nil { - return nil, err + return nil, tracerr.Wrap(err) } for valueIdx, value := range lookedUpValues { caches[lookupIdx][keysToLookup[valueIdx]] = value From cffa132cea4c61ad2cdb9bcef56385fd3fe6a4ac Mon Sep 17 00:00:00 2001 From: benPearce1 Date: Tue, 7 Mar 2023 16:32:05 +1000 Subject: [PATCH 2/2] fixed missing new line output --- cmd/octopus/main.go | 1 + 1 file changed, 1 insertion(+) diff --git a/cmd/octopus/main.go b/cmd/octopus/main.go index 67cb3228..1e78ba6d 100644 --- a/cmd/octopus/main.go +++ b/cmd/octopus/main.go @@ -78,6 +78,7 @@ func main() { } else { cmd.PrintErr(err) } + cmd.Println() if usageError, ok := err.(*usage.UsageError); ok { // if the code returns a UsageError, print the usage information