diff --git a/cmd/comment.go b/cmd/comment.go index 5022795e..ac9c0d6a 100644 --- a/cmd/comment.go +++ b/cmd/comment.go @@ -71,13 +71,13 @@ func createReportContent(ctx context.Context, c *config.Config, r, rPrev *report table = d.Table() fileTable = d.FileCoveagesTable(files) for _, s := range d.CustomMetrics { - customTables = append(customTables, s.Table()) + customTables = append(customTables, s.Table(), s.MetadataTable()) } } else { table = r.Table() fileTable = r.FileCoveagesTable(files) for _, s := range r.CustomMetrics { - customTables = append(customTables, s.Table()) + customTables = append(customTables, s.Table(), s.MetadataTable()) } } diff --git a/report/custom.go b/report/custom.go index 18899e4a..2941502c 100644 --- a/report/custom.go +++ b/report/custom.go @@ -16,11 +16,18 @@ import ( //go:embed custom_metrics_schema.json var schema []byte +type MetadataKV struct { + Key string `json:"key"` + Name string `json:"name,omitempty"` + Value string `json:"value"` +} + type CustomMetricSet struct { - Key string `json:"key"` - Name string `json:"name,omitempty"` - Metrics []*CustomMetric `json:"metrics"` - report *Report + Key string `json:"key"` + Name string `json:"name,omitempty"` + Metadata []*MetadataKV `json:"metadata,omitempty"` + Metrics []*CustomMetric `json:"metrics"` + report *Report } type CustomMetric struct { @@ -79,6 +86,33 @@ func (s *CustomMetricSet) Table() string { return strings.Replace(buf.String(), "---|", "--:|", len(h)) } +func (s *CustomMetricSet) MetadataTable() string { + if len(s.Metadata) == 0 { + return "" + } + var h []string + var d []string + for _, m := range s.Metadata { + if m.Name == "" { + m.Name = m.Key + } + h = append(h, m.Name) + d = append(d, m.Value) + } + buf := new(bytes.Buffer) + buf.WriteString("
Metadata\n\n") + table := tablewriter.NewWriter(buf) + table.SetHeader(h) + table.SetAutoFormatHeaders(false) + table.SetAutoWrapText(false) + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + table.Append(d) + table.Render() + buf.WriteString("\n
\n") + return strings.Replace(buf.String(), "---|", "--:|", len(h)) +} + func (s *CustomMetricSet) Out(w io.Writer) error { if len(s.Metrics) == 0 { return nil @@ -180,6 +214,13 @@ func (s *CustomMetricSet) Validate() error { return m.Key })) } + if len(s.Metadata) != len(lo.UniqBy(s.Metadata, func(m *MetadataKV) string { + return m.Key + })) { + return fmt.Errorf("key of metadata must be unique: %s", lo.Map(s.Metadata, func(m *MetadataKV, _ int) string { + return m.Key + })) + } return nil } @@ -199,7 +240,6 @@ func (d *DiffCustomMetricSet) Table() string { table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) table.SetCenterSeparator("|") table.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_RIGHT, tablewriter.ALIGN_RIGHT, tablewriter.ALIGN_RIGHT}) - table.SetHeader([]string{"", makeHeadTitleWithLink(d.B.report.Ref, d.B.report.Commit, nil), makeHeadTitleWithLink(d.A.report.Ref, d.A.report.Commit, nil), "+/-"}) for _, m := range d.Metrics { var va, vb, diff string @@ -239,6 +279,36 @@ func (d *DiffCustomMetricSet) Table() string { return strings.Replace(strings.Replace(buf.String(), "---|", "--:|", 4), "--:|", "---|", 1) } +func (d *DiffCustomMetricSet) MetadataTable() string { + if len(d.A.Metadata) == 0 { + return "" + } + if d.B == nil || len(d.B.Metadata) == 0 { + return d.A.MetadataTable() + } + buf := new(bytes.Buffer) + buf.WriteString("
Metadata\n\n") + table := tablewriter.NewWriter(buf) + table.SetAutoFormatHeaders(false) + table.SetAutoWrapText(false) + table.SetBorders(tablewriter.Border{Left: true, Top: false, Right: true, Bottom: false}) + table.SetCenterSeparator("|") + table.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_RIGHT, tablewriter.ALIGN_RIGHT, tablewriter.ALIGN_RIGHT}) + table.SetHeader([]string{"", makeHeadTitleWithLink(d.B.report.Ref, d.B.report.Commit, nil), makeHeadTitleWithLink(d.A.report.Ref, d.A.report.Commit, nil)}) + for _, ma := range d.A.Metadata { + mb, ok := lo.Find(d.B.Metadata, func(m *MetadataKV) bool { + return m.Key == ma.Key + }) + if !ok { + mb = &MetadataKV{} + } + table.Append([]string{fmt.Sprintf("**%s**", ma.Key), mb.Value, ma.Value}) + } + table.Render() + buf.WriteString("\n
\n") + return strings.Replace(strings.Replace(buf.String(), "---|", "--:|", 4), "--:|", "---|", 1) +} + func isInt(v float64) bool { return v == float64(int64(v)) } diff --git a/report/custom_test.go b/report/custom_test.go index 9d6314b0..a16fd70d 100644 --- a/report/custom_test.go +++ b/report/custom_test.go @@ -47,6 +47,37 @@ func TestCustomMetricSetTable(t *testing.T) { } } +func TestCustomMetricSetMetadataTable(t *testing.T) { + tests := []struct { + s *CustomMetricSet + }{ + {&CustomMetricSet{}}, + {&CustomMetricSet{ + Key: "benchmark_0", + Name: "Benchmark-0", + Metadata: []*MetadataKV{ + {Key: "goos", Value: "darwin"}, + {Key: "goarch", Value: "amd64"}, + {Key: "pkg", Value: "github.com/k1LoW/octocov/metrics"}, + {Key: "commit", Value: "a1b2c3d4e5f6"}, + }, + }}, + } + for i, tt := range tests { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + got := tt.s.MetadataTable() + f := filepath.Join("custom_metrics", fmt.Sprintf("custom_metric_set_metadata_table.%d", i)) + if os.Getenv("UPDATE_GOLDEN") != "" { + golden.Update(t, testdataDir(t), f, got) + return + } + if diff := golden.Diff(t, testdataDir(t), f, got); diff != "" { + t.Error(diff) + } + }) + } +} + func TestCustomMetricSetOut(t *testing.T) { tests := []struct { s *CustomMetricSet @@ -114,6 +145,33 @@ func TestCustomMetricsSetValidate(t *testing.T) { Key: "key", Metrics: []*CustomMetric{}, }, true}, + {&CustomMetricSet{ + Key: "key", + Metrics: []*CustomMetric{ + {Key: "count", Value: 1000.0}, + {Key: "count", Value: 1001.0}, + }, + }, true}, + {&CustomMetricSet{ + Key: "key", + Metrics: []*CustomMetric{ + {Key: "count", Value: 1000.0}, + }, + Metadata: []*MetadataKV{ + {Key: "goos", Value: "darwin"}, + {Key: "goarch", Value: "amd64"}, + }, + }, false}, + {&CustomMetricSet{ + Key: "key", + Metrics: []*CustomMetric{ + {Key: "count", Value: 1000.0}, + }, + Metadata: []*MetadataKV{ + {Key: "goos", Value: "darwin"}, + {Key: "goos", Value: "linux"}, + }, + }, true}, } for i, tt := range tests { t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { @@ -198,3 +256,72 @@ func TestDiffCustomMetricSetTable(t *testing.T) { }) } } + +func TestDiffCustomMetricSetMetadataTable(t *testing.T) { + tests := []struct { + a *CustomMetricSet + b *CustomMetricSet + }{ + { + &CustomMetricSet{ + Key: "benchmark_0", + Name: "Benchmark-0", + Metadata: []*MetadataKV{ + {Key: "goos", Value: "darwin"}, + {Key: "goarch", Value: "amd64"}, + }, + report: &Report{ + Ref: "main", + Commit: "1234567890", + covPaths: []string{"testdata/cover.out"}, + }, + }, + nil, + }, + { + &CustomMetricSet{ + Key: "benchmark_0", + Name: "Benchmark-0", + Metadata: []*MetadataKV{ + {Key: "goos", Value: "darwin"}, + {Key: "goarch", Value: "amd64"}, + }, + report: &Report{ + Ref: "main", + Commit: "1234567890", + covPaths: []string{"testdata/cover.out"}, + }, + }, + &CustomMetricSet{ + Key: "benchmark_0", + Name: "Benchmark-0", + Metadata: []*MetadataKV{ + {Key: "goos", Value: "arwin"}, + {Key: "goarch", Value: "arm64"}, + }, + report: &Report{ + Ref: "main", + Commit: "2345678901", + covPaths: []string{"testdata/cover.out"}, + }, + }, + }, + } + + t.Setenv("GITHUB_SERVER_URL", "https://github.com") + t.Setenv("GITHUB_REPOSITORY", "owner/repo") + for i, tt := range tests { + t.Run(fmt.Sprintf("%d", i), func(t *testing.T) { + d := tt.a.Compare(tt.b) + got := d.MetadataTable() + f := filepath.Join("custom_metrics", fmt.Sprintf("diff_custom_metric_set_metadata_table.%d", i)) + if os.Getenv("UPDATE_GOLDEN") != "" { + golden.Update(t, testdataDir(t), f, got) + return + } + if diff := golden.Diff(t, testdataDir(t), f, got); diff != "" { + t.Error(diff) + } + }) + } +} diff --git a/report/report_test.go b/report/report_test.go index 00f901e4..b4dfeb21 100644 --- a/report/report_test.go +++ b/report/report_test.go @@ -115,6 +115,10 @@ func TestCollectCustomMetrics(t *testing.T) { { Key: "benchmark_0", Name: "Benchmark-0 (this is custom metrics test)", + Metadata: []*MetadataKV{ + {Key: "goos", Name: "GOOS", Value: "darwin"}, + {Key: "goarch", Name: "GOARCH", Value: "amd64"}, + }, Metrics: []*CustomMetric{ {Key: "N", Name: "Number of iterations", Value: 1000.0, Unit: ""}, {Key: "NsPerOp", Name: "Nanoseconds per iteration", Value: 676.5, Unit: " ns/op"}, @@ -132,6 +136,10 @@ func TestCollectCustomMetrics(t *testing.T) { { Key: "benchmark_0", Name: "Benchmark-0 (this is custom metrics test)", + Metadata: []*MetadataKV{ + {Key: "goos", Name: "GOOS", Value: "darwin"}, + {Key: "goarch", Name: "GOARCH", Value: "amd64"}, + }, Metrics: []*CustomMetric{ {Key: "N", Name: "Number of iterations", Value: 1000.0, Unit: ""}, {Key: "NsPerOp", Name: "Nanoseconds per iteration", Value: 676.5, Unit: " ns/op"}, @@ -140,6 +148,10 @@ func TestCollectCustomMetrics(t *testing.T) { { Key: "benchmark_1", Name: "Benchmark-1 (this is custom metrics test)", + Metadata: []*MetadataKV{ + {Key: "goos", Name: "GOOS", Value: "darwin"}, + {Key: "goarch", Name: "GOARCH", Value: "amd64"}, + }, Metrics: []*CustomMetric{ {Key: "N", Name: "Number of iterations", Value: 1500.0, Unit: ""}, {Key: "NsPerOp", Name: "Nanoseconds per iteration", Value: 1345.0, Unit: " ns/op"}, @@ -156,6 +168,10 @@ func TestCollectCustomMetrics(t *testing.T) { { Key: "benchmark_0", Name: "Benchmark-0 (this is custom metrics test)", + Metadata: []*MetadataKV{ + {Key: "goos", Name: "GOOS", Value: "darwin"}, + {Key: "goarch", Name: "GOARCH", Value: "amd64"}, + }, Metrics: []*CustomMetric{ {Key: "N", Name: "Number of iterations", Value: 1000.0, Unit: ""}, {Key: "NsPerOp", Name: "Nanoseconds per iteration", Value: 676.5, Unit: " ns/op"}, @@ -164,6 +180,10 @@ func TestCollectCustomMetrics(t *testing.T) { { Key: "benchmark_1", Name: "Benchmark-1 (this is custom metrics test)", + Metadata: []*MetadataKV{ + {Key: "goos", Name: "GOOS", Value: "darwin"}, + {Key: "goarch", Name: "GOARCH", Value: "amd64"}, + }, Metrics: []*CustomMetric{ {Key: "N", Name: "Number of iterations", Value: 1500.0, Unit: ""}, {Key: "NsPerOp", Name: "Nanoseconds per iteration", Value: 1345.0, Unit: " ns/op"}, @@ -185,6 +205,7 @@ func TestCollectCustomMetrics(t *testing.T) { t.Fatal(err) } } + return } for k, v := range tt.envs { t.Setenv(k, v) diff --git a/testdata/custom_metrics/benchmark_0.json b/testdata/custom_metrics/benchmark_0.json index aeaf86c3..39337ffc 100755 --- a/testdata/custom_metrics/benchmark_0.json +++ b/testdata/custom_metrics/benchmark_0.json @@ -1,6 +1,18 @@ { "key": "benchmark_0", "name": "Benchmark-0 (this is custom metrics test)", + "metadata": [ + { + "key": "goos", + "name": "GOOS", + "value": "darwin" + }, + { + "key": "goarch", + "name": "GOARCH", + "value": "amd64" + } + ], "metrics": [ { "key": "N", diff --git a/testdata/custom_metrics/benchmark_0_1.json b/testdata/custom_metrics/benchmark_0_1.json index b03eafa8..5e271372 100644 --- a/testdata/custom_metrics/benchmark_0_1.json +++ b/testdata/custom_metrics/benchmark_0_1.json @@ -2,6 +2,18 @@ { "key": "benchmark_0", "name": "Benchmark-0 (this is custom metrics test)", + "metadata": [ + { + "key": "goos", + "name": "GOOS", + "value": "darwin" + }, + { + "key": "goarch", + "name": "GOARCH", + "value": "amd64" + } + ], "metrics": [ { "key": "N", @@ -19,6 +31,18 @@ { "key": "benchmark_1", "name": "Benchmark-1 (this is custom metrics test)", + "metadata": [ + { + "key": "goos", + "name": "GOOS", + "value": "darwin" + }, + { + "key": "goarch", + "name": "GOARCH", + "value": "amd64" + } + ], "metrics": [ { "key": "N", diff --git a/testdata/custom_metrics/benchmark_1.json b/testdata/custom_metrics/benchmark_1.json index e896c9d5..212c5587 100755 --- a/testdata/custom_metrics/benchmark_1.json +++ b/testdata/custom_metrics/benchmark_1.json @@ -1,6 +1,18 @@ { "key": "benchmark_1", "name": "Benchmark-1 (this is custom metrics test)", + "metadata": [ + { + "key": "goos", + "name": "GOOS", + "value": "darwin" + }, + { + "key": "goarch", + "name": "GOARCH", + "value": "amd64" + } + ], "metrics": [ { "key": "N", diff --git a/testdata/custom_metrics/custom_metric_set_metadata_table.0.golden b/testdata/custom_metrics/custom_metric_set_metadata_table.0.golden new file mode 100644 index 00000000..e69de29b diff --git a/testdata/custom_metrics/custom_metric_set_metadata_table.1.golden b/testdata/custom_metrics/custom_metric_set_metadata_table.1.golden new file mode 100644 index 00000000..c083e6a1 --- /dev/null +++ b/testdata/custom_metrics/custom_metric_set_metadata_table.1.golden @@ -0,0 +1,7 @@ +
Metadata + +| goos | goarch | pkg | commit | +|-------:|-------:|---------------------------------:|-------------:| +| darwin | amd64 | github.com/k1LoW/octocov/metrics | a1b2c3d4e5f6 | + +
diff --git a/testdata/custom_metrics/diff_custom_metric_set_metadata_table.0.golden b/testdata/custom_metrics/diff_custom_metric_set_metadata_table.0.golden new file mode 100644 index 00000000..4185c6be --- /dev/null +++ b/testdata/custom_metrics/diff_custom_metric_set_metadata_table.0.golden @@ -0,0 +1,7 @@ +
Metadata + +| goos | goarch | +|-------:|-------:| +| darwin | amd64 | + +
diff --git a/testdata/custom_metrics/diff_custom_metric_set_metadata_table.1.golden b/testdata/custom_metrics/diff_custom_metric_set_metadata_table.1.golden new file mode 100644 index 00000000..edbcb043 --- /dev/null +++ b/testdata/custom_metrics/diff_custom_metric_set_metadata_table.1.golden @@ -0,0 +1,8 @@ +
Metadata + +| | ([2345678](https://github.com/owner/repo/commit/2345678901)) | ([1234567](https://github.com/owner/repo/commit/1234567890)) | +|------------|--------------------------------------------------------------:|--------------------------------------------------------------:| +| **goos** | arwin | darwin | +| **goarch** | arm64 | amd64 | + +