Skip to content

Commit 98a993f

Browse files
committed
feat: add syntax/schema error prefixes and error-type groupby
- Prefix each validation error with 'syntax:' or 'schema:' to distinguish error types across all reporters - Add ErrorType field to Report struct - Add 'error-type' as a new groupby option that groups results into syntax, schema, and Passed categories - Update flag help text, README, and index
1 parent 136758b commit 98a993f

File tree

10 files changed

+77
-15
lines changed

10 files changed

+77
-15
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10-
## [2.0.1] - 2026-04-09
10+
## [2.1.0] - 2026-04-09
1111

1212
### Added
1313

PKGBUILD

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
# Maintainer: Clayton Kehoe <clayton.j.kehoe at boeing dot com>
22
# Contributor : wiz64 <wiz64 dot com>
33
pkgname=config-file-validator
4-
pkgver=1.11.0
4+
pkgver=2.1.0
55
pkgrel=1
6-
pkgdesc="A tool to validate the syntax of configuration files"
6+
pkgdesc="A tool to validate the syntax and schema of configuration files"
77
arch=('x86_64')
88
url="https://github.com/Boeing/config-file-validator"
99
license=('Apache 2.0')
1010
depends=('glibc')
11-
makedepends=('go>=1.25' 'git' 'sed')
11+
makedepends=('go>=1.26.2' 'git' 'sed')
1212
source=("git+https://github.com/Boeing/config-file-validator.git")
1313
sha256sums=('SKIP')
1414
md5sums=('SKIP')

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ optional flags:
162162
-globbing
163163
If globbing flag is set, check for glob patterns in the arguments.
164164
-groupby string
165-
Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports
165+
Group output by filetype, directory, pass-fail, error-type. Supported for Standard and JSON reports
166166
-no-schema
167167
Disable all schema validation. Only syntax is checked.
168168
Cannot be used with --require-schema, --schema-map, or --schemastore.
@@ -289,7 +289,7 @@ validator --reporter=json:output.json --reporter=standard /path/to/search
289289

290290
### Group report output
291291

292-
Group the report output by file type, directory, or pass-fail. Supports one or more groupings.
292+
Group the report output by file type, directory, pass-fail, or error-type. Supports one or more groupings.
293293

294294
```shell
295295
validator -groupby filetype

cmd/validator/testdata/groupby.txtar

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@ stdout 'Summary'
1111
exec validator -groupby=pass-fail files
1212
stdout 'Passed'
1313

14+
# Group by error-type (all valid files → Passed group)
15+
exec validator -groupby=error-type files
16+
stdout 'Passed'
17+
18+
# Group by error-type with failures
19+
! exec validator -groupby=error-type mixed
20+
stdout 'syntax'
21+
stdout 'Passed'
22+
1423
# Double grouping
1524
exec validator -groupby=filetype,directory files
1625
stdout 'json'
@@ -39,3 +48,7 @@ stdout 'totalPassed'
3948
{"key": "value"}
4049
-- files/good.yaml --
4150
key: value
51+
-- mixed/good.json --
52+
{"key": "value"}
53+
-- mixed/bad.json --
54+
{"key": value}

cmd/validator/validator.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,7 +173,7 @@ func getFlags(args []string) (validatorConfig, error) {
173173
excludeFileTypesPtr = flagSet.String("exclude-file-types", "", "A comma separated list of file types to ignore")
174174
fileTypesPtr = flagSet.String("file-types", "", "A comma separated list of file types to validate")
175175
versionPtr = flagSet.Bool("version", false, "Version prints the release version of validator")
176-
groupOutputPtr = flagSet.String("groupby", "", "Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports")
176+
groupOutputPtr = flagSet.String("groupby", "", "Group output by filetype, directory, pass-fail, error-type. Supported for Standard and JSON reports")
177177
quietPtr = flagSet.Bool("quiet", false, "If quiet flag is set. It doesn't print any output to stdout.")
178178
globbingPrt = flagSet.Bool("globbing", false, "If globbing flag is set, check for glob patterns in the arguments.")
179179
requireSchemaPtr = flagSet.Bool("require-schema", false,
@@ -321,14 +321,14 @@ func validateReporterConf(conf map[string]string, groupBy *string) error {
321321
func validateGroupByConf(groupBy *string) error {
322322
groupByCleanString := cleanString("groupby")
323323
groupByUserInput := strings.Split(groupByCleanString, ",")
324-
groupByAllowedValues := []string{"filetype", "directory", "pass-fail"}
324+
groupByAllowedValues := []string{"filetype", "directory", "pass-fail", "error-type"}
325325
seenValues := make(map[string]bool)
326326

327327
// Check that the groupby values are valid and not duplicates
328328
if groupBy != nil && isFlagSet("groupby") {
329329
for _, groupBy := range groupByUserInput {
330330
if !slices.Contains(groupByAllowedValues, groupBy) {
331-
return errors.New("wrong parameter value for groupby, only supports filetype, directory, pass-fail")
331+
return errors.New("wrong parameter value for groupby, only supports filetype, directory, pass-fail, error-type")
332332
}
333333
if _, ok := seenValues[groupBy]; ok {
334334
return errors.New("wrong parameter value for groupby, duplicate values are not allowed")

index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ optional flags:
178178
-globbing
179179
If globbing flag is set, check for glob patterns in the arguments.
180180
-groupby string
181-
Group output by filetype, directory, pass-fail. Supported for Standard and JSON reports
181+
Group output by filetype, directory, pass-fail, error-type. Supported for Standard and JSON reports
182182
-no-schema
183183
Disable all schema validation. Only syntax is checked.
184184
Cannot be used with --require-schema, --schema-map, or --schemastore.
@@ -305,7 +305,7 @@ validator --reporter=json:output.json --reporter=standard /path/to/search
305305

306306
### Group report output
307307

308-
Group the report output by file type, directory, or pass-fail. Supports one or more groupings.
308+
Group the report output by file type, directory, pass-fail, or error-type. Supports one or more groupings.
309309

310310
```shell
311311
validator -groupby filetype

pkg/cli/cli.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -117,10 +117,21 @@ func (c CLI) Run() (int, error) {
117117
return 1, fmt.Errorf("unable to read file: %w", err)
118118
}
119119

120-
isValid, err := fileToValidate.FileType.Validator.ValidateSyntax(fileContent)
120+
isValid, syntaxErr := fileToValidate.FileType.Validator.ValidateSyntax(fileContent)
121121

122+
var schemaErr error
122123
if isValid {
123-
isValid, err = validateSchema(fileToValidate.FileType.Validator, fileContent, fileToValidate.Path)
124+
isValid, schemaErr = validateSchema(fileToValidate.FileType.Validator, fileContent, fileToValidate.Path)
125+
}
126+
127+
err = syntaxErr
128+
errorType := ""
129+
if syntaxErr != nil {
130+
errorType = "syntax"
131+
}
132+
if schemaErr != nil {
133+
err = schemaErr
134+
errorType = "schema"
124135
}
125136

126137
var line, col int
@@ -133,9 +144,11 @@ func (c CLI) Run() (int, error) {
133144
var validationErrors []string
134145
var se *validator.SchemaErrors
135146
if errors.As(err, &se) {
136-
validationErrors = se.Errors()
147+
for _, e := range se.Errors() {
148+
validationErrors = append(validationErrors, "schema: "+e)
149+
}
137150
} else if err != nil {
138-
validationErrors = []string{err.Error()}
151+
validationErrors = []string{"syntax: " + err.Error()}
139152
}
140153

141154
report := reporter.Report{
@@ -144,6 +157,7 @@ func (c CLI) Run() (int, error) {
144157
IsValid: isValid,
145158
ValidationError: err,
146159
ValidationErrors: validationErrors,
160+
ErrorType: errorType,
147161
IsQuiet: Quiet,
148162
StartLine: line,
149163
StartColumn: col,

pkg/cli/group_output.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,21 @@ func GroupByPassFail(reports []reporter.Report) map[string][]reporter.Report {
4343
return reportByPassOrFail
4444
}
4545

46+
// Group Reports by Error Type (syntax, schema, or passed)
47+
func GroupByErrorType(reports []reporter.Report) map[string][]reporter.Report {
48+
reportByErrorType := make(map[string][]reporter.Report)
49+
50+
for _, report := range reports {
51+
key := report.ErrorType
52+
if key == "" {
53+
key = "Passed"
54+
}
55+
reportByErrorType[key] = append(reportByErrorType[key], report)
56+
}
57+
58+
return reportByErrorType
59+
}
60+
4661
// Group Reports by Directory
4762
func GroupByDirectory(reports []reporter.Report) map[string][]reporter.Report {
4863
reportByDirectory := make(map[string][]reporter.Report)
@@ -79,6 +94,8 @@ func GroupBySingle(reports []reporter.Report, groupBy string) (map[string][]repo
7994
groupReport = GroupByFileType(reports)
8095
case "directory":
8196
groupReport = GroupByDirectory(reports)
97+
case "error-type":
98+
groupReport = GroupByErrorType(reports)
8299
default:
83100
return nil, fmt.Errorf("unable to group by %s", groupBy)
84101
}

pkg/cli/group_output_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ func Test_ValidGroupOutput(t *testing.T) {
2121
{"single directory", []string{"directory"}},
2222
{"single filetype", []string{"filetype"}},
2323
{"single pass-fail", []string{"pass-fail"}},
24+
{"single error-type", []string{"error-type"}},
2425
{"double directory,pass-fail", []string{"directory", "pass-fail"}},
2526
{"double filetype,directory", []string{"filetype", "directory"}},
2627
{"double pass-fail,filetype", []string{"pass-fail", "filetype"}},
@@ -132,6 +133,22 @@ func Test_GroupByFileType(t *testing.T) {
132133
require.Len(t, result["json"], 1)
133134
}
134135

136+
func Test_GroupByErrorType(t *testing.T) {
137+
t.Parallel()
138+
139+
reports := []reporter.Report{
140+
{FileName: "good.json", FilePath: "/path/good.json", IsValid: true},
141+
{FileName: "bad_syntax.json", FilePath: "/path/bad_syntax.json", IsValid: false, ErrorType: "syntax"},
142+
{FileName: "bad_schema.json", FilePath: "/path/bad_schema.json", IsValid: false, ErrorType: "schema"},
143+
{FileName: "bad_schema2.yaml", FilePath: "/path/bad_schema2.yaml", IsValid: false, ErrorType: "schema"},
144+
}
145+
146+
result := GroupByErrorType(reports)
147+
require.Len(t, result["Passed"], 1)
148+
require.Len(t, result["syntax"], 1)
149+
require.Len(t, result["schema"], 2)
150+
}
151+
135152
func Test_GroupByPassFail(t *testing.T) {
136153
t.Parallel()
137154

pkg/reporter/reporter.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ type Report struct {
88
IsValid bool
99
ValidationError error
1010
ValidationErrors []string
11+
ErrorType string
1112
IsQuiet bool
1213
StartLine int
1314
StartColumn int

0 commit comments

Comments
 (0)