85 lines
2.5 KiB
Go
85 lines
2.5 KiB
Go
package state
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"gitea.maximumdirect.net/eric/distributor/internal/bundle"
|
|
"gitea.maximumdirect.net/eric/distributor/internal/link"
|
|
"gitea.maximumdirect.net/eric/distributor/internal/storage"
|
|
)
|
|
|
|
const (
|
|
OutputKindSource = "source"
|
|
OutputKindGenerated = "generated"
|
|
)
|
|
|
|
func Validate(s DistributorState) error {
|
|
if s.SchemaVersion != SchemaVersion {
|
|
return fmt.Errorf("state schema_version must be %d", SchemaVersion)
|
|
}
|
|
if s.PipelineID == "" {
|
|
return fmt.Errorf("state pipeline_id is required")
|
|
}
|
|
if s.DestinationID == "" {
|
|
return fmt.Errorf("state destination_id is required")
|
|
}
|
|
if s.PublishedAt.IsZero() {
|
|
return fmt.Errorf("state published_at is required")
|
|
}
|
|
if err := validateEmbeddedManifest(s.Source.Manifest); err != nil {
|
|
return fmt.Errorf("state source.manifest: %w", err)
|
|
}
|
|
if s.Links != nil && s.Links.PrimaryURL != "" {
|
|
if err := link.ValidateHTTPURL(s.Links.PrimaryURL); err != nil {
|
|
return fmt.Errorf("state links.primary_url: %w", err)
|
|
}
|
|
}
|
|
if s.Outputs == nil {
|
|
return fmt.Errorf("state outputs is required")
|
|
}
|
|
seen := make(map[string]struct{}, len(s.Outputs))
|
|
for index, output := range s.Outputs {
|
|
if err := validateOutput(index, output); err != nil {
|
|
return err
|
|
}
|
|
if _, exists := seen[output.Path]; exists {
|
|
return fmt.Errorf("state outputs[%d].path duplicates %q", index, output.Path)
|
|
}
|
|
seen[output.Path] = struct{}{}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func validateEmbeddedManifest(manifest bundle.Manifest) error {
|
|
return bundle.ValidateManifest(manifest)
|
|
}
|
|
|
|
func validateOutput(index int, output OutputFile) error {
|
|
if err := storage.ValidatePath(output.Path); err != nil {
|
|
return fmt.Errorf("state outputs[%d].path: %w", index, err)
|
|
}
|
|
switch output.Kind {
|
|
case OutputKindSource, OutputKindGenerated:
|
|
default:
|
|
return fmt.Errorf("state outputs[%d].kind must be source or generated", index)
|
|
}
|
|
if err := storage.ValidatePath(output.SourcePath); err != nil {
|
|
return fmt.Errorf("state outputs[%d].source_path: %w", index, err)
|
|
}
|
|
if output.Kind == OutputKindGenerated && output.Transform == "" {
|
|
return fmt.Errorf("state outputs[%d].transform is required for generated output", index)
|
|
}
|
|
if output.URL != "" {
|
|
if err := link.ValidateHTTPURL(output.URL); err != nil {
|
|
return fmt.Errorf("state outputs[%d].url: %w", index, err)
|
|
}
|
|
}
|
|
if err := bundle.ValidateDigest(output.SHA256); err != nil {
|
|
return fmt.Errorf("state outputs[%d].sha256: %w", index, err)
|
|
}
|
|
if output.Size < 0 {
|
|
return fmt.Errorf("state outputs[%d].size must be non-negative", index)
|
|
}
|
|
return nil
|
|
}
|