Prepare pipelines before source execution
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
)
|
||||
|
||||
type LegacyRawValidatorConstructor func() (contracts.LegacyRawValidator, error)
|
||||
type LegacyRawValidatorBuilder func(BuildRequest) (contracts.LegacyRawValidator, error)
|
||||
|
||||
type ValidatorSpec struct {
|
||||
Key string `json:"key"`
|
||||
@@ -32,37 +33,42 @@ const (
|
||||
)
|
||||
|
||||
type ValidatorRegistry struct {
|
||||
legacyConstructors map[string]LegacyRawValidatorConstructor
|
||||
legacySpecs map[string]ValidatorSpec
|
||||
typedEntries map[artifactVariantKey]typedValidatorEntry
|
||||
chunkEntries map[string]chunkValidatorEntry
|
||||
serializedEntries map[string]serializedValidatorEntry
|
||||
legacyBuilders map[string]LegacyRawValidatorBuilder
|
||||
legacyValidators map[string]OptionValidator
|
||||
legacySpecs map[string]ValidatorSpec
|
||||
typedEntries map[artifactVariantKey]typedValidatorEntry
|
||||
chunkEntries map[string]chunkValidatorEntry
|
||||
serializedEntries map[string]serializedValidatorEntry
|
||||
}
|
||||
|
||||
type typedValidatorEntry struct {
|
||||
spec ValidatorSpec
|
||||
kind contracts.ArtifactKind
|
||||
valueType reflect.Type
|
||||
constructor func() (any, error)
|
||||
spec ValidatorSpec
|
||||
kind contracts.ArtifactKind
|
||||
valueType reflect.Type
|
||||
validateOptions OptionValidator
|
||||
builder func(BuildRequest) (any, error)
|
||||
}
|
||||
|
||||
type chunkValidatorEntry struct {
|
||||
spec ValidatorSpec
|
||||
constructor func() (contracts.ChunkValidator, error)
|
||||
spec ValidatorSpec
|
||||
validateOptions OptionValidator
|
||||
builder func(BuildRequest) (contracts.ChunkValidator, error)
|
||||
}
|
||||
|
||||
type serializedValidatorEntry struct {
|
||||
spec SerializedValidatorSpec
|
||||
constructor func() (contracts.SerializedValidator, error)
|
||||
spec SerializedValidatorSpec
|
||||
validateOptions OptionValidator
|
||||
builder func(BuildRequest) (contracts.SerializedValidator, error)
|
||||
}
|
||||
|
||||
func NewValidatorRegistry() *ValidatorRegistry {
|
||||
return &ValidatorRegistry{
|
||||
legacyConstructors: make(map[string]LegacyRawValidatorConstructor),
|
||||
legacySpecs: make(map[string]ValidatorSpec),
|
||||
typedEntries: make(map[artifactVariantKey]typedValidatorEntry),
|
||||
chunkEntries: make(map[string]chunkValidatorEntry),
|
||||
serializedEntries: make(map[string]serializedValidatorEntry),
|
||||
legacyBuilders: make(map[string]LegacyRawValidatorBuilder),
|
||||
legacyValidators: make(map[string]OptionValidator),
|
||||
legacySpecs: make(map[string]ValidatorSpec),
|
||||
typedEntries: make(map[artifactVariantKey]typedValidatorEntry),
|
||||
chunkEntries: make(map[string]chunkValidatorEntry),
|
||||
serializedEntries: make(map[string]serializedValidatorEntry),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +77,15 @@ func (r *ValidatorRegistry) RegisterLegacyRaw(key string, constructor LegacyRawV
|
||||
}
|
||||
|
||||
func (r *ValidatorRegistry) RegisterLegacyRawWithSpec(spec ValidatorSpec, constructor LegacyRawValidatorConstructor) error {
|
||||
if constructor == nil {
|
||||
return fmt.Errorf("validator constructor for %q must not be nil", strings.TrimSpace(spec.Key))
|
||||
}
|
||||
return r.RegisterLegacyRawBuilderWithSpec(spec, allowLegacyOptions, func(BuildRequest) (contracts.LegacyRawValidator, error) {
|
||||
return constructor()
|
||||
})
|
||||
}
|
||||
|
||||
func (r *ValidatorRegistry) RegisterLegacyRawBuilderWithSpec(spec ValidatorSpec, validateOptions OptionValidator, builder LegacyRawValidatorBuilder) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("validator registry must not be nil")
|
||||
}
|
||||
@@ -78,24 +93,40 @@ func (r *ValidatorRegistry) RegisterLegacyRawWithSpec(spec ValidatorSpec, constr
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if constructor == nil {
|
||||
return fmt.Errorf("validator constructor for %q must not be nil", normalizedSpec.Key)
|
||||
if validateOptions == nil {
|
||||
return fmt.Errorf("validator option validator for %q must not be nil", normalizedSpec.Key)
|
||||
}
|
||||
if _, ok := r.legacyConstructors[normalizedSpec.Key]; ok {
|
||||
if builder == nil {
|
||||
return fmt.Errorf("validator builder for %q must not be nil", normalizedSpec.Key)
|
||||
}
|
||||
if _, ok := r.legacyBuilders[normalizedSpec.Key]; ok {
|
||||
return fmt.Errorf("legacy raw validator %q is already registered", normalizedSpec.Key)
|
||||
}
|
||||
if r.legacyConstructors == nil {
|
||||
r.legacyConstructors = make(map[string]LegacyRawValidatorConstructor)
|
||||
if r.legacyBuilders == nil {
|
||||
r.legacyBuilders = make(map[string]LegacyRawValidatorBuilder)
|
||||
}
|
||||
if r.legacyValidators == nil {
|
||||
r.legacyValidators = make(map[string]OptionValidator)
|
||||
}
|
||||
if r.legacySpecs == nil {
|
||||
r.legacySpecs = make(map[string]ValidatorSpec)
|
||||
}
|
||||
r.legacyConstructors[normalizedSpec.Key] = constructor
|
||||
r.legacyBuilders[normalizedSpec.Key] = builder
|
||||
r.legacyValidators[normalizedSpec.Key] = validateOptions
|
||||
r.legacySpecs[normalizedSpec.Key] = normalizedSpec
|
||||
return nil
|
||||
}
|
||||
|
||||
func RegisterTypedValidator[T any](registry *ValidatorRegistry, kind contracts.ArtifactKind, spec ValidatorSpec, constructor func() (contracts.TypedValidator[T], error)) error {
|
||||
if constructor == nil {
|
||||
return fmt.Errorf("validator constructor for %q must not be nil", strings.TrimSpace(spec.Key))
|
||||
}
|
||||
return RegisterTypedValidatorBuilder(registry, kind, spec, allowLegacyOptions, func(BuildRequest) (contracts.TypedValidator[T], error) {
|
||||
return constructor()
|
||||
})
|
||||
}
|
||||
|
||||
func RegisterTypedValidatorBuilder[T any](registry *ValidatorRegistry, kind contracts.ArtifactKind, spec ValidatorSpec, validateOptions OptionValidator, builder func(BuildRequest) (contracts.TypedValidator[T], error)) error {
|
||||
if registry == nil {
|
||||
return fmt.Errorf("validator registry must not be nil")
|
||||
}
|
||||
@@ -107,8 +138,11 @@ func RegisterTypedValidator[T any](registry *ValidatorRegistry, kind contracts.A
|
||||
if kind == "" {
|
||||
return fmt.Errorf("typed validator %q artifact kind must not be empty", normalizedSpec.Key)
|
||||
}
|
||||
if constructor == nil {
|
||||
return fmt.Errorf("validator constructor for %q must not be nil", normalizedSpec.Key)
|
||||
if validateOptions == nil {
|
||||
return fmt.Errorf("validator option validator for %q must not be nil", normalizedSpec.Key)
|
||||
}
|
||||
if builder == nil {
|
||||
return fmt.Errorf("validator builder for %q must not be nil", normalizedSpec.Key)
|
||||
}
|
||||
key := artifactVariantKey{module: normalizedSpec.Key, kind: kind}
|
||||
if _, ok := registry.typedEntries[key]; ok {
|
||||
@@ -118,17 +152,27 @@ func RegisterTypedValidator[T any](registry *ValidatorRegistry, kind contracts.A
|
||||
registry.typedEntries = make(map[artifactVariantKey]typedValidatorEntry)
|
||||
}
|
||||
registry.typedEntries[key] = typedValidatorEntry{
|
||||
spec: normalizedSpec,
|
||||
kind: kind,
|
||||
valueType: reflect.TypeFor[T](),
|
||||
constructor: func() (any, error) {
|
||||
return constructor()
|
||||
spec: normalizedSpec,
|
||||
kind: kind,
|
||||
valueType: reflect.TypeFor[T](),
|
||||
validateOptions: validateOptions,
|
||||
builder: func(request BuildRequest) (any, error) {
|
||||
return builder(cloneBuildRequest(request))
|
||||
},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RegisterChunkValidator(registry *ValidatorRegistry, spec ValidatorSpec, constructor func() (contracts.ChunkValidator, error)) error {
|
||||
if constructor == nil {
|
||||
return fmt.Errorf("validator constructor for %q must not be nil", strings.TrimSpace(spec.Key))
|
||||
}
|
||||
return RegisterChunkValidatorBuilder(registry, spec, allowLegacyOptions, func(BuildRequest) (contracts.ChunkValidator, error) {
|
||||
return constructor()
|
||||
})
|
||||
}
|
||||
|
||||
func RegisterChunkValidatorBuilder(registry *ValidatorRegistry, spec ValidatorSpec, validateOptions OptionValidator, builder func(BuildRequest) (contracts.ChunkValidator, error)) error {
|
||||
if registry == nil {
|
||||
return fmt.Errorf("validator registry must not be nil")
|
||||
}
|
||||
@@ -136,8 +180,11 @@ func RegisterChunkValidator(registry *ValidatorRegistry, spec ValidatorSpec, con
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if constructor == nil {
|
||||
return fmt.Errorf("validator constructor for %q must not be nil", normalizedSpec.Key)
|
||||
if validateOptions == nil {
|
||||
return fmt.Errorf("validator option validator for %q must not be nil", normalizedSpec.Key)
|
||||
}
|
||||
if builder == nil {
|
||||
return fmt.Errorf("validator builder for %q must not be nil", normalizedSpec.Key)
|
||||
}
|
||||
if _, ok := registry.chunkEntries[normalizedSpec.Key]; ok {
|
||||
return fmt.Errorf("chunk validator %q is already registered", normalizedSpec.Key)
|
||||
@@ -145,11 +192,20 @@ func RegisterChunkValidator(registry *ValidatorRegistry, spec ValidatorSpec, con
|
||||
if registry.chunkEntries == nil {
|
||||
registry.chunkEntries = make(map[string]chunkValidatorEntry)
|
||||
}
|
||||
registry.chunkEntries[normalizedSpec.Key] = chunkValidatorEntry{spec: normalizedSpec, constructor: constructor}
|
||||
registry.chunkEntries[normalizedSpec.Key] = chunkValidatorEntry{spec: normalizedSpec, validateOptions: validateOptions, builder: builder}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RegisterSerializedValidator(registry *ValidatorRegistry, spec SerializedValidatorSpec, constructor func() (contracts.SerializedValidator, error)) error {
|
||||
if constructor == nil {
|
||||
return fmt.Errorf("validator constructor for %q must not be nil", strings.TrimSpace(spec.Key))
|
||||
}
|
||||
return RegisterSerializedValidatorBuilder(registry, spec, allowLegacyOptions, func(BuildRequest) (contracts.SerializedValidator, error) {
|
||||
return constructor()
|
||||
})
|
||||
}
|
||||
|
||||
func RegisterSerializedValidatorBuilder(registry *ValidatorRegistry, spec SerializedValidatorSpec, validateOptions OptionValidator, builder func(BuildRequest) (contracts.SerializedValidator, error)) error {
|
||||
if registry == nil {
|
||||
return fmt.Errorf("validator registry must not be nil")
|
||||
}
|
||||
@@ -161,8 +217,11 @@ func RegisterSerializedValidator(registry *ValidatorRegistry, spec SerializedVal
|
||||
if !spec.SupportsChunks && !spec.SupportsArtifacts {
|
||||
return fmt.Errorf("serialized validator %q must support chunks, artifacts, or both", spec.Key)
|
||||
}
|
||||
if constructor == nil {
|
||||
return fmt.Errorf("validator constructor for %q must not be nil", spec.Key)
|
||||
if validateOptions == nil {
|
||||
return fmt.Errorf("validator option validator for %q must not be nil", spec.Key)
|
||||
}
|
||||
if builder == nil {
|
||||
return fmt.Errorf("validator builder for %q must not be nil", spec.Key)
|
||||
}
|
||||
if _, ok := registry.serializedEntries[spec.Key]; ok {
|
||||
return fmt.Errorf("serialized validator %q is already registered", spec.Key)
|
||||
@@ -170,11 +229,15 @@ func RegisterSerializedValidator(registry *ValidatorRegistry, spec SerializedVal
|
||||
if registry.serializedEntries == nil {
|
||||
registry.serializedEntries = make(map[string]serializedValidatorEntry)
|
||||
}
|
||||
registry.serializedEntries[spec.Key] = serializedValidatorEntry{spec: spec, constructor: constructor}
|
||||
registry.serializedEntries[spec.Key] = serializedValidatorEntry{spec: spec, validateOptions: validateOptions, builder: builder}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *ValidatorRegistry) BuildLegacyRaw(key string) (contracts.LegacyRawValidator, error) {
|
||||
return r.BuildLegacyRawWithRequest(key, BuildRequest{})
|
||||
}
|
||||
|
||||
func (r *ValidatorRegistry) BuildLegacyRawWithRequest(key string, request BuildRequest) (contracts.LegacyRawValidator, error) {
|
||||
if r == nil {
|
||||
return nil, fmt.Errorf("validator registry must not be nil")
|
||||
}
|
||||
@@ -182,11 +245,11 @@ func (r *ValidatorRegistry) BuildLegacyRaw(key string) (contracts.LegacyRawValid
|
||||
if normalizedKey == "" {
|
||||
return nil, fmt.Errorf("validator key must not be empty")
|
||||
}
|
||||
constructor, ok := r.legacyConstructors[normalizedKey]
|
||||
builder, ok := r.legacyBuilders[normalizedKey]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("legacy raw validator %q is not registered", normalizedKey)
|
||||
}
|
||||
validator, err := constructor()
|
||||
validator, err := builder(cloneBuildRequest(request))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("build validator %q: %w", normalizedKey, err)
|
||||
}
|
||||
@@ -203,6 +266,37 @@ func (r *ValidatorRegistry) BuildLegacyRaw(key string) (contracts.LegacyRawValid
|
||||
return validator, nil
|
||||
}
|
||||
|
||||
func (r *ValidatorRegistry) validateOptions(resolved ResolvedValidator) error {
|
||||
if r == nil {
|
||||
return fmt.Errorf("validator registry must not be nil")
|
||||
}
|
||||
key := strings.TrimSpace(resolved.Binding.Module)
|
||||
var validator OptionValidator
|
||||
switch resolved.Target {
|
||||
case ValidatorTargetTyped:
|
||||
entry, ok := r.typedEntry(key, resolved.ArtifactKind)
|
||||
if ok {
|
||||
validator = entry.validateOptions
|
||||
}
|
||||
case ValidatorTargetChunk:
|
||||
entry, ok := r.chunkEntry(key)
|
||||
if ok {
|
||||
validator = entry.validateOptions
|
||||
}
|
||||
case ValidatorTargetSerialized:
|
||||
entry, ok := r.serializedEntry(key)
|
||||
if ok {
|
||||
validator = entry.validateOptions
|
||||
}
|
||||
default:
|
||||
validator = r.legacyValidators[key]
|
||||
}
|
||||
if validator == nil {
|
||||
return fmt.Errorf("validator %q construction entry is not registered", key)
|
||||
}
|
||||
return validateRegisteredOptions(validator, resolved.Binding.Options)
|
||||
}
|
||||
|
||||
func (r *ValidatorRegistry) Spec(key string) (ValidatorSpec, bool) {
|
||||
if r == nil {
|
||||
return ValidatorSpec{}, false
|
||||
|
||||
Reference in New Issue
Block a user