github.com/ActiveState/cli@v0.0.0-20240508170324-6801f60cd051/pkg/platform/api/buildplanner/response/shared.go (about) 1 package response 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 8 "github.com/ActiveState/cli/internal/errs" 9 "github.com/ActiveState/cli/internal/locale" 10 "github.com/ActiveState/cli/pkg/platform/api/buildplanner/types" 11 ) 12 13 type BuildPlannerError struct { 14 Err error 15 ValidationErrors []string 16 IsTransient bool 17 } 18 19 // InputError returns true as we want to treat all build planner errors as input errors 20 // and not report them to Rollbar. We defer the responsibility of logging these errors 21 // to the maintainers of the build planner. 22 func (e *BuildPlannerError) InputError() bool { 23 return true 24 } 25 26 // UserError returns the error message to be displayed to the user. 27 // This function is added so that BuildPlannerErrors will be displayed 28 // to the user 29 func (e *BuildPlannerError) LocalizedError() string { 30 return e.Error() 31 } 32 33 func (e *BuildPlannerError) Error() string { 34 if e.Err != nil { 35 return e.Err.Error() 36 } 37 38 // Append last five lines to error message 39 offset := 0 40 numLines := len(e.ValidationErrors) 41 if numLines > 5 { 42 offset = numLines - 5 43 } 44 45 errorLines := strings.Join(e.ValidationErrors[offset:], "\n") 46 // Crop at 500 characters to reduce noisy output further 47 if len(errorLines) > 500 { 48 offset = len(errorLines) - 499 49 errorLines = fmt.Sprintf("…%s", errorLines[offset:]) 50 } 51 isCropped := offset > 0 52 croppedMessage := "" 53 if isCropped { 54 croppedMessage = locale.Tl("buildplan_err_cropped_intro", "These are the last lines of the error message:") 55 } 56 57 var err error 58 59 if croppedMessage != "" { 60 err = locale.NewError("buildplan_err_cropped", "", croppedMessage, errorLines) 61 } else { 62 err = locale.NewError("buildplan_err", "", errorLines) 63 } 64 65 if e.IsTransient { 66 err = errs.AddTips(err, locale.Tr("transient_solver_tip")) 67 } 68 69 return err.Error() 70 } 71 72 func (e *BuildPlannerError) Unwrap() error { 73 return errors.Unwrap(e.Err) 74 } 75 76 func IsErrorResponse(errorType string) bool { 77 return errorType == types.ErrorType || 78 errorType == types.NotFoundErrorType || 79 errorType == types.ParseErrorType || 80 errorType == types.AlreadyExistsErrorType || 81 errorType == types.NoChangeSinceLastCommitErrorType || 82 errorType == types.HeadOnBranchMovedErrorType || 83 errorType == types.ForbiddenErrorType || 84 errorType == types.RemediableSolveErrorType || 85 errorType == types.PlanningErrorType || 86 errorType == types.MergeConflictType || 87 errorType == types.FastForwardErrorType || 88 errorType == types.NoCommonBaseFoundType || 89 errorType == types.ValidationErrorType || 90 errorType == types.MergeConflictErrorType || 91 errorType == types.RevertConflictErrorType || 92 errorType == types.CommitNotInTargetHistoryErrorType || 93 errorType == types.ComitHasNoParentErrorType 94 } 95 96 // NotFoundError represents an error that occurred because a resource was not found. 97 type NotFoundError struct { 98 Type string `json:"type"` 99 Resource string `json:"resource"` 100 MayNeedAuthentication bool `json:"mayNeedAuthentication"` 101 } 102 103 // ParseError is an error that occurred while parsing the build expression. 104 type ParseError struct { 105 Path string `json:"path"` 106 } 107 108 type ForbiddenError struct { 109 Operation string `json:"operation"` 110 } 111 112 // Error contains an error message. 113 type Error struct { 114 Message string `json:"message"` 115 }