Skip to content

Commit 5edc8bb

Browse files
committed
Use single report cmd
1 parent 2033cd8 commit 5edc8bb

File tree

5 files changed

+258
-79
lines changed

5 files changed

+258
-79
lines changed

tools/flakeguard/cmd/generate_report.go

Lines changed: 0 additions & 77 deletions
This file was deleted.

tools/flakeguard/cmd/report.go

Lines changed: 238 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,238 @@
1+
package cmd
2+
3+
import (
4+
"fmt"
5+
"path/filepath"
6+
"strings"
7+
"time"
8+
9+
"github.com/briandowns/spinner"
10+
"github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard/reports"
11+
"github.com/spf13/cobra"
12+
)
13+
14+
var ReportCmd = &cobra.Command{
15+
Use: "report",
16+
Short: "Aggregate test results and generate reports",
17+
RunE: func(cmd *cobra.Command, args []string) error {
18+
fs := reports.OSFileSystem{}
19+
20+
// Get flag values directly using cmd.Flags().Get* methods
21+
reportResultsPath, _ := cmd.Flags().GetString("results-path")
22+
reportOutputPath, _ := cmd.Flags().GetString("output-path")
23+
reportFormats, _ := cmd.Flags().GetString("format")
24+
reportMaxPassRatio, _ := cmd.Flags().GetFloat64("max-pass-ratio")
25+
reportCodeOwnersPath, _ := cmd.Flags().GetString("codeowners-path")
26+
reportRepoPath, _ := cmd.Flags().GetString("repo-path")
27+
28+
// Split the formats into a slice
29+
formats := strings.Split(reportFormats, ",")
30+
31+
// Start spinner for loading test reports
32+
s := spinner.New(spinner.CharSets[11], 100*time.Millisecond)
33+
s.Suffix = " Loading test reports..."
34+
s.Start()
35+
36+
// Load test reports from JSON files
37+
testReports, err := reports.LoadReports(reportResultsPath)
38+
if err != nil {
39+
s.Stop()
40+
return fmt.Errorf("error loading test reports: %w", err)
41+
}
42+
s.Stop()
43+
fmt.Println("Test reports loaded successfully.")
44+
45+
// Start spinner for aggregating reports
46+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
47+
s.Suffix = " Aggregating test reports..."
48+
s.Start()
49+
50+
// Aggregate the reports
51+
aggregatedReport, err := reports.Aggregate(testReports...)
52+
if err != nil {
53+
s.Stop()
54+
return fmt.Errorf("error aggregating test reports: %w", err)
55+
}
56+
s.Stop()
57+
fmt.Println("Test reports aggregated successfully.")
58+
59+
// Start spinner for mapping test results to paths
60+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
61+
s.Suffix = " Mapping test results to paths..."
62+
s.Start()
63+
64+
// Map test results to test paths
65+
err = reports.MapTestResultsToPaths(aggregatedReport, reportRepoPath)
66+
if err != nil {
67+
s.Stop()
68+
return fmt.Errorf("error mapping test results to paths: %w", err)
69+
}
70+
s.Stop()
71+
fmt.Println("Test results mapped to paths successfully.")
72+
73+
// Map test results to code owners if codeOwnersPath is provided
74+
if reportCodeOwnersPath != "" {
75+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
76+
s.Suffix = " Mapping test results to code owners..."
77+
s.Start()
78+
79+
err = reports.MapTestResultsToOwners(aggregatedReport, reportCodeOwnersPath)
80+
if err != nil {
81+
s.Stop()
82+
return fmt.Errorf("error mapping test results to code owners: %w", err)
83+
}
84+
s.Stop()
85+
fmt.Println("Test results mapped to code owners successfully.")
86+
}
87+
88+
// Exclude outputs and package outputs from the aggregated report of all tests
89+
for i := range aggregatedReport.Results {
90+
aggregatedReport.Results[i].Outputs = nil
91+
aggregatedReport.Results[i].PackageOutputs = nil
92+
}
93+
94+
// Create output directory if it doesn't exist
95+
outputDir := reportOutputPath
96+
if err := fs.MkdirAll(outputDir, 0755); err != nil {
97+
return fmt.Errorf("error creating output directory: %w", err)
98+
}
99+
100+
// Save the aggregated report (all tests)
101+
allTestsReportPath := filepath.Join(outputDir, "all-tests-report.json")
102+
if err := reports.SaveReport(fs, allTestsReportPath, *aggregatedReport); err != nil {
103+
return fmt.Errorf("error saving all tests report: %w", err)
104+
}
105+
fmt.Printf("All tests report saved to %s\n", allTestsReportPath)
106+
107+
// Generate and save the reports (all tests) in specified formats
108+
for _, format := range formats {
109+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
110+
s.Suffix = fmt.Sprintf(" Generating all tests report in format %s...", format)
111+
s.Start()
112+
113+
if err := generateReport(aggregatedReport, format, filepath.Join(outputDir, "all-tests")); err != nil {
114+
s.Stop()
115+
return fmt.Errorf("error generating all tests report in format %s: %w", format, err)
116+
}
117+
s.Stop()
118+
fmt.Printf("All tests report in format %s generated successfully.\n", format)
119+
}
120+
121+
// Filter failed tests (PassRatio < maxPassRatio and not skipped)
122+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
123+
s.Suffix = " Filtering failed tests..."
124+
s.Start()
125+
126+
failedTests := reports.FilterTests(aggregatedReport.Results, func(tr reports.TestResult) bool {
127+
return !tr.Skipped && tr.PassRatio < reportMaxPassRatio
128+
})
129+
s.Stop()
130+
fmt.Println("Failed tests filtered successfully.")
131+
132+
// For failed tests, include outputs and package outputs
133+
for i := range failedTests {
134+
// Retrieve outputs and package outputs from original reports
135+
failedTests[i].Outputs = getOriginalOutputs(testReports, failedTests[i].TestName, failedTests[i].TestPackage)
136+
failedTests[i].PackageOutputs = getOriginalPackageOutputs(testReports, failedTests[i].TestName, failedTests[i].TestPackage)
137+
}
138+
139+
// Create a new report for failed tests
140+
failedReport := &reports.TestReport{
141+
GoProject: aggregatedReport.GoProject,
142+
TestRunCount: aggregatedReport.TestRunCount,
143+
RaceDetection: aggregatedReport.RaceDetection,
144+
ExcludedTests: aggregatedReport.ExcludedTests,
145+
SelectedTests: aggregatedReport.SelectedTests,
146+
Results: failedTests,
147+
}
148+
149+
// Save the failed tests report
150+
failedTestsReportPath := filepath.Join(outputDir, "failed-tests-report.json")
151+
if err := reports.SaveReport(fs, failedTestsReportPath, *failedReport); err != nil {
152+
return fmt.Errorf("error saving failed tests report: %w", err)
153+
}
154+
fmt.Printf("Failed tests report saved to %s\n", failedTestsReportPath)
155+
156+
// Generate and save the reports for failed tests in specified formats
157+
for _, format := range formats {
158+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
159+
s.Suffix = fmt.Sprintf(" Generating failed tests report in format %s...", format)
160+
s.Start()
161+
162+
if err := generateReport(failedReport, format, filepath.Join(outputDir, "failed-tests")); err != nil {
163+
s.Stop()
164+
return fmt.Errorf("error generating failed tests report in format %s: %w", format, err)
165+
}
166+
s.Stop()
167+
fmt.Printf("Failed tests report in format %s generated successfully.\n", format)
168+
}
169+
170+
fmt.Printf("Reports generated at: %s\n", reportOutputPath)
171+
172+
return nil
173+
},
174+
}
175+
176+
func init() {
177+
ReportCmd.Flags().StringP("results-path", "p", "", "Path to the folder containing JSON test result files (required)")
178+
ReportCmd.Flags().StringP("output-path", "o", "./report", "Path to output the generated report files")
179+
ReportCmd.Flags().StringP("format", "f", "markdown,json", "Comma-separated list of report formats (markdown,json)")
180+
ReportCmd.Flags().Float64P("max-pass-ratio", "", 1.0, "The maximum pass ratio threshold for a test to be considered flaky")
181+
ReportCmd.Flags().StringP("codeowners-path", "", "", "Path to the CODEOWNERS file")
182+
ReportCmd.Flags().StringP("repo-path", "", ".", "The path to the root of the repository/project")
183+
ReportCmd.MarkFlagRequired("results-path")
184+
}
185+
186+
func generateReport(report *reports.TestReport, format, outputPath string) error {
187+
fs := reports.OSFileSystem{}
188+
format = strings.ToLower(strings.TrimSpace(format))
189+
switch format {
190+
case "markdown":
191+
mdFileName := outputPath + ".md"
192+
mdFile, err := fs.Create(mdFileName)
193+
if err != nil {
194+
return fmt.Errorf("error creating markdown file: %w", err)
195+
}
196+
defer mdFile.Close()
197+
reports.GenerateMarkdownSummary(mdFile, report, 1.0)
198+
case "json":
199+
jsonFileName := outputPath + ".json"
200+
if err := reports.SaveReportNoLogs(fs, jsonFileName, *report); err != nil {
201+
return fmt.Errorf("error saving JSON report: %w", err)
202+
}
203+
default:
204+
return fmt.Errorf("unsupported report format: %s", format)
205+
}
206+
207+
// Generate summary JSON
208+
summaryData := reports.GenerateSummaryData(report.Results, 1.0)
209+
summaryFileName := outputPath + "-summary.json"
210+
if err := reports.SaveSummaryAsJSON(fs, summaryFileName, summaryData); err != nil {
211+
return fmt.Errorf("error saving summary JSON: %w", err)
212+
}
213+
214+
return nil
215+
}
216+
217+
// Helper functions to retrieve original outputs and package outputs
218+
func getOriginalOutputs(reports []*reports.TestReport, testName, testPackage string) []string {
219+
for _, report := range reports {
220+
for _, result := range report.Results {
221+
if result.TestName == testName && result.TestPackage == testPackage {
222+
return result.Outputs
223+
}
224+
}
225+
}
226+
return nil
227+
}
228+
229+
func getOriginalPackageOutputs(reports []*reports.TestReport, testName, testPackage string) []string {
230+
for _, report := range reports {
231+
for _, result := range report.Results {
232+
if result.TestName == testName && result.TestPackage == testPackage {
233+
return result.PackageOutputs
234+
}
235+
}
236+
}
237+
return nil
238+
}

tools/flakeguard/go.mod

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,14 @@ require (
88
)
99

1010
require (
11+
github.com/briandowns/spinner v1.23.1 // indirect
1112
github.com/davecgh/go-spew v1.1.1 // indirect
13+
github.com/fatih/color v1.7.0 // indirect
14+
github.com/mattn/go-colorable v0.1.2 // indirect
15+
github.com/mattn/go-isatty v0.0.8 // indirect
1216
github.com/pmezard/go-difflib v1.0.0 // indirect
17+
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad // indirect
18+
golang.org/x/term v0.1.0 // indirect
1319
gopkg.in/yaml.v3 v3.0.1 // indirect
1420
)
1521

tools/flakeguard/go.sum

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,16 @@
1+
github.com/briandowns/spinner v1.23.1 h1:t5fDPmScwUjozhDj4FA46p5acZWIPXYE30qW2Ptu650=
2+
github.com/briandowns/spinner v1.23.1/go.mod h1:LaZeM4wm2Ywy6vO571mvhQNRcWfRUnXOs0RcKV0wYKM=
13
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
24
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
35
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6+
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
7+
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
48
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
59
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
10+
github.com/mattn/go-colorable v0.1.2 h1:/bC9yWikZXAL9uJdulbSfyVNIR3n3trXl+v8+1sx8mU=
11+
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
12+
github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE=
13+
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
614
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
715
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
816
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
@@ -12,6 +20,11 @@ github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
1220
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
1321
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
1422
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
23+
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
24+
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad h1:ntjMns5wyP/fN65tdBD4g8J5w8n015+iIIs9rtjXkY0=
25+
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
26+
golang.org/x/term v0.1.0 h1:g6Z6vPFA9dYBAF7DWcH6sCcOntplXsDKcliusYijMlw=
27+
golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
1528
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
1629
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
1730
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=

tools/flakeguard/main.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,8 @@ func init() {
2828

2929
rootCmd.AddCommand(cmd.FindTestsCmd)
3030
rootCmd.AddCommand(cmd.RunTestsCmd)
31-
rootCmd.AddCommand(cmd.AggregateResultsCmd)
31+
rootCmd.AddCommand(cmd.ReportCmd)
3232
rootCmd.AddCommand(cmd.CheckTestOwnersCmd)
33-
rootCmd.AddCommand(cmd.GenerateReportCmd)
3433
}
3534

3635
func main() {

0 commit comments

Comments
 (0)