Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
432 changes: 432 additions & 0 deletions .go-covercheck.history.json

Large diffs are not rendered by default.

18 changes: 12 additions & 6 deletions cmd/go-covercheck/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -190,19 +190,24 @@
}

// showCoverage and get the results.
results, failed, err := showCoverage(args, cfg)
results, failed, err := collectCoverage(args, cfg)
if err != nil {
return err
}

// compare results against history, when requested
compareRef, _ := cmd.Flags().GetString(CompareHistoryFlag)
if compareRef != "" {
if err := compareHistory(cmd, compareRef, results); err != nil {
if err := compareHistory(cmd, compareRef, &results, cfg); err != nil {
// For comparison errors, still output the coverage results but then return the error
output.FormatAndReport(results, cfg, failed)
return err
}
}

// Now output the results (with any comparison data)
output.FormatAndReport(results, cfg, failed)

// save results to history, when requested.
bSaveHistory, _ := cmd.Flags().GetBool(SaveHistoryFlag)
if bSaveHistory {
Expand All @@ -217,7 +222,7 @@
return nil
}

func showCoverage(args []string, cfg *config.Config) (compute.Results, bool, error) {
func collectCoverage(args []string, cfg *config.Config) (compute.Results, bool, error) {
// we need coverage profile input from here on.
profiles, err := getCoverProfileData(args)
if err != nil {
Expand All @@ -226,7 +231,6 @@
filtered := filter(profiles, cfg)

results, failed := compute.CollectResults(filtered, cfg)
output.FormatAndReport(results, cfg, failed)
return results, failed, nil
}

Expand Down Expand Up @@ -260,7 +264,7 @@
return nil
}

func compareHistory(cmd *cobra.Command, compareRef string, results compute.Results) error {
func compareHistory(cmd *cobra.Command, compareRef string, results *compute.Results, cfg *config.Config) error {

Check failure on line 267 in cmd/go-covercheck/root.go

View workflow job for this annotation

GitHub Actions / build-test-lint

unused-parameter: parameter 'cfg' seems to be unused, consider removing or renaming it as _ (revive)
h, err := getHistory(cmd)
if err != nil {
return fmt.Errorf("failed to load history: %w", err)
Expand All @@ -270,7 +274,9 @@
if refEntry == nil {
return fmt.Errorf("no history entry found for ref: %s", compareRef)
}
output.CompareHistory(compareRef, refEntry, results)

// Always populate comparison data - different formats will handle it differently
results.Comparison = compute.BuildComparisonData(compareRef, refEntry.Commit[:7], refEntry.Results, *results)
return nil
}

Expand Down
2 changes: 1 addition & 1 deletion cmd/go-covercheck/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package main

import (
"encoding/json"
"gopkg.in/yaml.v3"
yaml "gopkg.in/yaml.v3"
"testing"

"github.com/mach6/go-covercheck/pkg/compute"
Expand Down
74 changes: 74 additions & 0 deletions pkg/compute/comparison.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package compute

// BuildComparisonData creates comparison data between current results and a historical entry.
// It takes the necessary parameters without directly importing the history package to avoid cycles.
func BuildComparisonData(ref string, commit string, historicalResults Results, currentResults Results) *ComparisonData {

Check failure on line 5 in pkg/compute/comparison.go

View workflow job for this annotation

GitHub Actions / build-test-lint

calculated cyclomatic complexity for function BuildComparisonData is 14, max is 10 (cyclop)
comparison := &ComparisonData{
Ref: ref,
Commit: commit,
Results: make([]ComparisonResult, 0),
}

// Compare by file
for _, curr := range currentResults.ByFile {
for _, prev := range historicalResults.ByFile {
if curr.File == prev.File {
statementsDelta := curr.StatementPercentage - prev.StatementPercentage
blocksDelta := curr.BlockPercentage - prev.BlockPercentage
if statementsDelta != 0 || blocksDelta != 0 {
comparison.Results = append(comparison.Results, ComparisonResult{
Name: curr.File,
Type: "file",
Delta: ComparisonDelta{
StatementsDelta: statementsDelta,
BlocksDelta: blocksDelta,
},
})
}
break
}
}
}

// Compare by package
for _, curr := range currentResults.ByPackage {
for _, prev := range historicalResults.ByPackage {
if curr.Package == prev.Package {
statementsDelta := curr.StatementPercentage - prev.StatementPercentage
blocksDelta := curr.BlockPercentage - prev.BlockPercentage
if statementsDelta != 0 || blocksDelta != 0 {
comparison.Results = append(comparison.Results, ComparisonResult{
Name: curr.Package,
Type: "package",
Delta: ComparisonDelta{
StatementsDelta: statementsDelta,
BlocksDelta: blocksDelta,
},
})
}
break
}
}
}

// Compare totals
statementsDelta := currentResults.ByTotal.Statements.Percentage - historicalResults.ByTotal.Statements.Percentage
blocksDelta := currentResults.ByTotal.Blocks.Percentage - historicalResults.ByTotal.Blocks.Percentage
if statementsDelta != 0 || blocksDelta != 0 {
comparison.Results = append(comparison.Results, ComparisonResult{
Name: "total",
Type: "total",
Delta: ComparisonDelta{
StatementsDelta: statementsDelta,
BlocksDelta: blocksDelta,
},
})
}

// Only return comparison data if there are actual differences
if len(comparison.Results) == 0 {
return nil
}

return comparison
}
27 changes: 24 additions & 3 deletions pkg/compute/model.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,30 @@
totalStatements int
}

// ComparisonDelta represents the comparison between current and historical results.
type ComparisonDelta struct {
StatementsDelta float64 `json:"statementsDelta" yaml:"statementsDelta"`
BlocksDelta float64 `json:"blocksDelta" yaml:"blocksDelta"`
}

// ComparisonResult represents comparison results for a specific item.
type ComparisonResult struct {
Name string `json:"name" yaml:"name"`

Check failure on line 76 in pkg/compute/model.go

View workflow job for this annotation

GitHub Actions / build-test-lint

tag is not aligned, should be: json:"name" yaml:"name" (tagalign)
Delta ComparisonDelta `json:"delta" yaml:"delta"`

Check failure on line 77 in pkg/compute/model.go

View workflow job for this annotation

GitHub Actions / build-test-lint

tag is not aligned, should be: json:"delta" yaml:"delta" (tagalign)
Type string `json:"type" yaml:"type"` // "file", "package", or "total"

Check failure on line 78 in pkg/compute/model.go

View workflow job for this annotation

GitHub Actions / build-test-lint

tag is not aligned, should be: json:"type" yaml:"type" (tagalign)
}

// ComparisonData holds all comparison information.
type ComparisonData struct {
Ref string `json:"ref" yaml:"ref"`
Commit string `json:"commit" yaml:"commit"`
Results []ComparisonResult `json:"results" yaml:"results"`
}

// Results holds information for all stats collected form the cover.Profile data.
type Results struct {
ByFile []ByFile `json:"byFile" yaml:"byFile"`
ByPackage []ByPackage `json:"byPackage" yaml:"byPackage"`
ByTotal Totals `json:"byTotal" yaml:"byTotal"`
ByFile []ByFile `json:"byFile" yaml:"byFile"`

Check failure on line 90 in pkg/compute/model.go

View workflow job for this annotation

GitHub Actions / build-test-lint

tag is not aligned, should be: json:"byFile" yaml:"byFile" (tagalign)
ByPackage []ByPackage `json:"byPackage" yaml:"byPackage"`

Check failure on line 91 in pkg/compute/model.go

View workflow job for this annotation

GitHub Actions / build-test-lint

tag is not aligned, should be: json:"byPackage" yaml:"byPackage" (tagalign)
ByTotal Totals `json:"byTotal" yaml:"byTotal"`

Check failure on line 92 in pkg/compute/model.go

View workflow job for this annotation

GitHub Actions / build-test-lint

tag is not aligned, should be: json:"byTotal" yaml:"byTotal" (tagalign)
Comparison *ComparisonData `json:"comparison,omitempty" yaml:"comparison,omitempty"`
}
2 changes: 1 addition & 1 deletion pkg/compute/model_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
"github.com/mach6/go-covercheck/pkg/config"
"github.com/stretchr/testify/require"
"golang.org/x/tools/cover"
"gopkg.in/yaml.v3"
yaml "gopkg.in/yaml.v3"
)

const (
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"fmt"
"os"

"gopkg.in/yaml.v3"
yaml "gopkg.in/yaml.v3"
)

// Application config variables that are updated by the build.
Expand Down
2 changes: 1 addition & 1 deletion pkg/history/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"sort"
"time"

"github.com/go-git/go-git/v6"
git "github.com/go-git/go-git/v6"
"github.com/go-git/go-git/v6/plumbing"
"github.com/mach6/go-covercheck/pkg/compute"
)
Expand Down
2 changes: 1 addition & 1 deletion pkg/history/history_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"testing"
"time"

"github.com/go-git/go-git/v6"
git "github.com/go-git/go-git/v6"
"github.com/go-git/go-git/v6/plumbing/object"
"github.com/mach6/go-covercheck/pkg/compute"
"github.com/mach6/go-covercheck/pkg/test"
Expand Down
2 changes: 1 addition & 1 deletion pkg/output/color.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"github.com/goccy/go-yaml/lexer"
"github.com/goccy/go-yaml/printer"
"github.com/mach6/go-covercheck/pkg/math"
"github.com/mattn/go-colorable"
colorable "github.com/mattn/go-colorable"
)

const escape = "\x1b"
Expand Down
82 changes: 82 additions & 0 deletions pkg/output/history.go
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,88 @@
return strings.Join(wrapped, "\n")
}

// displayComparisonFromData displays comparison results from structured comparison data.
func displayComparisonFromData(comparison *compute.ComparisonData) {

Check failure on line 233 in pkg/output/history.go

View workflow job for this annotation

GitHub Actions / build-test-lint

cognitive complexity 31 of func `displayComparisonFromData` is high (> 30) (gocognit)
fmt.Printf("\n≡ Comparing against ref: %s [commit %s]\n",
color.New(color.FgBlue).Sprint(comparison.Ref),
color.New(color.FgHiBlack).Sprint(comparison.Commit),
)

if len(comparison.Results) == 0 {
fmt.Println(" → No change")
return
}

// Group results by type for organized display
fileResults := make([]compute.ComparisonResult, 0)
packageResults := make([]compute.ComparisonResult, 0)
totalResults := make([]compute.ComparisonResult, 0)

for _, result := range comparison.Results {
switch result.Type {
case "file":
fileResults = append(fileResults, result)
case "package":
packageResults = append(packageResults, result)
case "total":
totalResults = append(totalResults, result)
}
}

// Display file comparisons
if len(fileResults) > 0 {
fmt.Printf(" → By File\n")
for _, result := range fileResults {
if result.Delta.StatementsDelta != 0 {
compareShowS()
delta, _ := formatDelta(result.Delta.StatementsDelta)
fmt.Printf("%s [%s]\n", result.Name, delta)
}
if result.Delta.BlocksDelta != 0 {
compareShowB()
delta, _ := formatDelta(result.Delta.BlocksDelta)
fmt.Printf("%s [%s]\n", result.Name, delta)
}
fmt.Println()
}
}

// Display package comparisons
if len(packageResults) > 0 {
fmt.Printf(" → By Package\n")
for _, result := range packageResults {
if result.Delta.StatementsDelta != 0 {
compareShowS()
delta, _ := formatDelta(result.Delta.StatementsDelta)
fmt.Printf("%s [%s]\n", result.Name, delta)
}
if result.Delta.BlocksDelta != 0 {
compareShowB()
delta, _ := formatDelta(result.Delta.BlocksDelta)
fmt.Printf("%s [%s]\n", result.Name, delta)
}
fmt.Println()
}
}

// Display total comparisons
if len(totalResults) > 0 {
fmt.Printf(" → By Total\n")
for _, result := range totalResults {
if result.Delta.StatementsDelta != 0 {
compareShowS()
delta, _ := formatDelta(result.Delta.StatementsDelta)
fmt.Printf("%s [%s]\n", result.Name, delta)
}
if result.Delta.BlocksDelta != 0 {
compareShowB()
delta, _ := formatDelta(result.Delta.BlocksDelta)
fmt.Printf("%s [%s]\n", result.Name, delta)
}
}
}
}

func compareShowS() {
fmt.Printf(" [%s] ", color.New(color.FgCyan).Sprint("S"))
}
Expand Down
8 changes: 6 additions & 2 deletions pkg/output/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import (
"os"

"github.com/fatih/color"
"github.com/hokaccha/go-prettyjson"
prettyjson "github.com/hokaccha/go-prettyjson"
"github.com/mach6/go-covercheck/pkg/compute"
"github.com/mach6/go-covercheck/pkg/config"
"gopkg.in/yaml.v3"
yaml "gopkg.in/yaml.v3"
)

func bailOnError(err error) {
Expand All @@ -27,6 +27,10 @@ func FormatAndReport(results compute.Results, cfg *config.Config, hasFailure boo
renderTable(results, cfg)
_ = os.Stdout.Sync()
renderSummary(hasFailure, results, cfg)
// Display comparison for table format if available
if results.Comparison != nil {
displayComparisonFromData(results.Comparison)
}
case config.FormatJSON:
if cfg.NoColor {
enc := json.NewEncoder(os.Stdout)
Expand Down
Loading