diff --git a/src/pkg/message/message.go b/src/pkg/message/message.go index 206176813f..68bf711219 100644 --- a/src/pkg/message/message.go +++ b/src/pkg/message/message.go @@ -327,7 +327,7 @@ func Table(header []string, data [][]string) { // preventing future characters from taking on the given color // returns string as normal if color is disabled func ColorWrap(str string, attr color.Attribute) string { - if config.NoColor { + if config.NoColor || str == "" { return str } return fmt.Sprintf("\x1b[%dm%s\x1b[0m", attr, str) diff --git a/src/pkg/packager/dev.go b/src/pkg/packager/dev.go index a33a8c1a35..c967153e67 100644 --- a/src/pkg/packager/dev.go +++ b/src/pkg/packager/dev.go @@ -9,6 +9,7 @@ import ( "errors" "fmt" "os" + "path/filepath" "runtime" "github.com/defenseunicorns/pkg/helpers/v2" @@ -19,6 +20,7 @@ import ( "github.com/defenseunicorns/zarf/src/pkg/packager/filters" "github.com/defenseunicorns/zarf/src/pkg/packager/lint" "github.com/defenseunicorns/zarf/src/types" + "github.com/fatih/color" ) // DevDeploy creates + deploys a package in one shot @@ -126,11 +128,48 @@ func (p *Packager) Lint(ctx context.Context) error { return nil } - lint.PrintFindings(findings, types.SevWarn, p.cfg.CreateOpts.BaseDir, p.cfg.Pkg.Metadata.Name) + mapOfFindingsByPath := lint.GroupFindingsByPath(findings, types.SevWarn, p.cfg.Pkg.Metadata.Name) - if lint.HasErrors(findings) { + header := []string{"Type", "Path", "Message"} + + for _, findings := range mapOfFindingsByPath { + lintData := [][]string{} + for _, finding := range findings { + lintData = append(lintData, []string{ + colorWrapSev(finding.Severity), + message.ColorWrap(finding.YqPath, color.FgCyan), + itemizedDescription(finding.Description, finding.Item), + }) + } + var packagePathFromUser string + if helpers.IsOCIURL(findings[0].PackagePathOverride) { + packagePathFromUser = findings[0].PackagePathOverride + } else { + packagePathFromUser = filepath.Join(p.cfg.CreateOpts.BaseDir, findings[0].PackagePathOverride) + } + message.Notef("Linting package %q at %s", findings[0].PackageNameOverride, packagePathFromUser) + message.Table(header, lintData) + } + + if lint.HasSeverity(findings, types.SevErr) { return errors.New("errors during lint") } return nil } + +func itemizedDescription(description string, item string) string { + if item == "" { + return description + } + return fmt.Sprintf("%s - %s", description, item) +} + +func colorWrapSev(s types.Severity) string { + if s == types.SevErr { + return message.ColorWrap("Error", color.FgRed) + } else if s == types.SevWarn { + return message.ColorWrap("Warning", color.FgYellow) + } + return "unknown" +} diff --git a/src/pkg/packager/lint/findings.go b/src/pkg/packager/lint/findings.go new file mode 100644 index 0000000000..5b184146ed --- /dev/null +++ b/src/pkg/packager/lint/findings.go @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2021-Present The Zarf Authors + +// Package lint contains functions for verifying zarf yaml files are valid +package lint + +import ( + "github.com/defenseunicorns/pkg/helpers/v2" + "github.com/defenseunicorns/zarf/src/types" +) + +// GroupFindingsByPath groups findings by their package path +func GroupFindingsByPath(findings []types.PackageFinding, severity types.Severity, packageName string) map[string][]types.PackageFinding { + findings = helpers.RemoveMatches(findings, func(finding types.PackageFinding) bool { + return finding.Severity > severity + }) + for i := range findings { + if findings[i].PackageNameOverride == "" { + findings[i].PackageNameOverride = packageName + } + if findings[i].PackagePathOverride == "" { + findings[i].PackagePathOverride = "." + } + } + + mapOfFindingsByPath := make(map[string][]types.PackageFinding) + for _, finding := range findings { + mapOfFindingsByPath[finding.PackagePathOverride] = append(mapOfFindingsByPath[finding.PackagePathOverride], finding) + } + return mapOfFindingsByPath +} + +// HasSeverity returns true if the findings contain a severity equal to or greater than the given severity +func HasSeverity(findings []types.PackageFinding, severity types.Severity) bool { + for _, finding := range findings { + if finding.Severity <= severity { + return true + } + } + return false +} diff --git a/src/pkg/packager/lint/validator_test.go b/src/pkg/packager/lint/findings_test.go similarity index 96% rename from src/pkg/packager/lint/validator_test.go rename to src/pkg/packager/lint/findings_test.go index 4c925ea7ed..99f0b7a652 100644 --- a/src/pkg/packager/lint/validator_test.go +++ b/src/pkg/packager/lint/findings_test.go @@ -65,7 +65,7 @@ func TestGroupFindingsByPath(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - require.Equal(t, tt.want, groupFindingsByPath(tt.findings, tt.severity, tt.packageName)) + require.Equal(t, tt.want, GroupFindingsByPath(tt.findings, tt.severity, tt.packageName)) }) } } @@ -116,7 +116,7 @@ func TestHasSeverity(t *testing.T) { tt := tt t.Run(tt.name, func(t *testing.T) { t.Parallel() - require.Equal(t, tt.expected, hasSeverity(tt.findings, tt.severity)) + require.Equal(t, tt.expected, HasSeverity(tt.findings, tt.severity)) }) } } diff --git a/src/pkg/packager/lint/validator.go b/src/pkg/packager/lint/validator.go deleted file mode 100644 index 769f0b583b..0000000000 --- a/src/pkg/packager/lint/validator.go +++ /dev/null @@ -1,104 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2021-Present The Zarf Authors - -// Package lint contains functions for verifying zarf yaml files are valid -package lint - -import ( - "fmt" - "path/filepath" - - "github.com/defenseunicorns/pkg/helpers/v2" - "github.com/defenseunicorns/zarf/src/pkg/message" - "github.com/defenseunicorns/zarf/src/types" - "github.com/fatih/color" -) - -func itemizedDescription(description string, item string) string { - if item == "" { - return description - } - return fmt.Sprintf("%s - %s", description, item) -} - -func colorWrapSev(s types.Severity) string { - if s == types.SevErr { - return message.ColorWrap("Error", color.FgRed) - } else if s == types.SevWarn { - return message.ColorWrap("Warning", color.FgYellow) - } - return "unknown" -} - -func packageRelPathToUser(baseDir string, relPath string) string { - if helpers.IsOCIURL(relPath) { - return relPath - } - return filepath.Join(baseDir, relPath) -} - -// PrintFindings prints a table of the findings with the given severity or higher -func PrintFindings(findings []types.PackageFinding, severity types.Severity, baseDir string, packageName string) { - if !hasSeverity(findings, severity) { - return - } - - mapOfFindingsByPath := groupFindingsByPath(findings, severity, packageName) - - header := []string{"Type", "Path", "Message"} - - for _, findings := range mapOfFindingsByPath { - lintData := [][]string{} - for _, finding := range findings { - lintData = append(lintData, []string{ - colorWrapSev(finding.Severity), - pathColorWrap(finding.YqPath), - itemizedDescription(finding.Description, finding.Item), - }) - } - message.Notef("Linting package %q at %s", findings[0].PackageNameOverride, - packageRelPathToUser(baseDir, findings[0].PackagePathOverride)) - message.Table(header, lintData) - } -} - -func groupFindingsByPath(findings []types.PackageFinding, severity types.Severity, packageName string) map[string][]types.PackageFinding { - findings = helpers.RemoveMatches(findings, func(finding types.PackageFinding) bool { - return finding.Severity > severity - }) - for i := range findings { - if findings[i].PackageNameOverride == "" { - findings[i].PackageNameOverride = packageName - } - if findings[i].PackagePathOverride == "" { - findings[i].PackagePathOverride = "." - } - } - - mapOfFindingsByPath := make(map[string][]types.PackageFinding) - for _, finding := range findings { - mapOfFindingsByPath[finding.PackagePathOverride] = append(mapOfFindingsByPath[finding.PackagePathOverride], finding) - } - return mapOfFindingsByPath -} - -func pathColorWrap(path string) string { - if path == "" { - return "" - } - return message.ColorWrap(path, color.FgCyan) -} - -func hasSeverity(findings []types.PackageFinding, category types.Severity) bool { - for _, finding := range findings { - if finding.Severity <= category { - return true - } - } - return false -} - -// HasErrors returns true if the validator finds errors in the Zarf package -func HasErrors(findings []types.PackageFinding) bool { - return hasSeverity(findings, types.SevErr) -}