package validation import ( "fmt" "strings" ) // Check identifies one shared validation check. type Check string const ( // GoTest identifies the base Go test suite. GoTest Check = "go-test" // GoVet identifies the separate full vet pass. GoVet Check = "go-vet" // PackageCompile identifies selected-target package compilation. PackageCompile Check = "package-compile" // GoFormat identifies committed Go source formatting. GoFormat Check = "go-format" // WorkspaceFiles identifies committed workspace files in module source. WorkspaceFiles Check = "workspace-files" // LocalReplacements identifies filesystem replacements in committed modules. LocalReplacements Check = "local-replacements" // FileSize identifies committed blobs that exceed a selected size limit. FileSize Check = "file-size" // MarkdownLinks identifies missing committed Markdown destinations or anchors. MarkdownLinks Check = "markdown-links" // SharedFiles identifies a requested shared file that is unavailable. SharedFiles Check = "shared-files" ) // Finding describes a validation observation at an optional source location. type Finding struct { Path string Line int Column int Message string Target string Directive string } // FileSizeMeasurement describes a measured file size and its selected limit. type FileSizeMeasurement struct { Bytes int64 LimitBytes int64 } // Failure describes a failed shared validation check and preserves its cause. type Failure struct { Check Check Findings []Finding Measurement *FileSizeMeasurement Cause error } // Error returns a useful summary of the failed check. func (failure *Failure) Error() string { return formatFailure(failure) } // Unwrap returns the underlying validation error. func (failure *Failure) Unwrap() error { if failure == nil { return nil } return failure.Cause } func formatFailure(failure *Failure) string { if failure == nil { return "" } 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 finding.Target != "" { fmt.Fprintf(&summary, " (target %q)", finding.Target) } if finding.Directive != "" { fmt.Fprintf(&summary, " (directive %q)", finding.Directive) } } if failure.Measurement != nil { fmt.Fprintf(&summary, ": measured %d bytes against a %d byte limit", failure.Measurement.Bytes, failure.Measurement.LimitBytes) } if failure.Cause != nil { if len(failure.Findings) == 0 && failure.Measurement == nil { summary.WriteString(": ") } else { summary.WriteString("; ") } summary.WriteString(failure.Cause.Error()) } return summary.String() } var _ error = (*Failure)(nil) var _ interface{ Unwrap() error } = (*Failure)(nil)