diff --git a/cmd/check_coverage.go b/cmd/check_coverage.go index f8f1ffc..78b26aa 100644 --- a/cmd/check_coverage.go +++ b/cmd/check_coverage.go @@ -1,30 +1,61 @@ package cmd import ( + "fmt" + "os/exec" + "regexp" + "strconv" + "strings" + log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - "github.com/spf13/viper" ) -var ( - ccInput string - check float32 +func NewCheckCoverageCmd() *cobra.Command { + var coverProfile string + var threshold float64 + var doNotFail bool - checkCoverageCmd = &cobra.Command{ + checkCoverageCmd := &cobra.Command{ Use: "check-coverage", Short: "Checks total coverage against thresholds", - Run: func(cmd *cobra.Command, args []string) { - in := viper.GetString("in") - check := cmd.Flags().Lookup("check").Value + RunE: func(cmd *cobra.Command, args []string) error { + result, err := exec.Command("go", "tool", "cover", "-func", coverProfile).Output() + if err != nil { + return err + } + + content := string(result) + index := strings.Index(content, "total") + line := content[index:] + re := regexp.MustCompile(`([0-9]*\.?[0-9]*)\s*%`) + match := re.FindStringSubmatch(line) + totalCoverage, err := strconv.ParseFloat(match[1], 32) + if err != nil { + return err + } + + if totalCoverage < threshold { + msg := fmt.Sprintf( + "total coverage %.2f is lower than threshold %.2f", + totalCoverage, + threshold, + ) + if doNotFail { + log.Warn(msg) + } else { + log.Fatalf(msg) + } + } - log.Infof("Input:\t%s", in) - log.Infof("Check:\t%s%%", check) + return nil }, } -) -func init() { - checkCoverageCmd.Flags().StringVar(&ccInput, "rInput", "", "rInput") - checkCoverageCmd.Flags().Float32VarP(&check, "check", "c", 100, "check") - checkCoverageCmd.MarkFlagRequired("rInput") + f := checkCoverageCmd.Flags() + f.StringVarP(&coverProfile, "coverprofile", "c", "coverage.out", "coverprofile") + f.Float64VarP(&threshold, "threshold", "t", 100, "threshold") + f.BoolVarP(&doNotFail, "do-not-fail", "d", false, "do-not-fail") + + return checkCoverageCmd } diff --git a/cmd/report.go b/cmd/report.go index 0bf06bb..d496375 100644 --- a/cmd/report.go +++ b/cmd/report.go @@ -1,34 +1,24 @@ package cmd import ( + "fmt" "strconv" + istanbulReporter "github.com/farbodsalimi/dokimi/internal/reporters/istanbul" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - - istanbulReporter "github.com/farbodsalimi/dokimi/internal/reporters/istanbul" ) -func init() { - reportCmd.Flags().BoolVar(&show, "show", false, "Shows written reports") - reportCmd.Flags(). - StringVarP(&reporter, "reporter", "r", "", "Reporter name e.g. istanbul, lcov, ...") - reportCmd.Flags().StringVarP(&rInput, "input", "i", "", "Path to input file") - reportCmd.Flags().StringVarP(&rOutput, "output", "o", "", "Path to output file") - reportCmd.MarkFlagRequired("reporter") - reportCmd.MarkFlagRequired("rInput") -} - -var ( - reporter string - rInput string - rOutput string - show bool +func NewReportCmd() *cobra.Command { + var reporter string + var rInput string + var rOutput string + var show bool - reportCmd = &cobra.Command{ + reportCmd := &cobra.Command{ Use: "report", Short: "Writes reports for Go coverage profiles", - Run: func(cmd *cobra.Command, args []string) { + RunE: func(cmd *cobra.Command, args []string) error { log.Infof("Reporter:\t%s", reporter) log.Infof("Input:\t%s", rInput) log.Infof("Output:\t%s", rOutput) @@ -38,7 +28,7 @@ var ( case "istanbul": istanbul, err := istanbulReporter.New() if err != nil { - log.Fatalln(err) + return err } if show { @@ -48,8 +38,20 @@ var ( } default: - log.Fatalf("Unknown reporter: %s", reporter) + return fmt.Errorf("unknown reporter: %s", reporter) } + + return nil }, } -) + + reportCmd.Flags().BoolVar(&show, "show", false, "Shows written reports") + reportCmd.Flags(). + StringVarP(&reporter, "reporter", "r", "", "Reporter name e.g. istanbul, lcov, ...") + reportCmd.Flags().StringVarP(&rInput, "input", "i", "", "Path to input file") + reportCmd.Flags().StringVarP(&rOutput, "output", "o", "", "Path to output file") + reportCmd.MarkFlagRequired("reporter") + reportCmd.MarkFlagRequired("rInput") + + return reportCmd +} diff --git a/cmd/root.go b/cmd/root.go index 7ac9ce2..5071855 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -4,29 +4,11 @@ import ( "errors" "os" + "github.com/farbodsalimi/dokimi/internal/configs" log "github.com/sirupsen/logrus" "github.com/spf13/cobra" - - "github.com/farbodsalimi/dokimi/internal/configs" ) -var ( - // Root Command - rootCmd = &cobra.Command{ - Use: "dokimi", - Short: "Dokimi provides some helper commands for testing in Go.", - } -) - -func init() { - cobra.OnInitialize(initConfig) - - rootCmd.CompletionOptions.DisableDefaultCmd = true - - rootCmd.AddCommand(reportCmd) - rootCmd.AddCommand(checkCoverageCmd) -} - func initConfig() { if _, err := os.Stat(configs.DokimiHomeDir); errors.Is(err, os.ErrNotExist) { log.Println("Creating", configs.DokimiHomeDir, "...") @@ -45,9 +27,28 @@ func initConfig() { } } -func Execute() { +func NewRootCommand() *cobra.Command { + rootCmd := &cobra.Command{ + Use: "dokimi", + Short: "Dokimi provides some helper commands for testing in Go.", + } + + rootCmd.AddCommand(NewReportCmd()) + rootCmd.AddCommand(NewCheckCoverageCmd()) + + return rootCmd +} + +func Execute(version string) error { + rootCmd := NewRootCommand() + rootCmd.Version = version + + cobra.OnInitialize(initConfig) + rootCmd.CompletionOptions.DisableDefaultCmd = true + if err := rootCmd.Execute(); err != nil { - log.Errorln(err) - os.Exit(1) + return err } + + return nil } diff --git a/internal/reporters/istanbul/show.go b/internal/reporters/istanbul/show.go index d0656de..7dc8845 100644 --- a/internal/reporters/istanbul/show.go +++ b/internal/reporters/istanbul/show.go @@ -4,13 +4,12 @@ import ( "os" "os/exec" + "github.com/farbodsalimi/dokimi/internal/configs" "github.com/olekukonko/tablewriter" log "github.com/sirupsen/logrus" - - "github.com/farbodsalimi/dokimi/internal/configs" ) -func (istanbul *Istanbul) ShowReport(input string, output string) { +func (istanbul *Istanbul) ShowReport(input string, output string) error { // istanbul.WriteReport( input, @@ -31,12 +30,14 @@ func (istanbul *Istanbul) ShowReport(input string, output string) { table.Append([]string{"npm i -g istanbul"}) table.Render() - log.Fatal(err) + return err } exeCmd = exec.Command("open", configs.IstanbulTmpIndexPath) err = exeCmd.Run() if err != nil { - log.Fatal(err) + return err } + + return nil } diff --git a/internal/reporters/istanbul/write.go b/internal/reporters/istanbul/write.go index 987119b..f787ec3 100644 --- a/internal/reporters/istanbul/write.go +++ b/internal/reporters/istanbul/write.go @@ -12,10 +12,10 @@ import ( "github.com/farbodsalimi/dokimi/internal/reporters/std" ) -func (istanbul *Istanbul) WriteReport(input string, output string) { +func (istanbul *Istanbul) WriteReport(input string, output string) error { wd, err := os.Getwd() if err != nil { - log.Fatal(err) + return err } absoluteDir, projectFolder := path.Split(wd) @@ -27,7 +27,7 @@ func (istanbul *Istanbul) WriteReport(input string, output string) { profiles, err := std.ParseProfiles(input) if err != nil { - log.Fatal(err) + return err } for _, p := range profiles { @@ -63,12 +63,14 @@ func (istanbul *Istanbul) WriteReport(input string, output string) { file, err := json.MarshalIndent(istanbulObject, "", " ") if err != nil { - log.Fatal(err) + return err } err = istanbul.writeFile(output, file, 0644) if err != nil { fmt.Println(err) - log.Fatal(err) + return err } + + return nil } diff --git a/main.go b/main.go index 1a05fd8..bdd8b05 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,22 @@ package main -import "github.com/farbodsalimi/dokimi/cmd" +import ( + "github.com/farbodsalimi/dokimi/cmd" + log "github.com/sirupsen/logrus" +) + +// Version is the version of this binary. It'll be overridden as part of the build process through linker flags. +var Version = "development" + +func init() { + log.SetFormatter(&log.TextFormatter{ + DisableTimestamp: true, + }) +} func main() { - cmd.Execute() + err := cmd.Execute(Version) + if err != nil { + log.Fatalln(err) + } }