Skip to content
Closed
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
56 changes: 48 additions & 8 deletions pkg/variantregistry/ocp.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,12 +161,13 @@ ORDER BY j.prowjob_job_name;
}

var (
wg sync.WaitGroup
parallelism = 20
jobCh = make(chan *prowJobLastRun)
count atomic.Int64
variantsByJobMu sync.Mutex
variantsByJob = make(map[string]map[string]string)
wg sync.WaitGroup
parallelism = 20
jobCh = make(chan *prowJobLastRun)
count atomic.Int64
variantsByJobMu sync.Mutex
variantsByJob = make(map[string]map[string]string)
variantsByJobSource = make(map[string]string) // tracks which original job name was used
)

// Producer
Expand Down Expand Up @@ -234,11 +235,39 @@ ORDER BY j.prowjob_job_name;
jLog.WithField("gcs_bucket", jlr.GCSBucket).WithField("url", jlr.URL.StringVal).Error("job had no gcs bucket or prow job url, proceeding without")
}

variants := v.CalculateVariantsForJob(jLog, jlr.JobName, clusterData)
normalizedJobName := normalizeJobNameForVariants(jlr.JobName)
variants := v.CalculateVariantsForJob(jLog, normalizedJobName, clusterData)

// Handle collision resolution when multiple job names normalize to the same key.
// This is temporary transition logic for the openshift-release master->main rename.
// TODO(sgoeddel): Remove this collision handling logic after confirming no master jobs exist
// in query results (master jobs fully aged out).
variantsByJobMu.Lock()
variantsByJob[jlr.JobName] = variants
existingSource := variantsByJobSource[normalizedJobName]
shouldUpdate := false

if existingSource == "" {
// No existing entry, always insert
shouldUpdate = true
} else if strings.Contains(existingSource, "-master-") && strings.Contains(jlr.JobName, "-main-") {
// Prefer main over master for deterministic collision resolution
shouldUpdate = true
jLog.WithField("existing_source", existingSource).WithField("new_source", jlr.JobName).Info("replacing master variant with main variant")
} else {
// Keep existing entry (either main already exists, or both are master/main, first wins)
jLog.WithField("existing_source", existingSource).WithField("new_source", jlr.JobName).Debug("keeping existing variant, skipping duplicate")
}

if shouldUpdate {
variantsByJob[normalizedJobName] = variants
variantsByJobSource[normalizedJobName] = jlr.JobName
}
variantsByJobMu.Unlock()

count.Add(1)
if normalizedJobName != jlr.JobName {
jLog.WithField("original_name", jlr.JobName).WithField("normalized_name", normalizedJobName).Info("normalized job name")
}
jLog.WithField("variants", variants).WithField("count", count.Load()).Info("calculated variants")
}
}
Expand All @@ -252,6 +281,17 @@ ORDER BY j.prowjob_job_name;
return variantsByJob, nil
}

// normalizeJobNameForVariants normalizes job names to handle transitions like master -> main.
// This ensures that jobs renamed from master to main are treated as the same job in the variant registry.
// Currently only applies to openshift/release jobs.
func normalizeJobNameForVariants(jobName string) string {
// Only normalize openshift-release jobs, using Replace (not ReplaceAll) to change only the first occurrence
if strings.Contains(jobName, "openshift-release-master") {
return strings.Replace(jobName, "-master-", "-main-", 1)
}
return jobName
}

// fileVariantsToIgnore are values in the cluster-data.json that vary by run, and are not consistent for the job itself.
// These are unsuited for variants.
var fileVariantsToIgnore = map[string]bool{
Expand Down
41 changes: 41 additions & 0 deletions pkg/variantregistry/ocp_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1790,3 +1790,44 @@ func TestVariantsSnapshot(t *testing.T) {
t.Logf("\n****** Run `make update-variants` to update the snapshot and accept these changes.")
}
}

func TestNormalizeJobNameForVariants(t *testing.T) {
tests := []struct {
name string
jobName string
expected string
}{
{
name: "openshift-release master to main",
jobName: "periodic-ci-openshift-release-master-nightly-4.16-e2e-aws-ovn",
expected: "periodic-ci-openshift-release-main-nightly-4.16-e2e-aws-ovn",
},
{
name: "openshift-release ci master to main",
jobName: "periodic-ci-openshift-release-master-ci-4.16-e2e-azure-ovn-upgrade",
expected: "periodic-ci-openshift-release-main-ci-4.16-e2e-azure-ovn-upgrade",
},
{
name: "non-openshift-release master unchanged",
jobName: "periodic-ci-openshift-multiarch-master-nightly-4.17-ocp-e2e-aws-ovn",
expected: "periodic-ci-openshift-multiarch-master-nightly-4.17-ocp-e2e-aws-ovn",
},
{
name: "already main stays main",
jobName: "periodic-ci-openshift-release-main-nightly-4.16-e2e-aws-ovn",
expected: "periodic-ci-openshift-release-main-nightly-4.16-e2e-aws-ovn",
},
{
name: "other repos with master unchanged",
jobName: "periodic-ci-openshift-hive-master-e2e-aws",
expected: "periodic-ci-openshift-hive-master-e2e-aws",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := normalizeJobNameForVariants(tt.jobName)
assert.Equal(t, tt.expected, result, "normalization failed for %s", tt.jobName)
})
}
}