Skip to content

Commit 3cc0780

Browse files
committed
Add separate send-to-splunk cmd
1 parent 066af40 commit 3cc0780

File tree

10 files changed

+444
-357
lines changed

10 files changed

+444
-357
lines changed

tools/flakeguard/cmd/aggregate_results.go

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,6 @@ var AggregateResultsCmd = &cobra.Command{
3131
githubWorkflowName, _ := cmd.Flags().GetString("github-workflow-name")
3232
githubWorkflowRunURL, _ := cmd.Flags().GetString("github-workflow-run-url")
3333
reportID, _ := cmd.Flags().GetString("report-id")
34-
splunkURL, _ := cmd.Flags().GetString("splunk-url")
35-
splunkToken, _ := cmd.Flags().GetString("splunk-token")
36-
splunkEvent, _ := cmd.Flags().GetString("splunk-event")
3734

3835
initialDirSize, err := getDirSize(resultsPath)
3936
if err != nil {
@@ -59,7 +56,6 @@ var AggregateResultsCmd = &cobra.Command{
5956
reports.WithRepoPath(repoPath),
6057
reports.WithCodeOwnersPath(codeOwnersPath),
6158
reports.WithReportID(reportID),
62-
reports.WithSplunk(splunkURL, splunkToken, splunkEvent),
6359
reports.WithBranchName(branchName),
6460
reports.WithBaseSha(baseSHA),
6561
reports.WithHeadSha(headSHA),
@@ -165,9 +161,6 @@ func init() {
165161
AggregateResultsCmd.Flags().String("github-workflow-name", "", "GitHub workflow name for the test report")
166162
AggregateResultsCmd.Flags().String("github-workflow-run-url", "", "GitHub workflow run URL for the test report")
167163
AggregateResultsCmd.Flags().String("report-id", "", "Optional identifier for the test report. Will be generated if not provided")
168-
AggregateResultsCmd.Flags().String("splunk-url", "", "Optional url to simultaneously send the test results to splunk")
169-
AggregateResultsCmd.Flags().String("splunk-token", "", "Optional Splunk HEC token to simultaneously send the test results to splunk")
170-
AggregateResultsCmd.Flags().String("splunk-event", "manual", "Optional Splunk event to send as the triggering event for the test results")
171164

172165
if err := AggregateResultsCmd.MarkFlagRequired("results-path"); err != nil {
173166
log.Fatal().Err(err).Msg("Error marking flag as required")

tools/flakeguard/cmd/generate_report.go

Lines changed: 6 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,18 @@
11
package cmd
22

33
import (
4-
"context"
54
"encoding/json"
65
"fmt"
76
"os"
87
"path/filepath"
9-
"strings"
108
"time"
119

1210
"github.com/briandowns/spinner"
13-
"github.com/google/go-github/v67/github"
1411
"github.com/rs/zerolog/log"
1512
"github.com/smartcontractkit/chainlink-testing-framework/tools/flakeguard/reports"
1613
"github.com/spf13/cobra"
17-
"golang.org/x/oauth2"
1814
)
1915

20-
const exampleGitHubToken = "EXAMPLE_GITHUB_TOKEN" //nolint:gosec
21-
2216
var GenerateReportCmd = &cobra.Command{
2317
Use: "generate-report",
2418
Short: "Generate test reports from aggregated results that can be posted to GitHub",
@@ -30,23 +24,16 @@ var GenerateReportCmd = &cobra.Command{
3024
outputDir, _ := cmd.Flags().GetString("output-path")
3125
maxPassRatio, _ := cmd.Flags().GetFloat64("max-pass-ratio")
3226
generatePRComment, _ := cmd.Flags().GetBool("generate-pr-comment")
33-
githubRepo, _ := cmd.Flags().GetString("github-repository")
34-
githubRunID, _ := cmd.Flags().GetInt64("github-run-id")
35-
artifactName, _ := cmd.Flags().GetString("failed-tests-artifact-name")
27+
failedLogsURL, _ := cmd.Flags().GetString("failed-logs-url")
28+
29+
failedLogsArtifactName := "failed-test-results-with-logs.json"
3630

3731
initialDirSize, err := getDirSize(outputDir)
3832
if err != nil {
3933
log.Error().Err(err).Str("path", outputDir).Msg("Error getting initial directory size")
4034
// intentionally don't exit here, as we can still proceed with the generation
4135
}
4236

43-
// Get the GitHub token from environment variable
44-
githubToken := os.Getenv("GITHUB_TOKEN")
45-
if githubToken == "" {
46-
log.Error().Msg("GITHUB_TOKEN environment variable is not set")
47-
os.Exit(ErrorExitCode)
48-
}
49-
5037
// Load the aggregated report
5138
s := spinner.New(spinner.CharSets[11], 100*time.Millisecond)
5239
s.Suffix = " Loading aggregated test report..."
@@ -72,19 +59,6 @@ var GenerateReportCmd = &cobra.Command{
7259
fmt.Println()
7360
log.Info().Msg("Successfully loaded aggregated test report")
7461

75-
// Check if there are failed tests
76-
hasFailedTests := aggregatedReport.SummaryData.FailedRuns > 0
77-
78-
var artifactLink string
79-
if hasFailedTests && githubRepo != "" && githubRunID != 0 && artifactName != "" {
80-
// Fetch artifact link from GitHub API
81-
artifactLink, err = fetchArtifactLinkWithRetry(githubToken, githubRepo, githubRunID, artifactName, 5, 5*time.Second)
82-
if err != nil {
83-
log.Error().Err(err).Msg("Error fetching artifact link")
84-
os.Exit(ErrorExitCode)
85-
}
86-
}
87-
8862
// Create output directory if it doesn't exist
8963
if err := fs.MkdirAll(outputDir, 0755); err != nil {
9064
log.Error().Err(err).Msg("Error creating output directory")
@@ -96,7 +70,7 @@ var GenerateReportCmd = &cobra.Command{
9670
s.Suffix = " Generating GitHub summary markdown..."
9771
s.Start()
9872

99-
err = generateGitHubSummaryMarkdown(aggregatedReport, filepath.Join(outputDir, "all-test"), artifactLink, artifactName)
73+
err = generateGitHubSummaryMarkdown(aggregatedReport, filepath.Join(outputDir, "all-test"), failedLogsURL, failedLogsArtifactName)
10074
if err != nil {
10175
s.Stop()
10276
fmt.Println()
@@ -147,8 +121,8 @@ var GenerateReportCmd = &cobra.Command{
147121
currentCommitSHA,
148122
repoURL,
149123
actionRunID,
150-
artifactName,
151-
artifactLink,
124+
failedLogsArtifactName,
125+
failedLogsURL,
152126
maxPassRatio,
153127
)
154128
if err != nil {
@@ -192,82 +166,6 @@ func init() {
192166
}
193167
}
194168

195-
func fetchArtifactLink(githubToken, githubRepo string, githubRunID int64, artifactName string) (string, error) {
196-
if githubToken == exampleGitHubToken {
197-
return "https://example-artifact-link.com", nil
198-
}
199-
ctx := context.Background()
200-
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: githubToken})
201-
tc := oauth2.NewClient(ctx, ts)
202-
client := github.NewClient(tc)
203-
204-
// Split owner/repo
205-
repoParts := strings.SplitN(githubRepo, "/", 2)
206-
if len(repoParts) != 2 {
207-
return "", fmt.Errorf("invalid format for --github-repository, expected owner/repo")
208-
}
209-
owner, repo := repoParts[0], repoParts[1]
210-
211-
opts := &github.ListOptions{PerPage: 100} // The max GitHub allows is 100 per page
212-
var allArtifacts []*github.Artifact
213-
214-
// Paginate through all artifacts
215-
for {
216-
artifacts, resp, err := client.Actions.ListWorkflowRunArtifacts(ctx, owner, repo, githubRunID, opts)
217-
if err != nil {
218-
return "", fmt.Errorf("error listing artifacts: %w", err)
219-
}
220-
221-
allArtifacts = append(allArtifacts, artifacts.Artifacts...)
222-
223-
if resp.NextPage == 0 {
224-
// No more pages
225-
break
226-
}
227-
// Move to the next page
228-
opts.Page = resp.NextPage
229-
}
230-
231-
// Find the artifact
232-
for _, artifact := range allArtifacts {
233-
if artifact.GetName() == artifactName {
234-
artifactID := artifact.GetID()
235-
artifactURL := fmt.Sprintf("https://github.com/%s/%s/actions/runs/%d/artifacts/%d",
236-
owner, repo, githubRunID, artifactID)
237-
return artifactURL, nil
238-
}
239-
}
240-
241-
return "", fmt.Errorf("artifact '%s' not found in the workflow run", artifactName)
242-
}
243-
244-
func fetchArtifactLinkWithRetry(
245-
githubToken, githubRepo string,
246-
githubRunID int64, artifactName string,
247-
maxRetries int, delay time.Duration,
248-
) (string, error) {
249-
var lastErr error
250-
for attempt := 1; attempt <= maxRetries; attempt++ {
251-
link, err := fetchArtifactLink(githubToken, githubRepo, githubRunID, artifactName)
252-
if err == nil {
253-
// Found the artifact link successfully
254-
return link, nil
255-
}
256-
257-
// If this was our last attempt, return the error
258-
lastErr = err
259-
if attempt == maxRetries {
260-
break
261-
}
262-
263-
// Otherwise wait and retry
264-
log.Printf("[Attempt %d/%d] Artifact not yet available. Retrying in %s...", attempt, maxRetries, delay)
265-
time.Sleep(delay)
266-
}
267-
268-
return "", fmt.Errorf("failed to fetch artifact link after %d retries: %w", maxRetries, lastErr)
269-
}
270-
271169
func generateGitHubSummaryMarkdown(report *reports.TestReport, outputPath, artifactLink, artifactName string) error {
272170
fs := reports.OSFileSystem{}
273171
mdFileName := outputPath + "-summary.md"
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"os"
7+
"strings"
8+
"time"
9+
10+
"github.com/google/go-github/v67/github"
11+
"github.com/rs/zerolog/log"
12+
"github.com/spf13/cobra"
13+
"golang.org/x/oauth2"
14+
)
15+
16+
const (
17+
exampleGitHubToken = "EXAMPLE_GITHUB_TOKEN" //nolint:gosec
18+
)
19+
20+
// GetGHArtifactLinkCmd fetches the artifact link from GitHub API.
21+
var GetGHArtifactLinkCmd = &cobra.Command{
22+
Use: "get-gh-artifact",
23+
Short: "Fetch artifact link from GitHub API",
24+
Run: func(cmd *cobra.Command, args []string) {
25+
// Get flag values
26+
githubRepo, _ := cmd.Flags().GetString("github-repository")
27+
githubRunID, _ := cmd.Flags().GetInt64("github-run-id")
28+
artifactName, _ := cmd.Flags().GetString("failed-tests-artifact-name")
29+
30+
// Get the GitHub token from environment variable
31+
githubToken := os.Getenv("GITHUB_TOKEN")
32+
if githubToken == "" {
33+
log.Error().Msg("GITHUB_TOKEN environment variable is not set")
34+
os.Exit(ErrorExitCode)
35+
}
36+
37+
// Fetch artifact link from GitHub API with retry logic
38+
artifactLink, err := fetchArtifactLinkWithRetry(githubToken, githubRepo, githubRunID, artifactName, 5, 5*time.Second)
39+
if err != nil {
40+
log.Error().Err(err).Msg("Error fetching artifact link")
41+
os.Exit(ErrorExitCode)
42+
}
43+
44+
fmt.Println("Artifact link:", artifactLink)
45+
},
46+
}
47+
48+
func init() {
49+
GetGHArtifactLinkCmd.Flags().String("github-repository", "", "The GitHub repository in the format owner/repo (required)")
50+
GetGHArtifactLinkCmd.Flags().Int64("github-run-id", 0, "The GitHub Actions run ID (required)")
51+
GetGHArtifactLinkCmd.Flags().String("failed-tests-artifact-name", "failed-test-results-with-logs.json", "The name of the failed tests artifact (default 'failed-test-results-with-logs.json')")
52+
53+
if err := GetGHArtifactLinkCmd.MarkFlagRequired("github-repository"); err != nil {
54+
log.Error().Err(err).Msg("Error marking github-repository flag as required")
55+
os.Exit(ErrorExitCode)
56+
}
57+
if err := GetGHArtifactLinkCmd.MarkFlagRequired("github-run-id"); err != nil {
58+
log.Error().Err(err).Msg("Error marking github-run-id flag as required")
59+
os.Exit(ErrorExitCode)
60+
}
61+
}
62+
63+
// fetchArtifactLink uses the GitHub API to retrieve the artifact link.
64+
func fetchArtifactLink(githubToken, githubRepo string, githubRunID int64, artifactName string) (string, error) {
65+
// If using the example token, return a fake link.
66+
if githubToken == exampleGitHubToken {
67+
return "https://example-artifact-link.com", nil
68+
}
69+
ctx := context.Background()
70+
ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: githubToken})
71+
tc := oauth2.NewClient(ctx, ts)
72+
client := github.NewClient(tc)
73+
74+
// Split owner and repo from the provided repository string.
75+
repoParts := strings.SplitN(githubRepo, "/", 2)
76+
if len(repoParts) != 2 {
77+
return "", fmt.Errorf("invalid format for --github-repository, expected owner/repo")
78+
}
79+
owner, repo := repoParts[0], repoParts[1]
80+
81+
opts := &github.ListOptions{PerPage: 100} // maximum per page allowed by GitHub
82+
var allArtifacts []*github.Artifact
83+
84+
// Paginate through all artifacts.
85+
for {
86+
artifacts, resp, err := client.Actions.ListWorkflowRunArtifacts(ctx, owner, repo, githubRunID, opts)
87+
if err != nil {
88+
return "", fmt.Errorf("error listing artifacts: %w", err)
89+
}
90+
91+
allArtifacts = append(allArtifacts, artifacts.Artifacts...)
92+
93+
if resp.NextPage == 0 {
94+
break
95+
}
96+
opts.Page = resp.NextPage
97+
}
98+
99+
// Search for the artifact by name.
100+
for _, artifact := range allArtifacts {
101+
if artifact.GetName() == artifactName {
102+
artifactID := artifact.GetID()
103+
artifactURL := fmt.Sprintf("https://github.com/%s/%s/actions/runs/%d/artifacts/%d",
104+
owner, repo, githubRunID, artifactID)
105+
return artifactURL, nil
106+
}
107+
}
108+
109+
return "", fmt.Errorf("artifact '%s' not found in the workflow run", artifactName)
110+
}
111+
112+
// fetchArtifactLinkWithRetry attempts to fetch the artifact link with retry logic.
113+
func fetchArtifactLinkWithRetry(githubToken, githubRepo string, githubRunID int64, artifactName string, maxRetries int, delay time.Duration) (string, error) {
114+
var lastErr error
115+
for attempt := 1; attempt <= maxRetries; attempt++ {
116+
link, err := fetchArtifactLink(githubToken, githubRepo, githubRunID, artifactName)
117+
if err == nil {
118+
return link, nil
119+
}
120+
121+
lastErr = err
122+
if attempt == maxRetries {
123+
break
124+
}
125+
126+
log.Printf("[Attempt %d/%d] Artifact not yet available. Retrying in %s...", attempt, maxRetries, delay)
127+
time.Sleep(delay)
128+
}
129+
130+
return "", fmt.Errorf("failed to fetch artifact link after %d retries: %w", maxRetries, lastErr)
131+
}

0 commit comments

Comments
 (0)