Skip to content

Commit

Permalink
Large cleanup and tuneup of messages
Browse files Browse the repository at this point in the history
Various messages fixed, small glitches resolved.
  • Loading branch information
daveshanley committed Jul 21, 2022
1 parent b7388aa commit 8bd63dc
Show file tree
Hide file tree
Showing 31 changed files with 190 additions and 113 deletions.
1 change: 1 addition & 0 deletions cmd/dashboard.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ func GetDashboardCommand() *cobra.Command {
}

dash := cui.CreateDashboard(resultSet, specIndex, specInfo)
dash.Version = Version
dash.Render()
return nil
},
Expand Down
2 changes: 1 addition & 1 deletion cmd/html_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func GetHTMLReportCommand() *cobra.Command {

return &cobra.Command{
SilenceUsage: true,
SilenceErrors: true,
SilenceErrors: false,
Use: "html-report",
Short: "Generate an HTML report of a linting run",
Long: "Generate an interactive and useful HTML report. Default output " +
Expand Down
60 changes: 45 additions & 15 deletions cmd/lint.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/daveshanley/vacuum/model"
"github.com/daveshanley/vacuum/motor"
"github.com/daveshanley/vacuum/rulesets"
"github.com/dustin/go-humanize"
"github.com/pterm/pterm"
"github.com/spf13/cobra"
"io/ioutil"
Expand Down Expand Up @@ -35,6 +36,7 @@ func GetLintCommand() *cobra.Command {
rulesetFlag, _ := cmd.Flags().GetString("ruleset")
silent, _ := cmd.Flags().GetBool("silent")
functionsFlag, _ := cmd.Flags().GetString("functions")
failSeverityFlag, _ := cmd.Flags().GetString("fail-severity")

if !silent {
PrintBanner()
Expand Down Expand Up @@ -112,10 +114,14 @@ func GetLintCommand() *cobra.Command {
fi, _ := os.Stat(args[0])
duration := time.Since(start)

warnings := resultSet.GetWarnCount()
errors := resultSet.GetErrorCount()
informs := resultSet.GetInfoCount()

if !detailsFlag {
RenderSummary(resultSet, args, silent)
RenderTime(timeFlag, duration, fi)
return nil
return CheckFailureSeverity(failSeverityFlag, errors, warnings, informs)
}

var cats []*model.RuleCategory
Expand Down Expand Up @@ -164,9 +170,9 @@ func GetLintCommand() *cobra.Command {
pterm.Println()
} // Blank line

RenderSummary(resultSet, args, silent)
RenderTime(timeFlag, duration, fi)

return nil
return CheckFailureSeverity(failSeverityFlag, errors, warnings, informs)
},
}

Expand All @@ -175,6 +181,7 @@ func GetLintCommand() *cobra.Command {
cmd.Flags().BoolP("errors", "e", false, "Show errors only")
cmd.Flags().StringP("category", "c", "", "Show a single category of results")
cmd.Flags().BoolP("silent", "x", false, "Show nothing except the result.")
cmd.Flags().StringP("fail-severity", "n", "error", "Results of this level or above will trigger a failure exit code")

return cmd
}
Expand All @@ -187,13 +194,25 @@ func processResults(results []*model.RuleFunctionResult, specData []string, snip
if !snippets {
tableData = [][]string{{"Line / Column", "Severity", "Message", "Path"}}
}
for _, r := range results {
for i, r := range results {

if i > 200 {
tableData = append(tableData, []string{"", "", pterm.LightRed(fmt.Sprintf("...%d "+
"more violations not rendered.", len(results)-200)), ""})
break
}
if snippets {
tableData = [][]string{{"Line / Column", "Severity", "Message", "Path"}}
}
start := fmt.Sprintf("(%v:%v)", r.StartNode.Line, r.StartNode.Column)

startLine := 0
startCol := 0
if r.StartNode != nil {
startLine = r.StartNode.Line
}
if r.StartNode != nil {
startCol = r.StartNode.Column
}
start := fmt.Sprintf("(%v:%v)", startLine, startCol)
m := r.Message
p := r.Path
if len(r.Path) > 60 {
Expand Down Expand Up @@ -228,6 +247,7 @@ func processResults(results []*model.RuleFunctionResult, specData []string, snip
_ = pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
renderCodeSnippet(r, specData)
}
i++
}

if !snippets && !silent {
Expand Down Expand Up @@ -271,8 +291,8 @@ func RenderSummary(rs *model.RuleResultSet, args []string, silent bool) {

if len(errors) > 0 || len(warn) > 0 || len(info) > 0 {

tableData = append(tableData, []string{cat.Name, fmt.Sprintf("%d", len(errors)),
fmt.Sprintf("%d", len(warn)), fmt.Sprintf("%d", len(info))})
tableData = append(tableData, []string{cat.Name, fmt.Sprintf("%v", humanize.Comma(int64(len(errors)))),
fmt.Sprintf("%v", humanize.Comma(int64(len(warn)))), fmt.Sprintf("%v", humanize.Comma(int64(len(info))))})
}

}
Expand All @@ -281,24 +301,34 @@ func RenderSummary(rs *model.RuleResultSet, args []string, silent bool) {
if !silent {
pterm.DefaultTable.WithHasHeader().WithData(tableData).Render()
pterm.Println()
pterm.Printf(">> run 'vacuum %s -d' to see full details", args[0])
pterm.Println()
pterm.Println()
}
}

if rs.GetErrorCount() > 0 {
errors := rs.GetErrorCount()
warnings := rs.GetWarnCount()
informs := rs.GetInfoCount()
errorsHuman := humanize.Comma(int64(rs.GetErrorCount()))
warningsHuman := humanize.Comma(int64(rs.GetWarnCount()))
informsHuman := humanize.Comma(int64(rs.GetInfoCount()))

if errors > 0 {
pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgRed)).WithMargin(10).Printf(
"Linting failed with %d errors", rs.GetErrorCount())
"Linting failed with %v errors, %v warnings and %v informs", errorsHuman, warningsHuman, informsHuman)
return
}
if rs.GetWarnCount() > 0 {
if warnings > 0 {
pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgYellow)).WithMargin(10).Printf(
"Linting passed, but with %d warnings", rs.GetWarnCount())
"Linting passed, but with %v warnings and %v informs", warningsHuman, informsHuman)
return
}

if informs > 0 {
pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgGreen)).WithMargin(10).Printf(
"Linting passed, %v informs reported", informsHuman)
}

pterm.DefaultHeader.WithBackgroundStyle(pterm.NewStyle(pterm.BgGreen)).WithMargin(10).Println(
"Linting passed, great job!")
"Linting passed, A perfect score! well done!")

}
23 changes: 23 additions & 0 deletions cmd/shared_functions.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,26 @@ func LoadCustomFunctions(functionsFlag string) (map[string]model.RuleFunction, e
}
return nil, nil
}

func CheckFailureSeverity(failSeverityFlag string, errors int, warnings int, informs int) error {
if failSeverityFlag != "error" {
switch failSeverityFlag {
case "warn":
if errors > 0 && warnings > 0 {
return fmt.Errorf("failed linting, with %d errors and %d warnings", errors, warnings)
}
return nil
case "info":
if errors > 0 && warnings > 0 && informs > 0 {
return fmt.Errorf("failed linting, with %d errors, %d warnings and %d informs",
errors, warnings, informs)
}
return nil
}
} else {
if errors > 0 {
return fmt.Errorf("failed linting, with %d errors", errors)
}
}
return nil
}
5 changes: 3 additions & 2 deletions cui/dashboard.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cui

import (
"fmt"
"github.com/daveshanley/vacuum/model"
ui "github.com/gizak/termui/v3"
"github.com/gizak/termui/v3/widgets"
Expand Down Expand Up @@ -32,6 +33,7 @@ type Dashboard struct {
violationViewActive bool
helpViewActive bool
uiEvents <-chan ui.Event
Version string
}

func CreateDashboard(resultSet *model.RuleResultSet, index *index.SpecIndex, info *datamodel.SpecInfo) *Dashboard {
Expand Down Expand Up @@ -203,8 +205,7 @@ func (dash *Dashboard) setGrid() {

p := widgets.NewParagraph()
// todo: bring in correct versioning.

p.Text = "vacuum v0.0.1: " +
p.Text = fmt.Sprintf("vacuum %v: ", dash.Version) +
"[Select Category](fg:white,bg:clear,md:bold) = <Tab>,\u2B05\uFE0F\u27A1\uFE0F/S,X | " +
"[Change Rule](fg:white,bg:clear,md:bold) = \u2B06\u2B07/A,Z | " +
"[Select / Leave Rule](fg:white,bg:clear,md:bold) = <Enter> / <Esc>"
Expand Down
6 changes: 3 additions & 3 deletions functions/core/alphabetical.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ func (a Alphabetical) RunRule(nodes []*yaml.Node, context model.RuleFunctionCont

if keyedBy == "" {
results = append(results, model.RuleFunctionResult{
Message: fmt.Sprintf("%s: '%s' is a map/object. %s", context.Rule.Description,
Message: fmt.Sprintf("%s: `%s` is a map/object. %s", context.Rule.Description,
node.Value, a.GetSchema().ErrorMessage),
StartNode: node,
EndNode: node,
Expand Down Expand Up @@ -165,7 +165,7 @@ func compareStringArray(strArr []string, context model.RuleFunctionContext) []mo
s := strings.Compare(strArr[x], strArr[x+1])
if s > 0 {
results = append(results, model.RuleFunctionResult{
Message: fmt.Sprintf("%s: '%s' must be placed before '%s' (alphabetical)",
Message: fmt.Sprintf("%s: `%s` must be placed before `%s` (alphabetical)",
context.Rule.Description,
strArr[x+1], strArr[x]),
})
Expand All @@ -191,7 +191,7 @@ func (a Alphabetical) checkNumberArrayIsSorted(arr *yaml.Node, context model.Rul
}
}

errmsg := "%s: '%v' is less than '%v', they need to be swapped (numerical ordering)"
errmsg := "%s: `%v` is less than `%v`, they need to be swapped (numerical ordering)"

if len(floatArray) > 0 {
if !sort.Float64sAreSorted(floatArray) {
Expand Down
14 changes: 7 additions & 7 deletions functions/core/pattern.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,22 +93,22 @@ func (p Pattern) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
rx, err := p.getPatternFromCache(p.match, context.Rule)
if err != nil {
results = append(results, model.RuleFunctionResult{
Message: fmt.Sprintf("%s: '%s' cannot be compiled into a regular expression: %s",
Message: fmt.Sprintf("%s: `%s` cannot be compiled into a regular expression: %s",
context.Rule.Description, p.match, err.Error()),
StartNode: node,
EndNode: node,
Path: pathValue,
Path: fmt.Sprintf("%s.%s", pathValue, currentField),
Rule: context.Rule,
})
} else {
pathValue = fmt.Sprintf("%s.%s", pathValue, currentField)
if !rx.MatchString(node.Value) {
results = append(results, model.RuleFunctionResult{
Message: fmt.Sprintf("%s: '%s' does not match the expression '%s'", context.Rule.Description,
Message: fmt.Sprintf("%s: `%s` does not match the expression `%s`", context.Rule.Description,
node.Value, p.match),
StartNode: node,
EndNode: node,
Path: pathValue,
Path: fmt.Sprintf("%s.%s", pathValue, currentField),
Rule: context.Rule,
})
}
Expand All @@ -124,16 +124,16 @@ func (p Pattern) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
context.Rule.Description, err.Error()),
StartNode: node,
EndNode: node,
Path: pathValue,
Path: fmt.Sprintf("%s.%s", pathValue, currentField),
Rule: context.Rule,
})
} else {
if rx.MatchString(node.Value) {
results = append(results, model.RuleFunctionResult{
Message: fmt.Sprintf("%s: matches the expression '%s'", context.Rule.Description, p.notMatch),
Message: fmt.Sprintf("%s: matches the expression `%s`", context.Rule.Description, p.notMatch),
StartNode: node,
EndNode: node,
Path: pathValue,
Path: fmt.Sprintf("%s.%s", pathValue, currentField),
Rule: context.Rule,
})
}
Expand Down
2 changes: 1 addition & 1 deletion functions/core/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (sch Schema) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)
if _, ok := forceValidation.(bool); ok {

r := model.BuildFunctionResultString(fmt.Sprintf("%s: %s", context.Rule.Description,
fmt.Sprintf("'%s', is missing and is required", context.RuleAction.Field)))
fmt.Sprintf("`%s`, is missing and is required", context.RuleAction.Field)))
r.StartNode = node
r.EndNode = node.Content[len(node.Content)-1]
r.Rule = context.Rule
Expand Down
2 changes: 1 addition & 1 deletion functions/core/schema_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,6 @@ func TestOpenAPISchema_MissingFieldForceValidation(t *testing.T) {
res := def.RunRule(nodes, ctx)

assert.Len(t, res, 1)
assert.Equal(t, "schema must be valid: 'lolly', is missing and is required", res[0].Message)
assert.Equal(t, "schema must be valid: `lolly`, is missing and is required", res[0].Message)

}
2 changes: 1 addition & 1 deletion functions/core/truthy.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (t *Truthy) RunRule(nodes []*yaml.Node, context model.RuleFunctionContext)

if !utils.IsNodeMap(fieldNode) && !utils.IsNodeArray(fieldNodeValue) {
results = append(results, model.RuleFunctionResult{
Message: fmt.Sprintf("%s: '%s' must be set", context.Rule.Description, context.RuleAction.Field),
Message: fmt.Sprintf("%s: `%s` must be set", context.Rule.Description, context.RuleAction.Field),
StartNode: node,
EndNode: node.Content[len(node.Content)-1],
Path: pathValue,
Expand Down
2 changes: 1 addition & 1 deletion functions/openapi/no_eval_descriptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func (ne NoEvalInDescriptions) RunRule(nodes []*yaml.Node, context model.RuleFun
endNode := desc.Node

results = append(results, model.RuleFunctionResult{
Message: fmt.Sprintf("description contains content with '%s', forbidden", pattern),
Message: fmt.Sprintf("description contains content with `%s`, forbidden", pattern),
StartNode: startNode,
EndNode: endNode,
Path: desc.Path,
Expand Down
20 changes: 16 additions & 4 deletions functions/openapi/oas_schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,17 +80,29 @@ func (os OASSchema) RunRule(nodes []*yaml.Node, context model.RuleFunctionContex

//validate using faster, more accurate resolver.
if validationError := schema.Validate(*info.SpecJSON); validationError != nil {
failure := validationError.(*jsonschema.ValidationError)
for _, fail := range failure.Causes {

if failure, ok := validationError.(*jsonschema.ValidationError); ok {
for _, fail := range failure.Causes {
results = append(results, model.RuleFunctionResult{
Message: fmt.Sprintf("OpenAPI specification is invalid: %s %v", fail.KeywordLocation,
fail.Message),
StartNode: nodes[0],
EndNode: nodes[0],
Path: "$",
Rule: context.Rule,
})
}
}
if failure, ok := validationError.(*jsonschema.InvalidJSONTypeError); ok {
results = append(results, model.RuleFunctionResult{
Message: fmt.Sprintf("OpenAPI specification is invalid: %s %v", fail.KeywordLocation,
fail.Message),
Message: fmt.Sprintf("OpenAPI specification is invalid: %v", failure.Error()),
StartNode: nodes[0],
EndNode: nodes[0],
Path: "$",
Rule: context.Rule,
})
}

}
return results
}

0 comments on commit 8bd63dc

Please sign in to comment.