Skip to content

TRT-2518: Add variant OS and JobTier to promotion check#2763

Open
xueqzhan wants to merge 1 commit intoopenshift:masterfrom
xueqzhan:jobtier-os
Open

TRT-2518: Add variant OS and JobTier to promotion check#2763
xueqzhan wants to merge 1 commit intoopenshift:masterfrom
xueqzhan:jobtier-os

Conversation

@xueqzhan
Copy link

Adds support for OS variants (RHEL 10) and JobTier filtering to the feature gate promotion analyzer.

@openshift-ci-robot
Copy link

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Mar 13, 2026
@openshift-ci-robot
Copy link

openshift-ci-robot commented Mar 13, 2026

@xueqzhan: This pull request references TRT-2518 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Adds support for OS variants (RHEL 10) and JobTier filtering to the feature gate promotion analyzer.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 13, 2026

Hello @xueqzhan! Some important instructions when contributing to openshift/api:
API design plays an important part in the user experience of OpenShift and as such API PRs are subject to a high level of scrutiny to ensure they follow our best practices. If you haven't already done so, please review the OpenShift API Conventions and ensure that your proposed changes are compliant. Following these conventions will help expedite the api review process for your PR.

@coderabbitai
Copy link

coderabbitai bot commented Mar 13, 2026

📝 Walkthrough

Walkthrough

The pull request modifies the feature gate test analyzer to implement a two-tier validation system distinguishing blocking errors from non-blocking warnings. The JobVariant struct is expanded with OS, JobTiers, and Optional fields to model OS-specific variants and configurable job tiers. Function signatures throughout the codebase are updated to propagate these new parameters: checkIfTestingIsSufficient now returns ValidationResult objects, buildHTMLFeatureGateData accepts blockingErrors explicitly, and Sippy query functions accept os and jobTiers parameters. HTML and Markdown output rendering is updated to display OS and JobTiers information. A new optional RHEL-10 variant is introduced to demonstrate non-blocking variants.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: adding variant OS and JobTier support to the promotion check, which aligns with the substantial changes throughout the codebase.
Description check ✅ Passed The description accurately summarizes the changeset, mentioning support for OS variants (RHEL 10) and JobTier filtering in the feature gate promotion analyzer.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.11.3)

Error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented
The command is terminated due to an error: build linters: unable to load custom analyzer "kubeapilinter": tools/_output/bin/kube-api-linter.so, plugin: not implemented


Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can scan for known vulnerabilities in your dependencies using OSV Scanner.

OSV Scanner will automatically detect and report security vulnerabilities in your project's dependencies. No additional configuration is required.

@openshift-ci openshift-ci bot added the size/L Denotes a PR that changes 100-499 lines, ignoring generated files. label Mar 13, 2026
@qodo-code-review
Copy link

ⓘ You are approaching your monthly quota for Qodo. Upgrade your plan

Review Summary by Qodo

Add OS variants and JobTier filtering to feature gate promotion analyzer

✨ Enhancement

Grey Divider

Walkthroughs

Description
• Add OS variant and JobTier support to promotion check validation
• Distinguish blocking errors from non-blocking warnings for optional variants
• Implement JobTier validation and filtering in Sippy queries
• Update HTML output to display OS and JobTier information
Diagram
flowchart LR
  A["Feature Gate Validation"] --> B["Check Testing Sufficiency"]
  B --> C["Separate Blocking vs Warnings"]
  C --> D["Optional Variants"]
  C --> E["Required Variants"]
  D --> F["Non-blocking Warnings"]
  E --> G["Blocking Errors"]
  B --> H["Validate JobTiers"]
  H --> I["Generate Sippy Queries"]
  I --> J["Query per JobTier"]
  B --> K["Update HTML Output"]
  K --> L["Display OS and JobTiers"]
Loading

Grey Divider

File Changes

1. tools/codegen/cmd/featuregate-test-analyzer.go ✨ Enhancement +122/-15

Refactor validation to support optional variants and JobTiers

• Refactored validation to return ValidationResult structs that distinguish blocking errors from
 non-blocking warnings
• Added Optional field to JobVariant to mark optional variants like RHEL 10
• Separated error handling to only fail the job on blocking errors, not warnings
• Added OS and JobTiers fields to JobVariant struct and HTML output
• Implemented validateJobTiers() function to validate JobTier values
• Updated markdown and HTML generation to display OS and JobTier information
• Modified checkIfTestingIsSufficient() to use ValidationResult with IsWarning flag

tools/codegen/cmd/featuregate-test-analyzer.go


2. tools/codegen/cmd/featuregate-test-analyzer_test.go 🧪 Tests +209/-1

Add tests for optional variant validation logic

• Uncommented Test_listTestResultFor test to enable manual testing
• Added comprehensive test suite Test_checkIfTestingIsSufficient_OptionalVariants with 7 test
 cases
• Test cases cover required vs optional variants with various failure scenarios
• Validates that optional variants produce warnings while required variants produce blocking errors

tools/codegen/cmd/featuregate-test-analyzer_test.go


3. tools/codegen/pkg/sippy/json_types.go ✨ Enhancement +84/-38

Add OS and JobTier support to Sippy query generation

• Updated QueriesFor() function signature to accept os and jobTiers parameters
• Refactored query building to support multiple JobTier queries (one per tier)
• Added OS variant filtering to base query items
• Implemented JobTier parsing with default fallback to standard/informing/blocking
• Updated BuildSippyTestAnalysisURL() to include OS parameter in URL generation

tools/codegen/pkg/sippy/json_types.go


View more (1)
4. tools/codegen/pkg/utils/html.go ✨ Enhancement +3/-1

Add OS and JobTiers to HTML variant display

• Added OS and JobTiers fields to HTMLVariantColumn struct
• Updated HTML template to display OS and JobTiers information in table headers
• Modified column header rendering to conditionally show OS and JobTiers when present

tools/codegen/pkg/utils/html.go


Grey Divider

Qodo Logo

@qodo-code-review
Copy link

qodo-code-review bot commented Mar 13, 2026

Code Review by Qodo

🐞 Bugs (4) 📘 Rule violations (0) 📎 Requirement gaps (0)

Grey Divider


Action required

1. JobTier results overwritten 🐞 Bug ✓ Correctness
Description
With JobTier support, a single variant now triggers multiple Sippy queries (one per tier), but
listTestResultForVariant overwrites per-test run counts when CurrentRuns meets the threshold, so the
final totals depend on query order and can be wrong. This can incorrectly pass/fail the promotion
sufficiency checks for a feature gate.
Code

tools/codegen/pkg/sippy/json_types.go[R101-133]

+	// Parse JobTiers - comma-separated string, default to standard/informing/blocking if empty
+	var jobTiersList []string
+	if jobTiers == "" {
+		jobTiersList = []string{"standard", "informing", "blocking"}
+	} else {
+		// Split by comma and trim whitespace
+		for _, tier := range strings.Split(jobTiers, ",") {
+			if trimmed := strings.TrimSpace(tier); trimmed != "" {
+				jobTiersList = append(jobTiersList, trimmed)
+			}
+		}
+	}
+
+	// Generate one query per JobTier (to work around API's single LinkOperator limitation)
+	var queries []*SippyQueryStruct
+	for _, jobTier := range jobTiersList {
+		// Copy base items for this query
+		items := make([]SippyQueryItem, len(baseItems))
+		copy(items, baseItems)
+
+		// Add JobTier filter
+		items = append(items, SippyQueryItem{
+			ColumnField:   "variants",
+			Not:           false,
+			OperatorValue: "contains",
+			Value:         fmt.Sprintf("JobTier:%s", jobTier),
+		})
+
+		queries = append(queries, &SippyQueryStruct{
+			Items:        items,
+			LinkOperator: "and",
+		})
	}
Evidence
QueriesFor now returns multiple queries (one per JobTier), and listTestResultForVariant iterates
across all queries but uses assignment (not accumulation) for the “7-day sufficient” branch, which
will overwrite previously accumulated results from earlier tiers.

tools/codegen/pkg/sippy/json_types.go[101-133]
tools/codegen/cmd/featuregate-test-analyzer.go[837-900]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`QueriesFor` now emits multiple Sippy queries per variant (one per JobTier). `listTestResultForVariant` iterates over those queries but overwrites `TotalRuns/SuccessfulRuns/...` when `CurrentRuns >= requiredNumberOfTestRunsPerVariant`, causing incorrect totals across tiers.

### Issue Context
This PR intentionally queries each JobTier separately and merges results. The merge logic must therefore be additive across queries.

### Fix Focus Areas
- tools/codegen/cmd/featuregate-test-analyzer.go[876-897]
- tools/codegen/pkg/sippy/json_types.go[101-133]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


2. Empty JobTier skips queries 🐞 Bug ✓ Correctness
Description
JobTier strings containing only commas/whitespace (e.g. "," or " , ") pass validateJobTiers but
produce an empty jobTiersList, causing QueriesFor to return zero queries and
listTestResultForVariant to make no API calls. This silently returns empty test results and can
wrongly report insufficient testing.
Code

tools/codegen/cmd/featuregate-test-analyzer.go[R667-685]

+func validateJobTiers(jobVariant JobVariant) error {
+	if jobVariant.JobTiers == "" {
+		return nil // Empty is valid - will default to standard,informing,blocking
+	}
+
+	validTiers := map[string]bool{
+		"standard":  true,
+		"informing": true,
+		"blocking":  true,
+	}
+
+	for _, tier := range strings.Split(jobVariant.JobTiers, ",") {
+		tier = strings.TrimSpace(tier)
+		if tier != "" && !validTiers[tier] {
+			return fmt.Errorf("invalid JobTier %q in variant %+v - must be one of: standard, informing, blocking", tier, jobVariant)
+		}
+	}
+	return nil
+}
Evidence
validateJobTiers ignores empty trimmed segments, while QueriesFor only appends non-empty tiers; if
all segments are empty, jobTiersList stays empty and the query-generation loop returns an empty
query slice, which listTestResultForVariant then iterates over zero times.

tools/codegen/cmd/featuregate-test-analyzer.go[667-685]
tools/codegen/pkg/sippy/json_types.go[101-133]
tools/codegen/cmd/featuregate-test-analyzer.go[829-841]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
Malformed `JobTiers` strings like `","` or whitespace-only values currently pass validation but result in *zero* JobTier filters, producing zero Sippy queries and silently empty results.

### Issue Context
`validateJobTiers` only rejects unknown non-empty tiers. `QueriesFor` drops empty trimmed tiers and does not apply a default if the resulting list is empty.

### Fix Focus Areas
- tools/codegen/cmd/featuregate-test-analyzer.go[667-685]
- tools/codegen/pkg/sippy/json_types.go[101-113]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


3. Network test enabled 🐞 Bug ⛯ Reliability
Description
Test_listTestResultFor is no longer skipped and calls listTestResultFor, which performs live HTTPS
requests to sippy.dptools.openshift.org. This makes unit tests non-hermetic and likely flaky/slow in
CI environments.
Code

tools/codegen/cmd/featuregate-test-analyzer_test.go[R61-64]

+			//t.Skip("this is for ease of manual testing")

			got, err := listTestResultFor(tt.args.featureGate, sets.New[string](tt.args.clusterProfile))
			if (err != nil) != tt.wantErr {
Evidence
The skip is commented out, so the test executes and invokes listTestResultFor; that code path
constructs an http.Client and calls the external Sippy API host directly.

tools/codegen/cmd/featuregate-test-analyzer_test.go[59-66]
tools/codegen/cmd/featuregate-test-analyzer.go[801-864]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
A test that performs live network calls to Sippy is now enabled by default, which is unsuitable for unit test suites and CI.

### Issue Context
The tested functions call out to `https://sippy.dptools.openshift.org/api/tests`.

### Fix Focus Areas
- tools/codegen/cmd/featuregate-test-analyzer_test.go[59-66]
- tools/codegen/cmd/featuregate-test-analyzer.go[801-864]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

4. Warnings hidden in HTML 🐞 Bug ✧ Quality
Description
Optional-variant warnings are excluded from the HTML artifact because only blockingErrors are passed
into buildHTMLFeatureGateData and Sufficient is computed from blockingErrors only. The HTML report
can therefore show a green “Sufficient” banner even when warnings exist, which is misleading for
HTML consumers.
Code

tools/codegen/cmd/featuregate-test-analyzer.go[R241-243]

+		// Only add blocking errors to the error list (warnings don't fail the job)
+		errs = append(errs, blockingErrors...)
+		featureGateHTMLData = append(featureGateHTMLData, buildHTMLFeatureGateData(enabledFeatureGate, testingResults, blockingErrors, release))
Evidence
Run() explicitly passes only blockingErrors into the HTML builder, and the HTML template only
renders success vs insufficient based on the Sufficient flag, with no warning section.

tools/codegen/cmd/featuregate-test-analyzer.go[241-243]
tools/codegen/cmd/featuregate-test-analyzer.go[337-342]
tools/codegen/pkg/utils/html.go[75-89]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
The HTML output currently cannot communicate non-blocking warnings for optional variants, and may present an overly optimistic status.

### Issue Context
Markdown output includes warnings, but HTML is built only from `blockingErrors`.

### Fix Focus Areas
- tools/codegen/cmd/featuregate-test-analyzer.go[191-243]
- tools/codegen/cmd/featuregate-test-analyzer.go[263-342]
- tools/codegen/pkg/utils/html.go[7-22]
- tools/codegen/pkg/utils/html.go[75-89]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

ⓘ The new review experience is currently in Beta. Learn more

Grey Divider

Qodo Logo

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 13, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign deads2k for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
tools/codegen/cmd/featuregate-test-analyzer.go (1)

614-636: Consider updating OrderedJobVariants.Less to include new fields.

The sorting implementation for OrderedJobVariants doesn't consider the new OS, JobTiers, or Optional fields. If two variants differ only by these fields, their relative ordering will be non-deterministic. This could lead to inconsistent output ordering across runs.

♻️ Suggested fix to include new fields in sorting
 func (a OrderedJobVariants) Less(i, j int) bool {
 	if strings.Compare(a[i].Topology, a[j].Topology) < 0 {
 		return true
 	} else if strings.Compare(a[i].Topology, a[j].Topology) > 0 {
 		return false
 	}
 
 	if strings.Compare(a[i].Cloud, a[j].Cloud) < 0 {
 		return true
 	} else if strings.Compare(a[i].Cloud, a[j].Cloud) > 0 {
 		return false
 	}
 
 	if strings.Compare(a[i].Architecture, a[j].Architecture) < 0 {
 		return true
 	} else if strings.Compare(a[i].Architecture, a[j].Architecture) > 0 {
 		return false
 	}
 
+	if strings.Compare(a[i].NetworkStack, a[j].NetworkStack) < 0 {
+		return true
+	} else if strings.Compare(a[i].NetworkStack, a[j].NetworkStack) > 0 {
+		return false
+	}
+
+	if strings.Compare(a[i].OS, a[j].OS) < 0 {
+		return true
+	} else if strings.Compare(a[i].OS, a[j].OS) > 0 {
+		return false
+	}
+
+	if strings.Compare(a[i].JobTiers, a[j].JobTiers) < 0 {
+		return true
+	} else if strings.Compare(a[i].JobTiers, a[j].JobTiers) > 0 {
+		return false
+	}
+
 	return false
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/codegen/cmd/featuregate-test-analyzer.go` around lines 614 - 636,
OrderedJobVariants.Less currently only compares Topology, Cloud, and
Architecture, causing non-deterministic ordering when OS, JobTiers, or Optional
differ; update the Less method to perform additional comparisons after
Architecture in this order: compare OS (string), then compare JobTiers (ensure
deterministic comparison by joining/sorting slices or comparing lengths then
elements), then compare Optional (boolean: false < true), returning true/false
appropriately at each step, and finally return false if all compared fields are
equal. Ensure you reference the OrderedJobVariants type and its Less method when
making changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tools/codegen/cmd/featuregate-test-analyzer_test.go`:
- Line 61: The test calls listTestResultFor() which performs real HTTP requests;
restore the t.Skip (uncomment the existing t.Skip("this is for ease of manual
testing")) or replace external calls with a mocked HTTP transport so CI does not
make network requests; specifically change the test in
featuregate-test-analyzer_test.go to either call t.Skip at the top of the test
or inject a mock http.Client/transport into listTestResultFor (or wrap
listTestResultFor with a helper that accepts an http.Client) and use a fake
roundtripper returning deterministic responses for the dummy feature gate names.

---

Nitpick comments:
In `@tools/codegen/cmd/featuregate-test-analyzer.go`:
- Around line 614-636: OrderedJobVariants.Less currently only compares Topology,
Cloud, and Architecture, causing non-deterministic ordering when OS, JobTiers,
or Optional differ; update the Less method to perform additional comparisons
after Architecture in this order: compare OS (string), then compare JobTiers
(ensure deterministic comparison by joining/sorting slices or comparing lengths
then elements), then compare Optional (boolean: false < true), returning
true/false appropriately at each step, and finally return false if all compared
fields are equal. Ensure you reference the OrderedJobVariants type and its Less
method when making changes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 41be5d92-a7a4-40ea-90ef-2353a5840568

📥 Commits

Reviewing files that changed from the base of the PR and between 5e946e2 and cece552.

📒 Files selected for processing (4)
  • tools/codegen/cmd/featuregate-test-analyzer.go
  • tools/codegen/cmd/featuregate-test-analyzer_test.go
  • tools/codegen/pkg/sippy/json_types.go
  • tools/codegen/pkg/utils/html.go

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Skip("this is for ease of manual testing")
//t.Skip("this is for ease of manual testing")
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check git history to understand if this test was always meant to be skipped
git log --oneline -5 -- tools/codegen/cmd/featuregate-test-analyzer_test.go

# Check if there are any comments explaining when this test should run
rg -B2 -A2 "manual testing" tools/codegen/cmd/featuregate-test-analyzer_test.go

Repository: openshift/api

Length of output: 324


🏁 Script executed:

# Read the test function to understand what it does
sed -n '57,80p' tools/codegen/cmd/featuregate-test-analyzer_test.go

# Check if listTestResultFor makes actual HTTP requests
rg -B5 -A10 "func listTestResultFor" tools/codegen/cmd/featuregate-test-analyzer_test.go

# Check if there's any mocking or network request setup in the test file
rg "http|mock|Mock|client|Client" tools/codegen/cmd/featuregate-test-analyzer_test.go | head -20

Repository: openshift/api

Length of output: 763


🏁 Script executed:

# Find the implementation of listTestResultFor
rg -B2 -A20 "^func listTestResultFor" tools/codegen/cmd/featuregate-test-analyzer_test.go

# Also check if there's a non-test version
rg -B2 -A20 "^func listTestResultFor" tools/codegen/cmd/

# Check the actual commit diff
git show --no-patch --format="%B" cece552d

Repository: openshift/api

Length of output: 4226


🏁 Script executed:

# Check the full commit diff to see if the skip was intentionally removed
git show cece552d -- tools/codegen/cmd/featuregate-test-analyzer_test.go | head -100

# Check if there are any test skip markers or CI configuration
rg "skip|Skip" tools/codegen/cmd/featuregate-test-analyzer_test.go

Repository: openshift/api

Length of output: 2568


Restore t.Skip or add mocking to prevent external network requests in CI.

The t.Skip comment was added (while commented out) in the initial commit of this new test file. This test calls listTestResultFor(), which makes actual HTTP requests to sippy.dptools.openshift.org using real TLS configuration. The comment indicates this test is "for ease of manual testing only," yet the skip is commented out, causing the test to execute in CI and make real network calls with dummy feature gate names. This creates risk of CI flakiness or unexpected behavior. Either restore the skip or mock the HTTP transport.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tools/codegen/cmd/featuregate-test-analyzer_test.go` at line 61, The test
calls listTestResultFor() which performs real HTTP requests; restore the t.Skip
(uncomment the existing t.Skip("this is for ease of manual testing")) or replace
external calls with a mocked HTTP transport so CI does not make network
requests; specifically change the test in featuregate-test-analyzer_test.go to
either call t.Skip at the top of the test or inject a mock http.Client/transport
into listTestResultFor (or wrap listTestResultFor with a helper that accepts an
http.Client) and use a fake roundtripper returning deterministic responses for
the dummy feature gate names.

Comment on lines +101 to 133
// Parse JobTiers - comma-separated string, default to standard/informing/blocking if empty
var jobTiersList []string
if jobTiers == "" {
jobTiersList = []string{"standard", "informing", "blocking"}
} else {
// Split by comma and trim whitespace
for _, tier := range strings.Split(jobTiers, ",") {
if trimmed := strings.TrimSpace(tier); trimmed != "" {
jobTiersList = append(jobTiersList, trimmed)
}
}
}

// Generate one query per JobTier (to work around API's single LinkOperator limitation)
var queries []*SippyQueryStruct
for _, jobTier := range jobTiersList {
// Copy base items for this query
items := make([]SippyQueryItem, len(baseItems))
copy(items, baseItems)

// Add JobTier filter
items = append(items, SippyQueryItem{
ColumnField: "variants",
Not: false,
OperatorValue: "contains",
Value: fmt.Sprintf("JobTier:%s", jobTier),
})

queries = append(queries, &SippyQueryStruct{
Items: items,
LinkOperator: "and",
})
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

1. Jobtier results overwritten 🐞 Bug ✓ Correctness

With JobTier support, a single variant now triggers multiple Sippy queries (one per tier), but
listTestResultForVariant overwrites per-test run counts when CurrentRuns meets the threshold, so the
final totals depend on query order and can be wrong. This can incorrectly pass/fail the promotion
sufficiency checks for a feature gate.
Agent Prompt
### Issue description
`QueriesFor` now emits multiple Sippy queries per variant (one per JobTier). `listTestResultForVariant` iterates over those queries but overwrites `TotalRuns/SuccessfulRuns/...` when `CurrentRuns >= requiredNumberOfTestRunsPerVariant`, causing incorrect totals across tiers.

### Issue Context
This PR intentionally queries each JobTier separately and merges results. The merge logic must therefore be additive across queries.

### Fix Focus Areas
- tools/codegen/cmd/featuregate-test-analyzer.go[876-897]
- tools/codegen/pkg/sippy/json_types.go[101-133]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +667 to +685
func validateJobTiers(jobVariant JobVariant) error {
if jobVariant.JobTiers == "" {
return nil // Empty is valid - will default to standard,informing,blocking
}

validTiers := map[string]bool{
"standard": true,
"informing": true,
"blocking": true,
}

for _, tier := range strings.Split(jobVariant.JobTiers, ",") {
tier = strings.TrimSpace(tier)
if tier != "" && !validTiers[tier] {
return fmt.Errorf("invalid JobTier %q in variant %+v - must be one of: standard, informing, blocking", tier, jobVariant)
}
}
return nil
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

2. Empty jobtier skips queries 🐞 Bug ✓ Correctness

JobTier strings containing only commas/whitespace (e.g. "," or " , ") pass validateJobTiers but
produce an empty jobTiersList, causing QueriesFor to return zero queries and
listTestResultForVariant to make no API calls. This silently returns empty test results and can
wrongly report insufficient testing.
Agent Prompt
### Issue description
Malformed `JobTiers` strings like `","` or whitespace-only values currently pass validation but result in *zero* JobTier filters, producing zero Sippy queries and silently empty results.

### Issue Context
`validateJobTiers` only rejects unknown non-empty tiers. `QueriesFor` drops empty trimmed tiers and does not apply a default if the resulting list is empty.

### Fix Focus Areas
- tools/codegen/cmd/featuregate-test-analyzer.go[667-685]
- tools/codegen/pkg/sippy/json_types.go[101-113]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

Comment on lines +61 to 64
//t.Skip("this is for ease of manual testing")

got, err := listTestResultFor(tt.args.featureGate, sets.New[string](tt.args.clusterProfile))
if (err != nil) != tt.wantErr {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Action required

3. Network test enabled 🐞 Bug ⛯ Reliability

Test_listTestResultFor is no longer skipped and calls listTestResultFor, which performs live HTTPS
requests to sippy.dptools.openshift.org. This makes unit tests non-hermetic and likely flaky/slow in
CI environments.
Agent Prompt
### Issue description
A test that performs live network calls to Sippy is now enabled by default, which is unsuitable for unit test suites and CI.

### Issue Context
The tested functions call out to `https://sippy.dptools.openshift.org/api/tests`.

### Fix Focus Areas
- tools/codegen/cmd/featuregate-test-analyzer_test.go[59-66]
- tools/codegen/cmd/featuregate-test-analyzer.go[801-864]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 13, 2026

@xueqzhan: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
t.Skip("this is for ease of manual testing")
//t.Skip("this is for ease of manual testing")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did we mean to comment this out?

Architecture: "amd64",
Topology: "ha",
OS: "rhel10",
Optional: true, // RHEL 10 is optional in 4.22, will be required in OCP 5
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will optionality be represented on the rendered HTML page?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. size/L Denotes a PR that changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants