Expose validation errors through the root API
This commit is contained in:
121
validation_error.go
Normal file
121
validation_error.go
Normal file
@@ -0,0 +1,121 @@
|
||||
package releasekit
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"gitea.maximumdirect.net/eric/ReleaseKit/internal/validation"
|
||||
)
|
||||
|
||||
// ValidationCheck identifies a shared validation check that failed.
|
||||
// Current checks include "go-test".
|
||||
type ValidationCheck string
|
||||
|
||||
// ValidationFinding describes a failed check observation at an optional
|
||||
// repository-relative source location.
|
||||
type ValidationFinding struct {
|
||||
Path string // repository-relative path when available
|
||||
Line int // one-based source line, or zero when unavailable
|
||||
Column int // one-based source column, or zero when unavailable
|
||||
Message string // useful detail that is not promised to have exact wording
|
||||
Target string // applicable target for a file check
|
||||
Directive string // applicable directive for a file check
|
||||
}
|
||||
|
||||
// FileSizeMeasurement reports a measured file size and its selected limit.
|
||||
type FileSizeMeasurement struct {
|
||||
Bytes int64
|
||||
LimitBytes int64
|
||||
}
|
||||
|
||||
// ValidationError describes a failed shared validation check returned by
|
||||
// [Check] or [Publish]. Cause preserves the contextual and underlying error chain.
|
||||
type ValidationError struct {
|
||||
Check ValidationCheck // failed shared check
|
||||
Findings []ValidationFinding // actionable observations, when available
|
||||
Measurement *FileSizeMeasurement // measured file size, when applicable
|
||||
Cause error // original contextual and underlying error chain
|
||||
}
|
||||
|
||||
// Error returns the contextual validation error summary.
|
||||
func (failure *ValidationError) Error() string {
|
||||
if failure == nil {
|
||||
return "<nil>"
|
||||
}
|
||||
if failure.Cause != nil {
|
||||
return failure.Cause.Error()
|
||||
}
|
||||
return formatPublicValidationError(failure)
|
||||
}
|
||||
|
||||
// Unwrap returns the original validation error chain.
|
||||
func (failure *ValidationError) Unwrap() error {
|
||||
if failure == nil {
|
||||
return nil
|
||||
}
|
||||
return failure.Cause
|
||||
}
|
||||
|
||||
func convertValidationError(err error) error {
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
var failure *validation.Failure
|
||||
if !errors.As(err, &failure) {
|
||||
return err
|
||||
}
|
||||
result := &ValidationError{
|
||||
Check: ValidationCheck(failure.Check),
|
||||
Cause: err,
|
||||
}
|
||||
if len(failure.Findings) != 0 {
|
||||
result.Findings = make([]ValidationFinding, len(failure.Findings))
|
||||
for index, finding := range failure.Findings {
|
||||
result.Findings[index] = ValidationFinding{
|
||||
Path: finding.Path,
|
||||
Line: finding.Line,
|
||||
Column: finding.Column,
|
||||
Message: finding.Message,
|
||||
Target: finding.Target,
|
||||
Directive: finding.Directive,
|
||||
}
|
||||
}
|
||||
}
|
||||
if failure.Measurement != nil {
|
||||
result.Measurement = &FileSizeMeasurement{
|
||||
Bytes: failure.Measurement.Bytes,
|
||||
LimitBytes: failure.Measurement.LimitBytes,
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func formatPublicValidationError(failure *ValidationError) string {
|
||||
var summary strings.Builder
|
||||
if failure.Check == "" {
|
||||
summary.WriteString("validation failed")
|
||||
} else {
|
||||
fmt.Fprintf(&summary, "%s validation failed", failure.Check)
|
||||
}
|
||||
for _, finding := range failure.Findings {
|
||||
summary.WriteString(": ")
|
||||
if finding.Path != "" {
|
||||
summary.WriteString(finding.Path)
|
||||
if finding.Line > 0 {
|
||||
fmt.Fprintf(&summary, ":%d", finding.Line)
|
||||
if finding.Column > 0 {
|
||||
fmt.Fprintf(&summary, ":%d", finding.Column)
|
||||
}
|
||||
}
|
||||
summary.WriteString(": ")
|
||||
}
|
||||
summary.WriteString(finding.Message)
|
||||
}
|
||||
if failure.Measurement != nil {
|
||||
fmt.Fprintf(&summary, ": measured %d bytes against a %d byte limit", failure.Measurement.Bytes, failure.Measurement.LimitBytes)
|
||||
}
|
||||
return summary.String()
|
||||
}
|
||||
|
||||
var _ error = (*ValidationError)(nil)
|
||||
Reference in New Issue
Block a user