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
5 changes: 3 additions & 2 deletions .claude/settings.local.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,10 @@
"Bash(mkdir:*)",
"Bash(make lint:*)",
"Bash(make:*)",
"Bash(./ddtest:*)"
"Bash(./ddtest:*)",
"Bash(git diff:*)"
],
"deny": [],
"defaultMode": "acceptEdits"
}
}
}
73 changes: 73 additions & 0 deletions internal/runner/dd_test_optimization.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,13 @@ import (
"fmt"
"log/slog"
"maps"
"os"
"regexp"
"strings"
"time"

"github.com/DataDog/ddtest/civisibility/constants"
"github.com/DataDog/ddtest/civisibility/utils"
"github.com/DataDog/ddtest/internal/settings"
"github.com/DataDog/ddtest/internal/testoptimization"
"golang.org/x/sync/errgroup"
Expand Down Expand Up @@ -55,6 +60,7 @@ func (tr *TestRunner) PrepareTestOptimization(ctx context.Context) error {
var fullDiscoverySucceeded bool
var fullDiscoveryErr error
var fastDiscoveryErr error
tr.testSuiteDurations = make(map[string]map[string]testoptimization.TestSuiteDurationInfo)

g, _ := errgroup.WithContext(ctx)

Expand All @@ -77,6 +83,8 @@ func (tr *TestRunner) PrepareTestOptimization(ctx context.Context) error {
}
}

tr.fetchAndStoreTestSuiteDurations()

startTime := time.Now()
slog.Info("Fetching skippable tests from Datadog...")
skippableTests = tr.optimizationClient.GetSkippableTests()
Expand Down Expand Up @@ -178,3 +186,68 @@ func (tr *TestRunner) PrepareTestOptimization(ctx context.Context) error {

return nil
}

func initializeDurationsFetchInputs() (string, string, error) {
ciTags := utils.GetCITags()
repositoryURL := ciTags[constants.GitRepositoryURL]
if repositoryURL == "" {
return "", "", fmt.Errorf("repository URL is required")
}

service := os.Getenv("DD_SERVICE")
if service == "" {
repoRegex := regexp.MustCompile(`(?m)/([a-zA-Z0-9\-_.]*)$`)
matches := repoRegex.FindStringSubmatch(repositoryURL)
if len(matches) > 1 {
repositoryURL = strings.TrimSuffix(matches[1], ".git")
}
service = repositoryURL
}

return ciTags[constants.GitRepositoryURL], service, nil
}

func (tr *TestRunner) fetchAndStoreTestSuiteDurations() {
repositoryURL, service, err := initializeDurationsFetchInputs()
if err != nil {
logDurationsAPIError(err)
tr.testSuiteDurations = make(map[string]map[string]testoptimization.TestSuiteDurationInfo)
return
}

durations, err := tr.durationsClient.GetTestSuiteDurations(repositoryURL, service)
if err != nil {
logDurationsAPIError(err)
tr.testSuiteDurations = make(map[string]map[string]testoptimization.TestSuiteDurationInfo)
return
}

tr.storeTestSuiteDurations(repositoryURL, service, durations)
}

func (tr *TestRunner) storeTestSuiteDurations(
repositoryURL, service string,
durations map[string]map[string]testoptimization.TestSuiteDurationInfo,
) {
totalSuites := countTestSuites(durations)
if totalSuites == 0 {
slog.Warn("Test durations API returned no test suites", "service", service, "repositoryURL", repositoryURL)
tr.testSuiteDurations = make(map[string]map[string]testoptimization.TestSuiteDurationInfo)
return
}

slog.Debug("Found test suite durations", "service", service, "repositoryURL", repositoryURL, "testSuitesCount", totalSuites)
tr.testSuiteDurations = durations
}

func countTestSuites(durations map[string]map[string]testoptimization.TestSuiteDurationInfo) int {
totalSuites := 0
for _, suites := range durations {
totalSuites += len(suites)
}
return totalSuites
}

func logDurationsAPIError(err error) {
slog.Error("Test durations API errored", "error", err)
}
Loading
Loading