Skip to content
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

Update runtime-debug error handling #2737

Merged
merged 2 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/platform/api/buildplanner/model/buildplan.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func (o Operation) String() string {
}

type BuildPlannerError struct {
Err error
ValidationErrors []string
IsTransient bool
}
Expand All @@ -111,6 +112,10 @@ func (e *BuildPlannerError) UserError() string {
}

func (e *BuildPlannerError) Error() string {
if e.Err != nil {
return e.Err.Error()
}
Comment on lines +115 to +117
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm guessing prior to this change we weren't surfacing this error? Any idea what type of errors this is fixing?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get that, but that doesn't do anything to let us identify the error type, which is what this story is about. I'm not against also including this change, I just want to understand what this change does? What type of scenario are we not handling prior to this change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are already identifying build planner errors but this has only been solving errors. Adding the error field and returning it first allows us to also capture other errors that we want to be considered as build planner errors. In this PR I've included deprecation and fallback errors when processing a build planner response to this type so they will also be identified as build planner errors.


// Append last five lines to error message
offset := 0
numLines := len(e.ValidationErrors)
Expand Down
4 changes: 2 additions & 2 deletions pkg/platform/model/buildplanner.go
Original file line number Diff line number Diff line change
Expand Up @@ -367,10 +367,10 @@ func processBuildPlannerError(bpErr error, fallbackMessage string) error {
if errors.As(bpErr, graphqlErr) {
code, ok := graphqlErr.Extensions[codeExtensionKey].(string)
if ok && code == clientDeprecationErrorKey {
return locale.NewInputError("err_buildplanner_deprecated", "Encountered deprecation error: {{.V0}}", graphqlErr.Message)
return &bpModel.BuildPlannerError{Err: locale.NewInputError("err_buildplanner_deprecated", "Encountered deprecation error: {{.V0}}", graphqlErr.Message)}
}
}
return errs.Wrap(bpErr, fallbackMessage)
return &bpModel.BuildPlannerError{Err: errs.Wrap(bpErr, fallbackMessage)}
}

var versionRe = regexp.MustCompile(`^\d+(\.\d+)*$`)
Expand Down
7 changes: 6 additions & 1 deletion pkg/platform/runtime/runtime.go
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ func (r *Runtime) recordCompletion(err error) {
errorType = "input"
case errs.Matches(err, &model.SolverError{}):
errorType = "solve"
case errs.Matches(err, &setup.BuildError{}) || errs.Matches(err, &buildlog.BuildError{}):
case errs.Matches(err, &setup.BuildError{}), errs.Matches(err, &buildlog.BuildError{}):
errorType = "build"
case errs.Matches(err, &bpModel.BuildPlannerError{}):
errorType = "buildplan"
Expand All @@ -206,13 +206,18 @@ func (r *Runtime) recordCompletion(err error) {
case errs.Matches(err, &setup.ArtifactInstallError{}):
errorType = "install"
// Note: do not break because there could be download errors, and those take precedence
case errs.Matches(err, &setup.BuildError{}), errs.Matches(err, &buildlog.BuildError{}):
errorType = "build"
break // it only takes one build failure to report the runtime failure as due to build error
}
}
}
// Progress/event handler errors should come last because they can wrap one of the above errors,
// and those errors actually caused the failure, not these.
case errs.Matches(err, &setup.ProgressReportError{}) || errs.Matches(err, &buildlog.EventHandlerError{}):
errorType = "progress"
case errs.Matches(err, &setup.ExecutorSetupError{}):
errorType = "postprocess"
}

var message string
Expand Down
16 changes: 13 additions & 3 deletions pkg/platform/runtime/setup/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ type ArtifactSetupErrors struct {
errs []error
}

type ExecutorSetupError struct {
*errs.WrapperError
}

func (a *ArtifactSetupErrors) Error() string {
var errors []string
for _, err := range a.errs {
Expand Down Expand Up @@ -189,7 +193,7 @@ func (s *Setup) Update() (rerr error) {

// Update executors
if err := s.updateExecutors(artifacts); err != nil {
return errs.Wrap(err, "Failed to update executors")
return ExecutorSetupError{errs.Wrap(err, "Failed to update executors")}
}

// Mark installation as completed
Expand Down Expand Up @@ -745,12 +749,16 @@ func (s *Setup) moveToInstallPath(a artifact.ArtifactID, unpackedDir string, env
func (s *Setup) downloadArtifact(a artifact.ArtifactDownload, targetFile string) (rerr error) {
defer func() {
if rerr != nil {
rerr = &ArtifactDownloadError{errs.Wrap(rerr, "Unable to download artifact")}
if !errs.Matches(rerr, &ProgressReportError{}) {
rerr = &ArtifactDownloadError{errs.Wrap(rerr, "Unable to download artifact")}
}

if err := s.handleEvent(events.ArtifactDownloadFailure{a.ArtifactID, rerr}); err != nil {
rerr = errs.Wrap(rerr, "Could not handle ArtifactDownloadFailure event")
return
}
}

if err := s.handleEvent(events.ArtifactDownloadSuccess{a.ArtifactID}); err != nil {
rerr = errs.Wrap(rerr, "Could not handle ArtifactDownloadSuccess event")
return
Expand All @@ -765,7 +773,7 @@ func (s *Setup) downloadArtifact(a artifact.ArtifactDownload, targetFile string)
b, err := httputil.GetWithProgress(artifactURL.String(), &progress.Report{
ReportSizeCb: func(size int) error {
if err := s.handleEvent(events.ArtifactDownloadStarted{a.ArtifactID, size}); err != nil {
return errs.Wrap(err, "Could not handle ArtifactDownloadStarted event")
return ProgressReportError{errs.Wrap(err, "Could not handle ArtifactDownloadStarted event")}
}
return nil
},
Expand All @@ -779,9 +787,11 @@ func (s *Setup) downloadArtifact(a artifact.ArtifactDownload, targetFile string)
if err != nil {
return errs.Wrap(err, "Download %s failed", artifactURL.String())
}

if err := fileutils.WriteFile(targetFile, b); err != nil {
return errs.Wrap(err, "Writing download to target file %s failed", targetFile)
}

return nil
}

Expand Down
Loading