diff --git a/pipeline/frontend/yaml/linter/schema/schema.go b/pipeline/frontend/yaml/linter/schema/schema.go index 4666faa7ef..228cf8b465 100644 --- a/pipeline/frontend/yaml/linter/schema/schema.go +++ b/pipeline/frontend/yaml/linter/schema/schema.go @@ -19,6 +19,7 @@ import ( _ "embed" "fmt" "io" + "strings" "codeberg.org/6543/go-yaml2json" "codeberg.org/6543/xyaml" @@ -58,7 +59,7 @@ func Lint(r io.Reader) ([]gojsonschema.ResultError, error) { } if !result.Valid() { - return result.Errors(), fmt.Errorf("config not valid") + return filterRedundantCompositionErrors(result.Errors()), fmt.Errorf("config not valid") } return nil, nil @@ -67,3 +68,47 @@ func Lint(r io.Reader) ([]gojsonschema.ResultError, error) { func LintString(s string) ([]gojsonschema.ResultError, error) { return Lint(bytes.NewBufferString(s)) } + +func filterRedundantCompositionErrors(schemaErrors []gojsonschema.ResultError) []gojsonschema.ResultError { + filtered := make([]gojsonschema.ResultError, 0, len(schemaErrors)) + for index, schemaError := range schemaErrors { + if isCompositionError(schemaError) && hasSpecificSchemaError(schemaErrors, index, schemaError.Field()) { + continue + } + + filtered = append(filtered, schemaError) + } + + return filtered +} + +func isCompositionError(schemaError gojsonschema.ResultError) bool { + switch schemaError.Type() { + case "number_one_of", "number_any_of": + return true + default: + return false + } +} + +func hasSpecificSchemaError(schemaErrors []gojsonschema.ResultError, currentIndex int, field string) bool { + for index, schemaError := range schemaErrors { + if index == currentIndex || isCompositionError(schemaError) { + continue + } + + if isSameFieldOrChild(schemaError.Field(), field) { + return true + } + } + + return false +} + +func isSameFieldOrChild(field, parent string) bool { + if parent == "(root)" { + return true + } + + return field == parent || strings.HasPrefix(field, parent+".") +} diff --git a/pipeline/frontend/yaml/linter/schema/schema_test.go b/pipeline/frontend/yaml/linter/schema/schema_test.go index 11d29384fa..e164a10367 100644 --- a/pipeline/frontend/yaml/linter/schema/schema_test.go +++ b/pipeline/frontend/yaml/linter/schema/schema_test.go @@ -147,3 +147,27 @@ func TestSchema(t *testing.T) { }) } } + +func TestSchemaFiltersRedundantCompositionErrors(t *testing.T) { + t.Parallel() + + configErrors, err := schema.LintString(`steps: + publish: + image: plugins/docker + settings: + repo: foo/bar + tags: latest + environment: + CGO: 0 +`) + require.Error(t, err) + + descriptions := make([]string, 0, len(configErrors)) + for _, configError := range configErrors { + descriptions = append(descriptions, configError.Description()) + } + + assert.NotContains(t, descriptions, "Must validate one and only one schema (oneOf)") + assert.NotContains(t, descriptions, "Must validate at least one schema (anyOf)") + assert.Contains(t, descriptions, "Additional property settings is not allowed") +}