Write terminal debug reports for failed runs
This commit is contained in:
90
internal/cli/run_terminal.go
Normal file
90
internal/cli/run_terminal.go
Normal file
@@ -0,0 +1,90 @@
|
||||
package cli
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/core/debugbundle"
|
||||
"gitea.maximumdirect.net/eric/notarius/internal/framework/pipeline"
|
||||
)
|
||||
|
||||
type DebugTerminalWriter interface {
|
||||
WriteRunReport(debugbundle.RunReport) error
|
||||
WriteError(string) error
|
||||
}
|
||||
|
||||
type pipelineCommandState struct {
|
||||
report debugbundle.RunReport
|
||||
terminalized bool
|
||||
}
|
||||
|
||||
func newPipelineCommandState(runID, pipelineID, outputPath string) *pipelineCommandState {
|
||||
return &pipelineCommandState{report: debugbundle.RunReport{
|
||||
RunID: runID,
|
||||
PipelineID: pipelineID,
|
||||
OutputPath: outputPath,
|
||||
}}
|
||||
}
|
||||
|
||||
func (s *pipelineCommandState) setDebugPath(debugPath string) {
|
||||
if s != nil {
|
||||
s.report.DebugPath = debugPath
|
||||
}
|
||||
}
|
||||
|
||||
func (s *pipelineCommandState) observeOutput(output pipeline.RunOutput) {
|
||||
if s == nil {
|
||||
return
|
||||
}
|
||||
s.report.OutputCount = len(output.NormalizeOutputs)
|
||||
s.report.RejectedCount = len(output.Rejected)
|
||||
s.report.WarningCount = len(output.Warnings)
|
||||
s.report.ValidationStatus = output.Manifest.ValidationStatus
|
||||
}
|
||||
|
||||
func (s *pipelineCommandState) terminalize(writer DebugTerminalWriter, primaryErr error) (error, error) {
|
||||
if s == nil || s.terminalized {
|
||||
return primaryErr, nil
|
||||
}
|
||||
s.terminalized = true
|
||||
if writer == nil {
|
||||
return primaryErr, nil
|
||||
}
|
||||
|
||||
report := s.report
|
||||
report.Succeeded = primaryErr == nil
|
||||
reportErr := writer.WriteRunReport(report)
|
||||
if reportErr != nil {
|
||||
reportErr = fmt.Errorf("write debug run report: %w", reportErr)
|
||||
if primaryErr == nil {
|
||||
primaryErr = reportErr
|
||||
reportErr = nil
|
||||
}
|
||||
}
|
||||
|
||||
var errorLogErr error
|
||||
if primaryErr != nil {
|
||||
if err := writer.WriteError(primaryErr.Error()); err != nil {
|
||||
errorLogErr = fmt.Errorf("write debug error log: %w", err)
|
||||
}
|
||||
}
|
||||
return primaryErr, errors.Join(reportErr, errorLogErr)
|
||||
}
|
||||
|
||||
func failPipelineCommand(stderr io.Writer, state *pipelineCommandState, writer DebugTerminalWriter, primaryErr error, persistenceErrs ...error) int {
|
||||
primaryErr, terminalErr := state.terminalize(writer, primaryErr)
|
||||
persistenceErrs = append(persistenceErrs, terminalErr)
|
||||
return writePipelineCommandFailure(stderr, state, primaryErr, errors.Join(persistenceErrs...))
|
||||
}
|
||||
|
||||
func writePipelineCommandFailure(stderr io.Writer, state *pipelineCommandState, primaryErr, persistenceErr error) int {
|
||||
fmt.Fprintf(stderr, "notarius: %v\n", primaryErr)
|
||||
if persistenceErr != nil {
|
||||
fmt.Fprintf(stderr, "notarius: %v\n", persistenceErr)
|
||||
}
|
||||
if state != nil && state.report.DebugPath != "" {
|
||||
fmt.Fprintf(stderr, "notarius: debug=%s\n", state.report.DebugPath)
|
||||
}
|
||||
return 1
|
||||
}
|
||||
Reference in New Issue
Block a user