Skip to content

Commit 6653333

Browse files
committed
Split into 2 commands to get links to artifacts in markdown
1 parent 1540a1b commit 6653333

File tree

8 files changed

+524
-293
lines changed

8 files changed

+524
-293
lines changed
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
package cmd
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
"path/filepath"
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 AggregateResultsCmd = &cobra.Command{
15+
Use: "aggregate-results",
16+
Short: "Aggregate test results into a single JSON report",
17+
RunE: func(cmd *cobra.Command, args []string) error {
18+
fs := reports.OSFileSystem{}
19+
20+
// Get flag values
21+
resultsPath, _ := cmd.Flags().GetString("results-path")
22+
outputDir, _ := cmd.Flags().GetString("output-path")
23+
summaryFileName, _ := cmd.Flags().GetString("summary-file-name")
24+
maxPassRatio, _ := cmd.Flags().GetFloat64("max-pass-ratio")
25+
codeOwnersPath, _ := cmd.Flags().GetString("codeowners-path")
26+
repoPath, _ := cmd.Flags().GetString("repo-path")
27+
28+
// Ensure the output directory exists
29+
if err := fs.MkdirAll(outputDir, 0755); err != nil {
30+
return fmt.Errorf("error creating output directory: %w", err)
31+
}
32+
33+
// Start spinner for loading test reports
34+
s := spinner.New(spinner.CharSets[11], 100*time.Millisecond)
35+
s.Suffix = " Loading test reports..."
36+
s.Start()
37+
38+
// Load test reports from JSON files
39+
testReports, err := reports.LoadReports(resultsPath)
40+
if err != nil {
41+
s.Stop()
42+
return fmt.Errorf("error loading test reports: %w", err)
43+
}
44+
s.Stop()
45+
fmt.Println("Test reports loaded successfully.")
46+
47+
// Start spinner for aggregating reports
48+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
49+
s.Suffix = " Aggregating test reports..."
50+
s.Start()
51+
52+
// Aggregate the reports
53+
aggregatedReport, err := reports.Aggregate(testReports...)
54+
if err != nil {
55+
s.Stop()
56+
return fmt.Errorf("error aggregating test reports: %w", err)
57+
}
58+
s.Stop()
59+
fmt.Println("Test reports aggregated successfully.")
60+
61+
// Start spinner for mapping test results to paths
62+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
63+
s.Suffix = " Mapping test results to paths..."
64+
s.Start()
65+
66+
// Map test results to test paths
67+
err = reports.MapTestResultsToPaths(aggregatedReport, repoPath)
68+
if err != nil {
69+
s.Stop()
70+
return fmt.Errorf("error mapping test results to paths: %w", err)
71+
}
72+
s.Stop()
73+
fmt.Println("Test results mapped to paths successfully.")
74+
75+
// Map test results to code owners if codeOwnersPath is provided
76+
if codeOwnersPath != "" {
77+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
78+
s.Suffix = " Mapping test results to code owners..."
79+
s.Start()
80+
81+
err = reports.MapTestResultsToOwners(aggregatedReport, codeOwnersPath)
82+
if err != nil {
83+
s.Stop()
84+
return fmt.Errorf("error mapping test results to code owners: %w", err)
85+
}
86+
s.Stop()
87+
fmt.Println("Test results mapped to code owners successfully.")
88+
}
89+
90+
// Save the aggregated report to the output directory
91+
aggregatedReportPath := filepath.Join(outputDir, "all-test-results.json")
92+
if err := reports.SaveReport(fs, aggregatedReportPath, *aggregatedReport); err != nil {
93+
return fmt.Errorf("error saving aggregated test report: %w", err)
94+
}
95+
fmt.Printf("Aggregated test report saved to %s\n", aggregatedReportPath)
96+
97+
// Filter failed tests (PassRatio < maxPassRatio and not skipped)
98+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
99+
s.Suffix = " Filtering failed tests..."
100+
s.Start()
101+
102+
failedTests := reports.FilterTests(aggregatedReport.Results, func(tr reports.TestResult) bool {
103+
return !tr.Skipped && tr.PassRatio < maxPassRatio
104+
})
105+
s.Stop()
106+
107+
// Check if there are any failed tests
108+
if len(failedTests) > 0 {
109+
fmt.Printf("Found %d failed test(s).\n", len(failedTests))
110+
111+
// Create a new report for failed tests with logs
112+
failedReportWithLogs := &reports.TestReport{
113+
GoProject: aggregatedReport.GoProject,
114+
TestRunCount: aggregatedReport.TestRunCount,
115+
RaceDetection: aggregatedReport.RaceDetection,
116+
ExcludedTests: aggregatedReport.ExcludedTests,
117+
SelectedTests: aggregatedReport.SelectedTests,
118+
Results: failedTests,
119+
}
120+
121+
// Save the failed tests report with logs
122+
failedTestsReportWithLogsPath := filepath.Join(outputDir, "failed-test-results-with-logs.json")
123+
if err := reports.SaveReport(fs, failedTestsReportWithLogsPath, *failedReportWithLogs); err != nil {
124+
return fmt.Errorf("error saving failed tests report with logs: %w", err)
125+
}
126+
fmt.Printf("Failed tests report with logs saved to %s\n", failedTestsReportWithLogsPath)
127+
128+
// Remove logs from test results for the report without logs
129+
for i := range failedReportWithLogs.Results {
130+
failedReportWithLogs.Results[i].Outputs = nil
131+
failedReportWithLogs.Results[i].PackageOutputs = nil
132+
}
133+
134+
// Save the failed tests report without logs
135+
failedTestsReportNoLogsPath := filepath.Join(outputDir, "failed-test-results.json")
136+
if err := reports.SaveReport(fs, failedTestsReportNoLogsPath, *failedReportWithLogs); err != nil {
137+
return fmt.Errorf("error saving failed tests report without logs: %w", err)
138+
}
139+
fmt.Printf("Failed tests report without logs saved to %s\n", failedTestsReportNoLogsPath)
140+
} else {
141+
fmt.Println("No failed tests found. Skipping generation of failed tests reports.")
142+
}
143+
144+
// Generate all-tests-summary.json
145+
if summaryFileName != "" {
146+
s = spinner.New(spinner.CharSets[11], 100*time.Millisecond)
147+
s.Suffix = " Generating summary json..."
148+
s.Start()
149+
150+
summaryFilePath := filepath.Join(outputDir, summaryFileName)
151+
err = generateAllTestsSummaryJSON(aggregatedReport, summaryFilePath, maxPassRatio)
152+
if err != nil {
153+
s.Stop()
154+
return fmt.Errorf("error generating summary json: %w", err)
155+
}
156+
s.Stop()
157+
fmt.Printf("Summary generated at %s\n", summaryFilePath)
158+
}
159+
160+
fmt.Println("Aggregation complete.")
161+
162+
return nil
163+
},
164+
}
165+
166+
func init() {
167+
AggregateResultsCmd.Flags().StringP("results-path", "p", "", "Path to the folder containing JSON test result files (required)")
168+
AggregateResultsCmd.Flags().StringP("output-path", "o", "./report", "Path to output the aggregated results (directory)")
169+
AggregateResultsCmd.Flags().StringP("summary-file-name", "s", "all-test-summary.json", "Name of the summary JSON file")
170+
AggregateResultsCmd.Flags().Float64P("max-pass-ratio", "", 1.0, "The maximum pass ratio threshold for a test to be considered flaky")
171+
AggregateResultsCmd.Flags().StringP("codeowners-path", "", "", "Path to the CODEOWNERS file")
172+
AggregateResultsCmd.Flags().StringP("repo-path", "", ".", "The path to the root of the repository/project")
173+
174+
AggregateResultsCmd.MarkFlagRequired("results-path")
175+
}
176+
177+
// New function to generate all-tests-summary.json
178+
func generateAllTestsSummaryJSON(report *reports.TestReport, outputPath string, maxPassRatio float64) error {
179+
summary := reports.GenerateSummaryData(report.Results, maxPassRatio)
180+
data, err := json.Marshal(summary)
181+
if err != nil {
182+
return fmt.Errorf("error marshaling summary data to JSON: %w", err)
183+
}
184+
185+
fs := reports.OSFileSystem{}
186+
jsonFile, err := fs.Create(outputPath)
187+
if err != nil {
188+
return fmt.Errorf("error creating file: %w", err)
189+
}
190+
defer jsonFile.Close()
191+
192+
_, err = jsonFile.Write(data)
193+
if err != nil {
194+
return fmt.Errorf("error writing data to file: %w", err)
195+
}
196+
197+
return nil
198+
}

0 commit comments

Comments
 (0)