From 2923607297ed33323ec4d7b472fea2954d239043 Mon Sep 17 00:00:00 2001 From: Marco Santos Date: Fri, 26 Aug 2022 10:55:54 +0000 Subject: [PATCH] refactor: add improvements to the project --- Makefile | 3 + cmd/gitlab-code-quality/commands/transform.go | 118 +++++++++++------- model/checkstyle.go | 4 +- model/report.go | 8 +- model/report_test.go | 49 ++++++++ 5 files changed, 132 insertions(+), 50 deletions(-) create mode 100644 model/report_test.go diff --git a/Makefile b/Makefile index b2d16f2..ad75594 100644 --- a/Makefile +++ b/Makefile @@ -33,6 +33,9 @@ lint-diff: check-lint lint-checkstyle: check-lint golangci-lint --out-format checkstyle run ./... +start: + go run cmd/gitlab-code-quality/main.go transform + test: go test -v ./... diff --git a/cmd/gitlab-code-quality/commands/transform.go b/cmd/gitlab-code-quality/commands/transform.go index b8e3b2e..054b64a 100644 --- a/cmd/gitlab-code-quality/commands/transform.go +++ b/cmd/gitlab-code-quality/commands/transform.go @@ -12,6 +12,7 @@ import ( "strings" "github.com/spf13/cobra" + "github.com/spf13/pflag" ) // TransformCmd ... @@ -21,52 +22,88 @@ var TransformCmd = &cobra.Command{ RunE: transformCmdF, } +type TransformCommand struct { + sourceReport []string + reporterEngine []string + reportType []string + outputFile string + outputArg bool + detectReport bool +} + +func NewTransformCommand(flags *pflag.FlagSet) *TransformCommand { + transformCommand := TransformCommand{} + + transformCommand.sourceReport, _ = flags.GetStringSlice("source-report") + transformCommand.reporterEngine, _ = flags.GetStringSlice("reporter-tool") + transformCommand.reportType, _ = flags.GetStringSlice("report-type") + transformCommand.outputFile, _ = flags.GetString("output-file") + transformCommand.outputArg, _ = flags.GetBool("output") + transformCommand.detectReport, _ = flags.GetBool("detect-report") + + return &transformCommand +} + +func (t *TransformCommand) FindReport(reportLocation string) []string { + matches, _ := filepath.Glob("*-checkstyle.xml") + return matches +} + +func (t *TransformCommand) AddReport(reportFile string, reportType string, reportEngine string) *TransformCommand { + t.reporterEngine = append(t.reporterEngine, reportEngine) + t.reportType = append(t.reportType, reportType) + t.sourceReport = append(t.sourceReport, reportFile) + + return t +} + +func (t *TransformCommand) CreateFile(fileData []byte) error { + f, errCreate := os.Create(t.outputFile) + + if errCreate != nil { + return errCreate + } + + defer f.Close() + + _, errWrite := f.Write(fileData) + + if errWrite != nil { + return errWrite + } + + return nil +} + func init() { TransformCmd.Flags().StringSlice("source-report", []string{""}, "Source Report") TransformCmd.Flags().StringSlice("reporter-tool", []string{""}, "Reporter Tool") TransformCmd.Flags().StringSlice("report-type", []string{model.ReportTypeIssue}, "Report Type") - TransformCmd.Flags().Bool("output", false, "Output") + TransformCmd.Flags().Bool("output", true, "Output") TransformCmd.Flags().Bool("debug", false, "Enables debug mode") - TransformCmd.Flags().Bool("detect-report", false, "Automatically detect report files") + TransformCmd.Flags().Bool("detect-report", true, "Automatically detect report files") TransformCmd.Flags().String("output-file", "", "Output File Name") RootCmd.AddCommand(TransformCmd) } func transformCmdF(command *cobra.Command, args []string) error { - sourceReportArg, _ := command.Flags().GetStringSlice("source-report") - reporterToolArg, _ := command.Flags().GetStringSlice("reporter-tool") - reportTypeArg, _ := command.Flags().GetStringSlice("report-type") - outputFileArg, _ := command.Flags().GetString("output-file") - outputArg, _ := command.Flags().GetBool("output") - detectReportArg, _ := command.Flags().GetBool("detect-report") - //debugArg, _ := command.Flags().GetBool("debug") - - sourceReport := make([]string, len(sourceReportArg)) - copy(sourceReport, sourceReportArg) - - reporterTool := make([]string, len(sourceReport)) - copy(reporterTool, reporterToolArg) - - reportType := make([]string, len(sourceReport)) - copy(reportType, reportTypeArg) + transformCommand := NewTransformCommand(command.Flags()) parsedReport := make([]*model.Report, 0) // Detect Report Files Automatically - if detectReportArg { - matches, err := filepath.Glob("*-*-checkstyle.xml") - - if err == nil && len(matches) > 0 { - for _, fileName := range matches { - splitFileName := strings.Split(fileName, "-") - reporterTool = append(reporterTool, splitFileName[1]) - reportType = append(reportType, model.ReportTypeIssue) - sourceReport = append(sourceReport, fileName) - } + if transformCommand.detectReport { + for _, reportFile := range transformCommand.FindReport("*-checkstyle.xml") { + fmt.Printf("Detected report: file (%s)\n", reportFile) + // Spliting will only work when the regex is appropriate + splitFileName := strings.Split(reportFile, "-") + transformCommand = transformCommand.AddReport(reportFile, model.ReportTypeIssue, splitFileName[0]) } } - for idx, report := range sourceReport { + for idx, report := range transformCommand.sourceReport { + fmt.Printf("Using report: file (%s) type (%s) engine (%s)\n", report, transformCommand.reportType[idx], transformCommand.reporterEngine[idx]) + reportFromFile, err := os.ReadFile(report) if err != nil { return errors.New("specified source report was not found") @@ -79,38 +116,29 @@ func transformCmdF(command *cobra.Command, args []string) error { err = xml.Unmarshal(byteValue, &result) if err != nil { - return errors.New("could not parse the provided file, it must be a xml checkstyle compliant") + return errors.New("could not parse the provided file, it must be xml checkstyle compliant") } // Assemble Gitlab report compatible structure for _, file := range result.Files { - for _, fileError := range file.Errors { - errorReport := model.NewReportFromCheckstyle(fileError, reportType[idx], reporterTool[idx], file.Name) - parsedReport = append(parsedReport, errorReport) + for _, fileCheckStyleError := range file.Errors { + parsedReport = append(parsedReport, model.NewReportFromCheckstyle(fileCheckStyleError, transformCommand.reportType[idx], transformCommand.reporterEngine[idx], file.Name)) } } } jsonReport, _ := model.ReportListToJSON(parsedReport) - if outputArg { + if transformCommand.outputArg { fmt.Printf("%s\n", jsonReport) } - if outputFileArg != "" { - f, err := os.Create(outputFileArg) - - if err != nil { + if transformCommand.outputFile != "" { + if err := transformCommand.CreateFile(jsonReport); err != nil { return err } - defer f.Close() - - _, err2 := f.Write(jsonReport) - - if err2 != nil { - return err2 - } + fmt.Printf("Report created at: %s\n", transformCommand.outputFile) } return nil diff --git a/model/checkstyle.go b/model/checkstyle.go index d143c40..ee8e4c7 100644 --- a/model/checkstyle.go +++ b/model/checkstyle.go @@ -6,8 +6,8 @@ import "encoding/xml" // ... // // References: -// - http://checkstyle.sourceforge.net/ -// - http://eslint.org/docs/user-guide/formatters/#checkstyle +// http://checkstyle.sourceforge.net/ +// http://eslint.org/docs/user-guide/formatters/#checkstyle type CheckStyleResult struct { XMLName xml.Name `xml:"checkstyle"` Version string `xml:"version,attr"` diff --git a/model/report.go b/model/report.go index a5e77df..4f86a98 100644 --- a/model/report.go +++ b/model/report.go @@ -39,6 +39,8 @@ const ( SeverityBlocker = "blocker" ReportTypeIssue = "issue" + + ReportEngineEslint = "eslint" ) type ReportContent struct { @@ -130,7 +132,7 @@ func (r *Report) SetSeverity(severity string) { func (r *Report) SetCheckName() { switch r.EngineName { - case "eslint": + case ReportEngineEslint: checkNameSplit := strings.Split(r.CheckName, "/") r.CheckName = checkNameSplit[len(checkNameSplit)-1] } @@ -141,7 +143,7 @@ func (r *Report) SetCategories() { r.Categories = []string{Style} switch r.EngineName { - case "eslint": + case ReportEngineEslint: if eslintCategory[r.CheckName] != "" { r.Categories = []string{eslintCategory[r.CheckName]} } @@ -170,7 +172,7 @@ func (r *Report) ComputeFingerprint() { hasher.Write(b) switch r.EngineName { - case "eslint": + case ReportEngineEslint: if r.CheckName == Complexity { r.Fingerprint = hex.EncodeToString(hasher.Sum(nil)) } diff --git a/model/report_test.go b/model/report_test.go new file mode 100644 index 0000000..71fe275 --- /dev/null +++ b/model/report_test.go @@ -0,0 +1,49 @@ +package model + +import ( + "testing" +) + +const ( + reportFileName = "eslint-checkstyle.xml" + reportCheckName = "@typescript-eslint/no-unused-vars" + checkName = "no-unused-vars" +) + +func newReport() *Report { + NewReportFromCheckstyle(&CheckStyleError{ + Column: 0, + Line: 0, + Message: "", + Severity: BugRisk, + }, ReportTypeIssue, ReportEngineEslint, reportFileName) + + r := Report{ + EngineName: ReportEngineEslint, + CheckName: reportCheckName, + Categories: []string{eslintCategory[checkName]}, + } + + return &r +} + +func TestSetCheckName(t *testing.T) { + r := newReport() + r.SetCheckName() + + if r.CheckName != checkName { + t.Fail() + } +} + +func TestSetCategories(t *testing.T) { + r := newReport() + r.SetCheckName() + r.SetCategories() + + for _, category := range r.Categories { + if category != eslintCategory[r.CheckName] { + t.Fail() + } + } +}