114 lines
4.2 KiB
Go
114 lines
4.2 KiB
Go
package cli
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"time"
|
|
|
|
"gitea.maximumdirect.net/eric/audita/v3/internal/core/diagnostics"
|
|
"gitea.maximumdirect.net/eric/audita/v3/internal/core/redaction"
|
|
"gitea.maximumdirect.net/eric/audita/v3/internal/core/reporting"
|
|
"gitea.maximumdirect.net/eric/audita/v3/internal/framework/outcomes"
|
|
commandkit "go.maximumdirect.net/commandkit"
|
|
)
|
|
|
|
// finishProcess delivers the transcript and reports before emitting success information.
|
|
func finishProcess(inv commandkit.Invocation, input processInput, loaded *processInputs, prepared *preparedProcess, snapshot reporting.Snapshot, transcript []byte, primary error) commandkit.Outcome {
|
|
reporter := inv.Reporter()
|
|
secrets := loaded.Runtime.ConfiguredSecrets(inv.Context)
|
|
safe := redaction.New(secrets)
|
|
for _, warning := range prepared.Prepared.Warnings {
|
|
_ = reporter.Warn("Debug artifact: " + safe.String(warning.Error()))
|
|
}
|
|
completed := time.Now().UTC()
|
|
snapshot.RunID, snapshot.StartedAt, snapshot.CompletedAt = prepared.RunID, prepared.Started, &completed
|
|
snapshot.TranscriptPath, snapshot.OutputPath = input.Transcript, input.Output.Value
|
|
if primary == nil {
|
|
primary = inv.Context.Err()
|
|
}
|
|
snapshot.Status = reporting.StatusCompleted
|
|
if primary != nil {
|
|
snapshot = failedProcessingSnapshot(snapshot, primary, inv.Context.Err())
|
|
}
|
|
reportPaths := prepared.Prepared.Output.ReportPaths()
|
|
var reports diagnostics.ReportBundle
|
|
var failed func([]diagnostics.FileFailure) diagnostics.ReportBundle
|
|
if len(reportPaths) > 0 {
|
|
var err error
|
|
reports, err = renderReportBundle(snapshot, secrets...)
|
|
if err != nil {
|
|
if primary == nil {
|
|
primary = err
|
|
}
|
|
snapshot.Status = reporting.StatusFailed
|
|
}
|
|
failed = func(failures []diagnostics.FileFailure) diagnostics.ReportBundle {
|
|
result, bundleErr := renderReportBundle(failedOutputSnapshot(snapshot, failures), secrets...)
|
|
if bundleErr != nil {
|
|
return reports
|
|
}
|
|
return result
|
|
}
|
|
}
|
|
if canceled := inv.Context.Err(); primary == nil && canceled != nil {
|
|
primary = canceled
|
|
snapshot = failedProcessingSnapshot(snapshot, canceled, canceled)
|
|
if failed != nil {
|
|
reports = failed(nil)
|
|
}
|
|
}
|
|
result := prepared.Prepared.Output.Finish(primary, transcript, reports, failed)
|
|
if result != nil {
|
|
return commandkit.Failure(safe.String(result.Error())).WithCause(result)
|
|
}
|
|
_ = reporter.AtEnd().Info(reporting.CompletionLine(snapshot))
|
|
for _, path := range reportPaths {
|
|
_ = reporter.AtEnd().Info(fmt.Sprintf("Report: %s", safe.String(path)))
|
|
}
|
|
if prepared.Prepared.Debug != nil {
|
|
_ = reporter.AtEnd().Info(fmt.Sprintf("Diagnostics: %s", safe.String(prepared.Prepared.Debug.Path())))
|
|
}
|
|
return commandkit.Success()
|
|
}
|
|
|
|
func failedProcessingSnapshot(snapshot reporting.Snapshot, primary, contextErr error) reporting.Snapshot {
|
|
for _, record := range snapshot.Errors {
|
|
if record.Scope == "run" {
|
|
return failedOutputSnapshot(snapshot, nil)
|
|
}
|
|
}
|
|
record := reporting.ErrorRecord{Scope: "run", Reason: "processing_failure", Message: "Processing failed"}
|
|
if errors.Is(primary, context.Canceled) || (contextErr != nil && errors.Is(primary, contextErr)) {
|
|
record.Phase = "processing"
|
|
record.Reason = string(outcomes.ReasonCanceled)
|
|
record.Message = "Processing was canceled."
|
|
}
|
|
snapshot.Errors = append(snapshot.Errors, record)
|
|
return failedOutputSnapshot(snapshot, nil)
|
|
}
|
|
|
|
// failedOutputSnapshot derives the count from the same run records sent to each report.
|
|
func failedOutputSnapshot(snapshot reporting.Snapshot, failures []diagnostics.FileFailure) reporting.Snapshot {
|
|
snapshot.Status = reporting.StatusFailed
|
|
if len(failures) > 0 {
|
|
snapshot.Errors = append([]reporting.ErrorRecord(nil), snapshot.Errors...)
|
|
}
|
|
for _, failure := range failures {
|
|
record := reporting.ErrorRecord{Scope: "run", Reason: "output_failure", Message: "Required output delivery failed", OutputPath: failure.Path}
|
|
if failure.Kind == "report initialization" {
|
|
record.Phase = "initialization"
|
|
record.Message = "Required report initialization failed"
|
|
}
|
|
snapshot.Errors = append(snapshot.Errors, record)
|
|
}
|
|
count := 0
|
|
for _, record := range snapshot.Errors {
|
|
if record.Scope == "run" {
|
|
count++
|
|
}
|
|
}
|
|
snapshot.Summary.RunErrors = &count
|
|
return snapshot
|
|
}
|