Skip to content

Commit

Permalink
feat(linting): Add support for linting decK files
Browse files Browse the repository at this point in the history
  • Loading branch information
mheap committed Jul 24, 2023
1 parent b1fde70 commit 5823a9b
Show file tree
Hide file tree
Showing 4 changed files with 319 additions and 1 deletion.
166 changes: 166 additions & 0 deletions cmd/file_lint.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,166 @@
package cmd

import (
"errors"
"fmt"
"io/ioutil"
"log"
"strings"

"github.com/daveshanley/vacuum/motor"
"github.com/daveshanley/vacuum/rulesets"
"github.com/kong/go-apiops/filebasics"
"github.com/kong/go-apiops/logbasics"
"github.com/spf13/cobra"
)

var (
cmdLintInputFilename string
cmdLintInputRuleset string
)

func executeLint(cmd *cobra.Command, _ []string) error {

Check failure on line 23 in cmd/file_lint.go

View workflow job for this annotation

GitHub Actions / test

File is not `gofumpt`-ed (gofumpt)
severityList := map[string]int{
"hint": 0,
"info": 1,
"warn": 2,
"error": 3,
}

verbosity, _ := cmd.Flags().GetInt("verbose")
logbasics.Initialize(log.LstdFlags, verbosity)

inputFilename, err := cmd.Flags().GetString("state")

Check failure on line 35 in cmd/file_lint.go

View workflow job for this annotation

GitHub Actions / test

File is not `gofumpt`-ed (gofumpt)
if err != nil {
return fmt.Errorf("failed getting cli argument 'state'; %w", err)
}

minimumSeverity, err := cmd.Flags().GetString("fail-severity")

Check failure on line 41 in cmd/file_lint.go

View workflow job for this annotation

GitHub Actions / test

File is not `gofumpt`-ed (gofumpt)
if err != nil {
return fmt.Errorf("failed getting cli argument 'fail-severity'; %w", err)
}

onlyFailures, err := cmd.Flags().GetBool("display-only-failures")

if err != nil {
return fmt.Errorf("failed getting cli argument 'display-only-failures'; %w", err)
}

var outputFormat string
{
outputFormat, err = cmd.Flags().GetString("format")
if err != nil {
return fmt.Errorf("failed getting cli argument 'format'; %w", err)
}
outputFormat = strings.ToUpper(outputFormat)
}

inputRuleset, err := cmd.Flags().GetString("ruleset")

if err != nil || inputRuleset == "" {
return fmt.Errorf("failed getting cli argument 'ruleset';")
}

ruleSetBytes, err := ioutil.ReadFile(inputRuleset)
if err != nil {
panic(err.Error())
}

customRuleSet, rsErr := rulesets.CreateRuleSetFromData(ruleSetBytes)

if rsErr != nil {
panic(err.Error())
}

specBytes, err := ioutil.ReadFile(inputFilename)
if err != nil {
panic(err.Error())
}

ruleSetResults := motor.ApplyRulesToRuleSet(&motor.RuleSetExecution{
RuleSet: customRuleSet,
Spec: specBytes,
SkipDocumentCheck: true,
})

failingCount := 0
totalCount := 0

var lintResults []map[string]interface{}
for _, x := range ruleSetResults.Results {

if onlyFailures && (x.Rule.Severity != "error") {
continue
}

if severityList[x.Rule.Severity] >= severityList[minimumSeverity] {
failingCount++
}

totalCount++

lintResults = append(lintResults, map[string]interface{}{
"message": x.Message,
"path": x.Rule.Given,
"line": x.StartNode.Line,
"column": x.StartNode.Column,
"severity": x.Rule.Severity,
})
}

lintErrs := map[string]interface{}{
"total_count": totalCount,
"fail_count": failingCount,
"results": lintResults,
}

if outputFormat == "DEFAULT" {
if totalCount > 0 {
fmt.Printf("Linting Violations: %d\n", totalCount)
fmt.Printf("Failures: %d\n\n", failingCount)
for _, violation := range lintErrs["results"].([]map[string]interface{}) {
fmt.Printf("[%d:%d] %s\n", violation["line"], violation["column"], violation["message"])
}
}
} else {
filebasics.WriteSerializedFile("-", lintErrs, filebasics.OutputFormat(outputFormat))

Check failure on line 129 in cmd/file_lint.go

View workflow job for this annotation

GitHub Actions / test

Error return value of `filebasics.WriteSerializedFile` is not checked (errcheck)
}

if failingCount > 0 {
// We don't want to print the error here as they're already output above
// But we _do_ want to set an exit code of failure
cmd.SilenceErrors = true
return errors.New("linting errors detected")
}

return nil
}

//
//
// Define the CLI data for the lint command
//
//

func newLintCmd() *cobra.Command {
lintCmd := &cobra.Command{
Use: "lint [flags] lint-file",
Short: "Short description here",
Long: `Long description Here`,
RunE: executeLint,
}

lintCmd.Flags().StringVarP(&cmdLintInputFilename, "state", "s", "-",
"decK file to process. Use - to read from stdin.")
lintCmd.Flags().StringVarP(&cmdLintInputRuleset, "ruleset", "r", "",
"Ruleset to apply to the state file.")
lintCmd.Flags().StringP("format", "", "default", "output format: default, "+
string(filebasics.OutputFormatJSON)+" or "+string(filebasics.OutputFormatYaml))
lintCmd.Flags().StringP("fail-severity", "", "warn", "minimum severity to fail on")
lintCmd.Flags().BoolP("display-only-failures", "D", false, "only display failures")

return lintCmd
}
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ It can be used to export, import, or sync entities to Kong.`,
fileCmd.AddCommand(newMergeCmd())
fileCmd.AddCommand(newPatchCmd())
fileCmd.AddCommand(newOpenapi2KongCmd())
fileCmd.AddCommand(newLintCmd())
}
return rootCmd
}
Expand Down
28 changes: 27 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -33,13 +33,23 @@ require (
)

require (
atomicgo.dev/cursor v0.1.1 // indirect
atomicgo.dev/keyboard v0.2.9 // indirect
atomicgo.dev/schedule v0.0.2 // indirect
github.com/Kong/go-diff v1.2.2 // indirect
github.com/adrg/strutil v0.2.3 // indirect
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/containerd/console v1.0.3 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dprotaso/go-yit v0.0.0-20191028211022-135eb7262960 // indirect
github.com/daveshanley/vacuum v0.2.7 // indirect
github.com/dlclark/regexp2 v1.4.0 // indirect
github.com/dprotaso/go-yit v0.0.0-20220510233725-9ba8df137936 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/getkin/kin-openapi v0.108.0 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/gizak/termui/v3 v3.1.0 // indirect
github.com/go-logr/logr v1.2.3 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
Expand All @@ -49,6 +59,7 @@ require (
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/gookit/color v1.5.3 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
Expand All @@ -58,20 +69,29 @@ require (
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kong/semver/v4 v4.0.1 // indirect
github.com/lithammer/fuzzysearch v1.1.8 // indirect
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/mozillazg/go-slugify v0.2.0 // indirect
github.com/mozillazg/go-unidecode v0.2.0 // indirect
github.com/nsf/termbox-go v0.0.0-20190121233118-02980233997d // indirect
github.com/pb33f/libopenapi v0.9.6 // indirect
github.com/pb33f/libopenapi-validator v0.0.10 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
github.com/pterm/pterm v0.12.62 // indirect
github.com/rivo/uniseg v0.4.4 // indirect
github.com/santhosh-tekuri/jsonschema/v5 v5.3.0 // indirect
github.com/satori/go.uuid v1.2.0 // indirect
github.com/shoenig/go-m1cpu v0.1.6 // indirect
github.com/spf13/afero v1.9.5 // indirect
Expand All @@ -86,11 +106,17 @@ require (
github.com/vmware-labs/yaml-jsonpath v0.3.2 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.uber.org/atomic v1.11.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.10.0 // indirect
golang.org/x/sys v0.9.0 // indirect
golang.org/x/term v0.8.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/protobuf v1.30.0 // indirect
Expand Down
Loading

0 comments on commit 5823a9b

Please sign in to comment.