-
Notifications
You must be signed in to change notification settings - Fork 13
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial implementation of user-facing errors for state install
and state uninstall
.
#2877
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package packages | ||
|
||
import ( | ||
"errors" | ||
|
||
"github.com/ActiveState/cli/internal/errs" | ||
"github.com/ActiveState/cli/internal/locale" | ||
"github.com/ActiveState/cli/internal/runbits/rationalize" | ||
bpModel "github.com/ActiveState/cli/pkg/platform/api/buildplanner/model" | ||
"github.com/ActiveState/cli/pkg/platform/authentication" | ||
"github.com/ActiveState/cli/pkg/platform/runtime/buildexpression" | ||
) | ||
|
||
func rationalizeError(auth *authentication.Auth, err *error) { | ||
var commitError *bpModel.CommitError | ||
var requirementNotFoundErr *buildexpression.RequirementNotFoundError | ||
|
||
switch { | ||
case err == nil: | ||
return | ||
|
||
// No activestate.yaml. | ||
case errors.Is(*err, rationalize.ErrNoProject): | ||
*err = errs.WrapUserFacing(*err, | ||
locale.T("err_no_project"), | ||
errs.SetInput(), | ||
) | ||
|
||
// Error staging a commit during install. | ||
case errors.As(*err, &commitError): | ||
switch commitError.Type { | ||
case bpModel.NotFoundErrorType: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not quite because of the message, but I've added another case with a slightly different message. |
||
*err = errs.WrapUserFacing(*err, | ||
locale.Tl("err_packages_not_found", "Could not make runtime changes because your project was not found."), | ||
errs.SetInput(), | ||
errs.SetTips(locale.T("tip_private_project_auth")), | ||
) | ||
case bpModel.ForbiddenErrorType: | ||
*err = errs.WrapUserFacing(*err, | ||
locale.Tl("err_packages_forbidden", "Could not make runtime changes because you do not have permission to do so."), | ||
errs.SetInput(), | ||
errs.SetTips(locale.T("tip_private_project_auth")), | ||
) | ||
case bpModel.HeadOnBranchMovedErrorType: | ||
*err = errs.WrapUserFacing(*err, | ||
locale.T("err_buildplanner_head_on_branch_moved"), | ||
errs.SetInput(), | ||
) | ||
case bpModel.NoChangeSinceLastCommitErrorType: | ||
*err = errs.WrapUserFacing(*err, | ||
locale.Tl("err_packages_exists", "That package is already installed."), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this message will have to be more generic as it could also arise when running There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. May I ask how? If the user specifies a requirement that is not already installed, they'll get a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh I see, I missed that part. Thanks for pointing that out. |
||
errs.SetInput(), | ||
) | ||
default: | ||
*err = errs.WrapUserFacing(*err, | ||
locale.Tl("err_packages_buildplanner_error", "Could not make runtime changes due to the following error: {{.V0}}", commitError.Message), | ||
errs.SetInput(), | ||
) | ||
} | ||
|
||
// Requirement not found for uninstall. | ||
case errors.As(*err, &requirementNotFoundErr): | ||
*err = errs.WrapUserFacing(*err, | ||
locale.Tr("err_remove_requirement_not_found", requirementNotFoundErr.Name), | ||
errs.SetInput(), | ||
) | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -302,22 +302,43 @@ func IsErrorResponse(errorType string) bool { | |
errorType == ComitHasNoParentErrorType | ||
} | ||
|
||
type CommitError struct { | ||
Type string | ||
Message string | ||
*locale.LocalizedError // for legacy, non-user-facing error usages | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since not all consumers are using user-facing errors, keep using the localized errors from the buildplanner for those consumers. The user-facing error rationalizer in this PR is making use of There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe that for this to be used this type needs an There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it inherits There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh yes, you're right! |
||
} | ||
|
||
func ProcessCommitError(commit *Commit, fallbackMessage string) error { | ||
if commit.Error == nil { | ||
return errs.New(fallbackMessage) | ||
} | ||
|
||
switch commit.Type { | ||
case NotFoundErrorType: | ||
return locale.NewInputError("err_buildplanner_commit_not_found", "Could not find commit, received message: {{.V0}}", commit.Message) | ||
return &CommitError{ | ||
commit.Type, commit.Message, | ||
locale.NewInputError("err_buildplanner_commit_not_found", "Could not find commit, received message: {{.V0}}", commit.Message), | ||
} | ||
case ParseErrorType: | ||
return locale.NewInputError("err_buildplanner_parse_error", "The platform failed to parse the build expression, received message: {{.V0}}. Path: {{.V1}}", commit.Message, commit.ParseError.Path) | ||
return &CommitError{ | ||
commit.Type, commit.Message, | ||
locale.NewInputError("err_buildplanner_parse_error", "The platform failed to parse the build expression, received message: {{.V0}}. Path: {{.V1}}", commit.Message, commit.ParseError.Path), | ||
} | ||
case ForbiddenErrorType: | ||
return locale.NewInputError("err_buildplanner_forbidden", "Operation forbidden: {{.V0}}, received message: {{.V1}}", commit.Operation, commit.Message) | ||
return &CommitError{ | ||
commit.Type, commit.Message, | ||
locale.NewInputError("err_buildplanner_forbidden", "Operation forbidden: {{.V0}}, received message: {{.V1}}", commit.Operation, commit.Message), | ||
} | ||
case HeadOnBranchMovedErrorType: | ||
return errs.Wrap(locale.NewInputError("err_buildplanner_head_on_branch_moved", "The branch you're trying to update has changed remotely, please run '[ACTIONABLE]state pull[/RESET]'."), "received message: "+commit.Error.Message) | ||
return errs.Wrap(&CommitError{ | ||
commit.Type, commit.Error.Message, | ||
locale.NewInputError("err_buildplanner_head_on_branch_moved"), | ||
}, "received message: "+commit.Error.Message) | ||
case NoChangeSinceLastCommitErrorType: | ||
return errs.Wrap(locale.NewInputError("err_buildplanner_no_change_since_last_commit", "No new changes to commit."), commit.Error.Message) | ||
return errs.Wrap(&CommitError{ | ||
commit.Type, commit.Error.Message, | ||
locale.NewInputError("err_buildplanner_no_change_since_last_commit", "No new changes to commit."), | ||
}, commit.Error.Message) | ||
default: | ||
return errs.New(fallbackMessage) | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should at least log the error message returned from the buildplanner for error types we are not handling here. We could also have a default case that just forwards the error message from the API. I know that for the
ParseError
we definitely want to do that this gives us the ability to have updated error messages in the case that the build expression format changes.