From 186fe37bf8ca293939f4ca279669caf7024f7a54 Mon Sep 17 00:00:00 2001 From: Elliot Shepherd Date: Wed, 6 Feb 2019 09:21:39 +1100 Subject: [PATCH] add code-climate output format Just the minimum of the format, to support GitLab CI Code Quality - https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html --- .golangci.example.yml | 2 +- README.md | 4 +-- pkg/commands/run.go | 2 ++ pkg/config/config.go | 2 ++ pkg/printers/codeclimate.go | 56 +++++++++++++++++++++++++++++++++++++ 5 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 pkg/printers/codeclimate.go diff --git a/.golangci.example.yml b/.golangci.example.yml index 54234d3b..0bb7444e 100644 --- a/.golangci.example.yml +++ b/.golangci.example.yml @@ -49,7 +49,7 @@ run: # output configuration options output: - # colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number" + # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" format: colored-line-number # print lines of code with issue, default is true diff --git a/README.md b/README.md index a1f23058..f897e17b 100644 --- a/README.md +++ b/README.md @@ -436,7 +436,7 @@ Usage: golangci-lint run [flags] Flags: - --out-format string Format of output: colored-line-number|line-number|json|tab|checkstyle (default "colored-line-number") + --out-format string Format of output: colored-line-number|line-number|json|tab|checkstyle|code-climate (default "colored-line-number") --print-issued-lines Print lines of code with issue (default true) --print-linter-name Print linter name in issue line (default true) --issues-exit-code int Exit code when issues were found (default 1) @@ -573,7 +573,7 @@ run: # output configuration options output: - # colored-line-number|line-number|json|tab|checkstyle, default is "colored-line-number" + # colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number" format: colored-line-number # print lines of code with issue, default is true diff --git a/pkg/commands/run.go b/pkg/commands/run.go index 407b0a4d..3bb569a5 100644 --- a/pkg/commands/run.go +++ b/pkg/commands/run.go @@ -363,6 +363,8 @@ func (e *Executor) createPrinter() (printers.Printer, error) { p = printers.NewTab(e.cfg.Output.PrintLinterName, e.log.Child("tab_printer")) case config.OutFormatCheckstyle: p = printers.NewCheckstyle() + case config.OutFormatCodeClimate: + p = printers.NewCodeClimate() default: return nil, fmt.Errorf("unknown output format %s", format) } diff --git a/pkg/config/config.go b/pkg/config/config.go index 82b9d4f6..cb5b4dd8 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -10,6 +10,7 @@ const ( OutFormatColoredLineNumber = "colored-line-number" OutFormatTab = "tab" OutFormatCheckstyle = "checkstyle" + OutFormatCodeClimate = "code-climate" ) var OutFormats = []string{ @@ -18,6 +19,7 @@ var OutFormats = []string{ OutFormatJSON, OutFormatTab, OutFormatCheckstyle, + OutFormatCodeClimate, } type ExcludePattern struct { diff --git a/pkg/printers/codeclimate.go b/pkg/printers/codeclimate.go new file mode 100644 index 00000000..0faebe32 --- /dev/null +++ b/pkg/printers/codeclimate.go @@ -0,0 +1,56 @@ +package printers + +import ( + "context" + "crypto/md5" + "encoding/json" + "fmt" + + "github.com/golangci/golangci-lint/pkg/logutils" + "github.com/golangci/golangci-lint/pkg/result" +) + +// CodeClimateIssue is a subset of the Code Climate spec - https://github.com/codeclimate/spec/blob/master/SPEC.md#data-types +// It is just enough to support GitLab CI Code Quality - https://docs.gitlab.com/ee/user/project/merge_requests/code_quality.html +type CodeClimateIssue struct { + Description string `json:"description"` + Fingerprint string `json:"fingerprint"` + Location struct { + Path string `json:"path"` + Lines struct { + Begin int `json:"begin"` + } `json:"lines"` + } `json:"location"` +} + +type CodeClimate struct { +} + +func NewCodeClimate() *CodeClimate { + return &CodeClimate{} +} + +func (p CodeClimate) Print(ctx context.Context, issues <-chan result.Issue) error { + allIssues := []CodeClimateIssue{} + for i := range issues { + var issue CodeClimateIssue + issue.Description = i.FromLinter + ": " + i.Text + issue.Location.Path = i.Pos.Filename + issue.Location.Lines.Begin = i.Pos.Line + + // Need a checksum of the issue, so we use MD5 of the filename, text, and first line of source + hash := md5.New() + _, _ = hash.Write([]byte(i.Pos.Filename + i.Text + i.SourceLines[0])) + issue.Fingerprint = fmt.Sprintf("%X", hash.Sum(nil)) + + allIssues = append(allIssues, issue) + } + + outputJSON, err := json.Marshal(allIssues) + if err != nil { + return err + } + + fmt.Fprint(logutils.StdOut, string(outputJSON)) + return nil +}