128 lines
4.0 KiB
Go
128 lines
4.0 KiB
Go
package releasekit
|
|
|
|
import (
|
|
"errors"
|
|
"slices"
|
|
|
|
"gitea.maximumdirect.net/eric/ReleaseKit/internal/validation"
|
|
)
|
|
|
|
// ValidationCheck identifies a shared validation check that failed.
|
|
// Current checks include "go-test", "go-vet", "package-compile", "go-format",
|
|
// "workspace-files", "local-replacements", "file-size", and "markdown-links".
|
|
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 check details alongside the contextual and underlying causes.
|
|
func (failure *ValidationError) Error() string {
|
|
if failure == nil {
|
|
return "<nil>"
|
|
}
|
|
diagnostic := internalValidationFailure(failure)
|
|
var original *validation.Failure
|
|
if errors.As(failure.Cause, &original) && sameValidationDiagnostics(diagnostic, original) {
|
|
// Converted causes already render these diagnostics and candidate context.
|
|
return failure.Cause.Error()
|
|
}
|
|
return diagnostic.Error()
|
|
}
|
|
|
|
// 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 publicFailure *ValidationError
|
|
if errors.As(err, &publicFailure) {
|
|
return err
|
|
}
|
|
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 internalValidationFailure(failure *ValidationError) *validation.Failure {
|
|
result := &validation.Failure{Check: validation.Check(failure.Check), Cause: failure.Cause}
|
|
for _, finding := range failure.Findings {
|
|
result.Findings = append(result.Findings, validation.Finding{
|
|
Path: finding.Path, Line: finding.Line, Column: finding.Column,
|
|
Message: finding.Message, Target: finding.Target, Directive: finding.Directive,
|
|
})
|
|
}
|
|
if failure.Measurement != nil {
|
|
result.Measurement = &validation.FileSizeMeasurement{
|
|
Bytes: failure.Measurement.Bytes, LimitBytes: failure.Measurement.LimitBytes,
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
func sameValidationDiagnostics(a, b *validation.Failure) bool {
|
|
if b == nil || a.Check != b.Check || !slices.Equal(a.Findings, b.Findings) {
|
|
return false
|
|
}
|
|
if a.Measurement == nil || b.Measurement == nil {
|
|
return a.Measurement == b.Measurement
|
|
}
|
|
return *a.Measurement == *b.Measurement
|
|
}
|
|
|
|
var _ error = (*ValidationError)(nil)
|