Skip to content

TRT-2821: Fall back to aggregate tables for base stats in test_details - #3847

Merged
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
mstaeble:worktree-test-details-base-stats-fallback
Aug 4, 2026
Merged

TRT-2821: Fall back to aggregate tables for base stats in test_details#3847
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
mstaeble:worktree-test-details-base-stats-fallback

Conversation

@mstaeble

@mstaeble mstaeble commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Introduces TestDetailsSummary as the provider return type for test details queries, replacing raw per-run rows with pre-computed per-job stats and optional individual run details.
  • Adds SummarizeTestJobRuns to group raw rows by (job, test key) into summaries, applied consistently in both BigQuery and Postgres providers.
  • Adds a fallback in QueryBaseJobRunTestStatus (Postgres provider) to populate base statistics from aggregate tables (test_cumulative_summaries for prefix-sum releases, prow_ga_raw_test_data for GA releases) when per-run data is unavailable for older base releases. Aggregate summaries have no individual JobRuns, so the UI shows stats without broken run links.
  • Refactors test_details.go report generation to work with pre-summarized data, simplifying stats aggregation and fixing a bug where per-run counts were double-aggregated.
  • Bumps BigQuery cache key prefix from V2 to V3 to avoid stale deserialization after the type change.
  • Fixes TestDetailsSummary.TestKeyStr serialization (json:"-" removed) so test key grouping survives the BQ Redis cache round-trip.

Test plan

  • Unit test for SummarizeTestJobRuns lifecycle promotion logic
  • Integration tests for aggregate fallback (prefix-sum, GA, precedence over per-run, variant filtering, multi-job, zero-delta exclusion, no-suite ownership, HAVING filter)
  • Integration tests for test details report generation (aggregate base stats, last failure tracking, flake-as-failure mode)
  • Existing integration tests updated for summarized return type
  • make test passes
  • make lint passes

Staging verification

Ran local server against staging Postgres DB and BigQuery with the branch code. Tested with explicit query parameters (5.0 sample, 4.22 base, Build and Networking components).

Postgres path: per-run base data (4.22 base)

test_details component=Build testId=openshift-tests:c19899c904fc1be7fadc2812f438dc3a
  Base: success=471, fail=0, flake=0, rate=1.0
  Sample: success=125, fail=0, flake=0, rate=1.0
  Jobs: 18, base runs: 471, sample runs: 125
  Explanations: []

Postgres path: aggregate fallback (4.17 base)

test_details component=Build testId=openshift-tests:c19899c904fc1be7fadc2812f438dc3a baseRelease=4.17
  Jobs: 16, base runs: 0 (aggregate, no individual runs)
  Server log: "no per-run base test details found, falling back to aggregate tables" release=4.17

BigQuery path (4.22 base)

test_details component=Build testId=openshift-tests:c19899c904fc1be7fadc2812f438dc3a
  Base: success (non-zero), fail, flake present
  Jobs: 25, base+sample runs present
  Explanations: []

Networking test cross-path comparison

BQ:       Base success=613, Jobs: 25
Postgres: Base success=471, Jobs: 18
(Count differences expected due to BQ having broader job coverage)

CR grid (Postgres)

60 component rows returned, regressions detected correctly.

No errors in server logs across all requests.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Component readiness reports now provide aggregated per-test and per-job summaries with detailed run information.
    • Added fallback reporting from aggregate historical data when detailed base-release results are unavailable.
    • Improved support for variant filtering, metadata, failure tracking, and flake-as-failure reporting.
  • Bug Fixes

    • Improved lifecycle aggregation and status handling across base, override, and sample results.
    • Preserved job ordering and enhanced report consistency across data sources.
  • Tests

    • Expanded coverage for aggregate fallbacks, failures, flakes, variants, suites, metadata, and report details.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

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: automatic mode

@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Jul 29, 2026
@openshift-ci

openshift-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 29, 2026
@mstaeble
mstaeble force-pushed the worktree-test-details-base-stats-fallback branch 3 times, most recently from 232123b to ba1a34e Compare August 1, 2026 13:08
@mstaeble mstaeble changed the title [WIP] Populate base statistics in test_details from aggregate tables TRT-2821: Fall back to aggregate tables for base stats in test_details Aug 1, 2026
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Aug 1, 2026
@openshift-ci-robot

openshift-ci-robot commented Aug 1, 2026

Copy link
Copy Markdown

@mstaeble: This pull request references TRT-2821 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 "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

  • Introduces TestDetailsSummary as the provider return type for test details queries, replacing raw per-run rows with pre-computed per-job stats and optional individual run details.
  • Adds SummarizeTestJobRuns to group raw rows by (job, test key) into summaries, applied consistently in both BigQuery and Postgres providers.
  • Adds a fallback in QueryBaseJobRunTestStatus (Postgres provider) to populate base statistics from aggregate tables (test_cumulative_summaries for prefix-sum releases, prow_ga_raw_test_data for GA releases) when per-run data is unavailable for older base releases. Aggregate summaries have no individual JobRuns, so the UI shows stats without broken run links.
  • Refactors test_details.go report generation to work with pre-summarized data, simplifying stats aggregation and fixing a bug where per-run counts were double-aggregated.
  • Bumps BigQuery cache key prefix from V2 to V3 to avoid stale deserialization after the type change.

Test plan

  • Unit test for SummarizeTestJobRuns lifecycle promotion logic
  • Integration tests for aggregate fallback (prefix-sum, GA, precedence over per-run, variant filtering, multi-job, zero-delta exclusion, no-suite ownership, HAVING filter)
  • Integration tests for test details report generation (aggregate base stats, last failure tracking, flake-as-failure mode)
  • Existing integration tests updated for summarized return type
  • make test passes
  • make lint passes

@coderabbitai ignore

🤖 Generated with Claude Code

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.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@openshift-ci-robot Acknowledged. The owner of TRT-2821 must set its target version to 5.0.0.

You are interacting with an AI system.

@mstaeble

mstaeble commented Aug 1, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@mstaeble, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 51 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 3776beb9-77e0-4dbe-9739-561e5125ec30

📥 Commits

Reviewing files that changed from the base of the PR and between 66462d9 and 5140c74.

📒 Files selected for processing (12)
  • pkg/api/componentreadiness/component_report_test.go
  • pkg/api/componentreadiness/dataprovider/bigquery/provider.go
  • pkg/api/componentreadiness/dataprovider/bigquery/querygenerators.go
  • pkg/api/componentreadiness/dataprovider/interface.go
  • pkg/api/componentreadiness/dataprovider/mixed/provider.go
  • pkg/api/componentreadiness/dataprovider/postgres/provider.go
  • pkg/api/componentreadiness/middleware/releasefallback/releasefallback.go
  • pkg/api/componentreadiness/test_details.go
  • pkg/apis/api/componentreport/crstatus/summarize.go
  • pkg/apis/api/componentreport/crstatus/summarize_test.go
  • pkg/apis/api/componentreport/crstatus/types.go
  • test/integration/component_readiness_test.go

Walkthrough

This pull request replaces raw test job-run rows with TestDetailsSummary aggregates containing statistics, lifecycle metadata, and nested run details. PostgreSQL adds aggregate fallback queries when detailed data is unavailable. Providers and report generation now use the summary model.

Changes

Component readiness test-detail pipeline

Layer / File(s) Summary
Summary contract and aggregation
pkg/apis/api/componentreport/crstatus/types.go, pkg/apis/api/componentreport/crstatus/summarize.go, pkg/apis/api/componentreport/crstatus/summarize_test.go
Adds TestDetailsSummary and JobRunDetail. SummarizeTestJobRuns aggregates counts, metadata, lifecycle values, and nested run details.
Provider summary and fallback paths
pkg/api/componentreadiness/dataprovider/interface.go, pkg/api/componentreadiness/dataprovider/bigquery/*, pkg/api/componentreadiness/dataprovider/mixed/provider.go, pkg/api/componentreadiness/dataprovider/postgres/provider.go
Provider APIs return summaries. BigQuery summarizes query results. PostgreSQL uses detailed results or aggregate prefix-sum and GA queries with variant filtering.
Fallback wiring and report aggregation
pkg/api/componentreadiness/middleware/releasefallback/releasefallback.go, pkg/api/componentreadiness/test_details.go
Fallback and report processing consume summaries, extract metadata, convert nested runs to report statistics, track failures, and preserve sorting.
Fixtures and integration validation
pkg/api/componentreadiness/component_report_test.go, test/integration/component_readiness_test.go
Tests validate nested runs, aggregate fallback, filtering, metadata, lifecycle handling, and report statistics.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant QueryBaseJobRunTestStatus
  participant queryTestDetails
  participant AggregateFallback
  participant TestDetailsReport
  QueryBaseJobRunTestStatus->>queryTestDetails: fetch detailed test data
  alt Detailed data exists
    queryTestDetails-->>QueryBaseJobRunTestStatus: return summaries
  else Detailed data is absent
    QueryBaseJobRunTestStatus->>AggregateFallback: query aggregate statistics
    AggregateFallback-->>QueryBaseJobRunTestStatus: return summaries
  end
  QueryBaseJobRunTestStatus-->>TestDetailsReport: provide summarized status
  TestDetailsReport->>TestDetailsReport: build report statistics
Loading

Possibly related PRs

Suggested labels: lgtm

Suggested reviewers: petr-muller, smg247

🚥 Pre-merge checks | ✅ 18 | ❌ 3

❌ Failed checks (3 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 17.65% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Coverage For New Features ⚠️ Warning The PR fixes TestDetailsSummary.TestKeyStr JSON serialization, but feature tests contain no marshal/unmarshal or cache round-trip regression test for this fix. Add a unit test that marshals and unmarshals TestJobRunStatuses and asserts TestDetailsSummary.TestKeyStr remains populated and usable for grouping.
Single Responsibility And Clear Naming ⚠️ Warning The new TestDetailsSummary has 9 top-level fields spanning identity, statistics, run details, and metadata; aggregateTestDetailRow also has 9 fields. Split TestDetailsSummary into focused identity/statistics, metadata, and run-detail types, and reduce aggregateTestDetailRow or justify its projection shape.
✅ Passed checks (18 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the primary change: falling back to aggregate tables for base statistics in test details.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Go Error Handling ✅ Passed PR-added Go code has no panic calls, checks nullable JiraComponentID before dereference, and wraps new database/date errors with %w.
Sql Injection Prevention ✅ Passed New aggregate queries use static SQL plus ? placeholders; test IDs, releases, dates, and variant values pass through GORM bind arguments, and variant clauses insert only placeholders.
Excessive Css In React Should Use Styles ✅ Passed The full PR changes only Go files; it adds no React, JSX, TSX, CSS, or inline style code, so this check is not applicable.
Feature Documentation ✅ Passed The PR changes component-readiness data flow and models, but docs/features contains only the unrelated symptoms document; documentation updates are encouraged, not required.
Stable And Deterministic Test Names ✅ Passed Changed tests use static Go test and t.Run titles; no Ginkgo title calls or dynamic interpolation, pod/node/namespace, timestamps, IPs, UUIDs, or generated identifiers appear in titles.
Test Structure And Quality ✅ Passed The PR adds standard Go tests with testing/testify, not Ginkgo; no cluster operations or Eventually waits are present, and NewTestDB registers t.Cleanup for each test database.
Microshift Test Compatibility ✅ Passed The PR adds no Ginkgo e2e tests. All changed test files use standard Go testing.T, with no Describe, Context, When, or It declarations to assess.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The PR adds standard Go unit/integration tests only; it adds no Ginkgo e2e tests or multi-node cluster assumptions requiring SNO review.
Topology-Aware Scheduling Compatibility ✅ Passed The checked-out PR changes only Go data-provider and report helpers; its diff contains no deployment manifests, controllers, replicas, affinity, topology spread, node selectors, or PDBs.
Ote Binary Stdout Contract ✅ Passed PR additions contain no active stdout writes, klog calls, or suite entrypoints; the only fmt.Printf match is commented, and the new logrus call uses the default stderr logger.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed Changed tests use Go testing/testify only; no new Ginkgo e2e tests, IPv4 assumptions, or external connectivity indicators were found.
No-Weak-Crypto ✅ Passed The full PR diff adds no MD5, SHA-1, DES, RC4, Blowfish, ECB, crypto APIs, custom crypto, or secret/token comparisons; touched files have no crypto imports or calls.
Container-Privileges ✅ Passed The PR changes only Go source and tests. No changed container/K8s manifest enables privileged, host namespaces, SYS_ADMIN, or privilege escalation; the Dockerfile root step is justified and switche...
No-Sensitive-Data-In-Logs ✅ Passed The cumulative PR diff adds logs for a release name and encoded test key only; no passwords, tokens, PII, session IDs, hostnames, or customer data are logged.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (8)
pkg/apis/api/componentreport/crstatus/summarize.go (1)

27-27: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document that SuccessRate in the summary is provisional.

AddTestCount receives a hardcoded false for flakeAsFailure. The counts are independent of that flag, but Stats.SuccessRate is not. Consumers must recompute the rate with the request's FlakeAsFailure, as summarizeRecordedTestStats does in pkg/api/componentreadiness/test_details.go. A short comment prevents a future consumer from reading summary.Stats.SuccessRate as authoritative.

♻️ Proposed comment
+			// Counts are flake-policy independent; SuccessRate here is provisional and
+			// callers must recompute it with the request's FlakeAsFailure setting.
 			summary.Stats = summary.Stats.AddTestCount(row.Count, false)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/apis/api/componentreport/crstatus/summarize.go` at line 27, Add a concise
comment at the summary.Stats assignment in summarizeRecordedTestStats
documenting that SuccessRate is provisional because AddTestCount uses
flakeAsFailure=false, and that consumers must recompute it using the request’s
FlakeAsFailure setting.
pkg/apis/api/componentreport/crstatus/summarize_test.go (1)

12-70: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extend coverage beyond lifecycle promotion.

The table covers only Lifecycle. SummarizeTestJobRuns also implements behavior that a regression would hide:

  • Count aggregation across rows into Stats.
  • Skipping JobRuns entries when ProwJobRunID is empty (the aggregate fallback path depends on this).
  • First-non-empty selection for JiraComponent, JiraComponentID, and TestName.
  • Grouping of several test keys under one job, and stable first-seen ordering.

These are pure-logic checks and need no database. Do you want me to generate the additional table-driven cases?

As per path instructions: "Prefer table-driven Go tests with descriptive case names, and search the same package for existing test patterns before adding new tests."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/apis/api/componentreport/crstatus/summarize_test.go` around lines 12 -
70, Extend TestSummarizeTestJobRuns_LifecyclePromotion or add a companion
table-driven test to cover Stats count aggregation, skipping rows with empty
ProwJobRunID, first-non-empty JiraComponent/JiraComponentID/TestName selection,
and grouping multiple test keys under one job while preserving first-seen order.
Follow existing same-package test patterns and assert the complete summarized
output for each descriptive case.

Source: Path instructions

pkg/api/componentreadiness/dataprovider/postgres/provider.go (3)

483-486: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Log when the aggregate fallback is used.

The fallback is silent. Reports built from the aggregate path contain no JobRuns, so the UI shows no individual runs. A single structured log line makes that state diagnosable.

♻️ Proposed change
 	if len(result) > 0 {
 		return result, nil
 	}
+	log.WithField("release", reqOptions.BaseRelease.Name).
+		Info("no per-run base test details found, falling back to aggregate tables")
 	return p.queryBaseAggregateTestDetails(ctx, reqOptions)

As per coding guidelines: "Prefer structured logging, especially for names and IDs, and prefer log.WithField() over formatting values into log strings when appropriate."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/api/componentreadiness/dataprovider/postgres/provider.go` around lines
483 - 486, In the result fallback within the provider method, add one structured
log entry immediately before calling queryBaseAggregateTestDetails, using the
existing logger and fields for relevant names or IDs rather than formatting
values into the message. Keep the successful result return unchanged and
preserve the existing aggregate fallback behavior.

Source: Coding guidelines


629-635: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the repeated variant-filter append.

The same block now appears three times in this file: queryTestDetails (lines 378-384), buildAggregatePrefixSumQuery (lines 591-597), and here. A small helper that returns the clause and appends the args keeps the three call sites in sync.

♻️ Proposed helper
// appendVariantFilter appends the variant-combination subquery and its args when
// includeVariants produces a filter clause.
func appendVariantFilter(sqlQuery string, args []any, includeVariants map[string][]string) (string, []any) {
	if len(includeVariants) == 0 {
		return sqlQuery, args
	}
	filterClause, filterArgs := buildVariantFilterClause(includeVariants)
	if filterClause == "" {
		return sqlQuery, args
	}
	return sqlQuery + " AND pj.variant_combination_id IN (SELECT vc.id FROM variant_combinations vc WHERE " + filterClause + ")",
		append(args, filterArgs...)
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/api/componentreadiness/dataprovider/postgres/provider.go` around lines
629 - 635, Extract the duplicated variant-filter logic into an
appendVariantFilter helper that accepts the SQL string, args, and
includeVariants, then returns the updated values while preserving empty-input
and empty-clause behavior. Replace the repeated blocks in queryTestDetails,
buildAggregatePrefixSumQuery, and the shown query flow with calls to this helper
so all three sites remain consistent.

656-698: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the shared requested-variant filtering and key construction.

Lines 656-698 duplicate queryTestDetails lines 406-465: the requestedVariantsByTestID map build, the variant match loop, the filterByDBGroupBy call, the KeyWithVariants construction, and the big.Rat conversion of JiraComponentID. The two paths must stay behaviorally identical, so a shared helper reduces the risk that only one path is updated later.

A helper such as matchAndBuildTestKey(row testID string, variants map[string]string, requested map[string]map[string]string, dbGroupBy sets.Set[string]) (crtest.KeyWithVariants, bool) covers both call sites.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/api/componentreadiness/dataprovider/postgres/provider.go` around lines
656 - 698, Extract the duplicated requested-variant matching and test-key
construction from queryTestDetails and the shown result-building loop into a
shared helper, such as matchAndBuildTestKey. Have it apply the requested variant
filter, call filterByDBGroupBy, and build the crtest.KeyWithVariants
consistently; update both callers to use it and preserve the existing
JiraComponentID big.Rat conversion in the surrounding row-processing logic.
pkg/api/componentreadiness/test_details.go (2)

502-519: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Share the metadata-merge and lifecycle-promotion rule with crstatus.

Lines 503-518 repeat the exact logic in pkg/apis/api/componentreport/crstatus/summarize.go lines 41-56: first-non-empty selection for JiraComponent, JiraComponentID, and TestName, plus promotion of Lifecycle to "informing". Two copies of the promotion rule can diverge if a new lifecycle value is added.

Move the rule into an exported helper in crstatus and call it from both places. extractMetadata also does not use its receiver c, so it can become a package-level function.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/api/componentreadiness/test_details.go` around lines 502 - 519, Move the
shared metadata merge and lifecycle-promotion logic from
ComponentReportGenerator.extractMetadata and crstatus summarization into an
exported helper in crstatus, then call that helper from both callers. Convert
extractMetadata to a package-level function because it does not use c, and
preserve the existing first-non-empty field selection and "informing" lifecycle
promotion behavior.

458-483: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document the one-summary-per-job precondition.

Both inner loops assign jobStats.SampleJobName and jobStats.BaseJobName on every iteration. If a job maps to more than one summary, the last summary wins and the earlier job names are lost, while the counts still accumulate across all of them.

Callers satisfy the precondition today: GenerateDetailsReportForTest receives statuses already split by test key. A short comment records that assumption for future callers.

♻️ Proposed comment
 	jobNames := sets.New(slices.Collect(maps.Keys(baseStatus))...)
 	jobNames.Insert(slices.Collect(maps.Keys(sampleStatus))...)
+	// Callers pass statuses already split by test key, so each job maps to at most
+	// one summary here; the job-name assignments below rely on that.
 	for job := range jobNames {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/api/componentreadiness/test_details.go` around lines 458 - 483, Add a
concise comment near the sampleStatus/baseStatus processing in the job loop
documenting that callers provide at most one summary per job, with
GenerateDetailsReportForTest supplying statuses split by test key. Do not alter
the existing aggregation or name-assignment logic.
test/integration/component_readiness_test.go (1)

2622-2635: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Positional indexing of JobRuns depends on the query ordering.

The assertions map JobRuns[0], [1], and [2] to the pass, fail, and flake runs. That holds only because queryTestDetails applies ORDER BY pjr.timestamp and the summarizer appends in row order. If the ordering clause changes, these assertions fail with a message that does not name the cause.

Selecting each run by ProwJobRunID makes the intent explicit and removes the ordering dependency.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/integration/component_readiness_test.go` around lines 2622 - 2635,
Replace the positional JobRuns[0], JobRuns[1], and JobRuns[2] lookups in the
pass/fail/flake assertions with selections by each run’s ProwJobRunID. Preserve
the existing count and success/flake assertions while making each detail lookup
independent of queryTestDetails ordering.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pkg/api/componentreadiness/dataprovider/postgres/provider.go`:
- Around line 501-504: Update the doc comment for
PostgresProvider.queryBaseAggregateTestDetails to state that it returns
map[string][]crstatus.TestDetailsSummary values instead of TestJobRunRows
entries.

In `@pkg/api/componentreadiness/middleware/releasefallback/releasefallback.go`:
- Line 252: Update the logging call in the release fallback test-key handling to
use Debug-level structured logging with testKeyStr as a named field, rather than
concatenating it into the Infof format string. Preserve the existing message
context while ensuring arbitrary key contents, including percent signs, are
logged safely.

In `@pkg/api/componentreadiness/test_details.go`:
- Around line 410-411: Update summarizeRecordedTestStats to add an explanation
when aggregate base summaries contain counts but no JobRuns, so the report
explains why BaseJobRunStats has no individual runs. Populate
testStats.Explanations only for this missing-detail condition and preserve empty
explanations for cases where base runs are available.

In `@pkg/apis/api/componentreport/crstatus/types.go`:
- Around line 52-56: Update GetDataFromCacheOrGenerate to restore TestKeyStr for
cached TestDetailsSummary and TestJobRunRows values by deriving it from each
corresponding TestKey after json.Unmarshal. Ensure both cached result types
retain the same grouped test-key behavior as freshly generated data.

---

Nitpick comments:
In `@pkg/api/componentreadiness/dataprovider/postgres/provider.go`:
- Around line 483-486: In the result fallback within the provider method, add
one structured log entry immediately before calling
queryBaseAggregateTestDetails, using the existing logger and fields for relevant
names or IDs rather than formatting values into the message. Keep the successful
result return unchanged and preserve the existing aggregate fallback behavior.
- Around line 629-635: Extract the duplicated variant-filter logic into an
appendVariantFilter helper that accepts the SQL string, args, and
includeVariants, then returns the updated values while preserving empty-input
and empty-clause behavior. Replace the repeated blocks in queryTestDetails,
buildAggregatePrefixSumQuery, and the shown query flow with calls to this helper
so all three sites remain consistent.
- Around line 656-698: Extract the duplicated requested-variant matching and
test-key construction from queryTestDetails and the shown result-building loop
into a shared helper, such as matchAndBuildTestKey. Have it apply the requested
variant filter, call filterByDBGroupBy, and build the crtest.KeyWithVariants
consistently; update both callers to use it and preserve the existing
JiraComponentID big.Rat conversion in the surrounding row-processing logic.

In `@pkg/api/componentreadiness/test_details.go`:
- Around line 502-519: Move the shared metadata merge and lifecycle-promotion
logic from ComponentReportGenerator.extractMetadata and crstatus summarization
into an exported helper in crstatus, then call that helper from both callers.
Convert extractMetadata to a package-level function because it does not use c,
and preserve the existing first-non-empty field selection and "informing"
lifecycle promotion behavior.
- Around line 458-483: Add a concise comment near the sampleStatus/baseStatus
processing in the job loop documenting that callers provide at most one summary
per job, with GenerateDetailsReportForTest supplying statuses split by test key.
Do not alter the existing aggregation or name-assignment logic.

In `@pkg/apis/api/componentreport/crstatus/summarize_test.go`:
- Around line 12-70: Extend TestSummarizeTestJobRuns_LifecyclePromotion or add a
companion table-driven test to cover Stats count aggregation, skipping rows with
empty ProwJobRunID, first-non-empty JiraComponent/JiraComponentID/TestName
selection, and grouping multiple test keys under one job while preserving
first-seen order. Follow existing same-package test patterns and assert the
complete summarized output for each descriptive case.

In `@pkg/apis/api/componentreport/crstatus/summarize.go`:
- Line 27: Add a concise comment at the summary.Stats assignment in
summarizeRecordedTestStats documenting that SuccessRate is provisional because
AddTestCount uses flakeAsFailure=false, and that consumers must recompute it
using the request’s FlakeAsFailure setting.

In `@test/integration/component_readiness_test.go`:
- Around line 2622-2635: Replace the positional JobRuns[0], JobRuns[1], and
JobRuns[2] lookups in the pass/fail/flake assertions with selections by each
run’s ProwJobRunID. Preserve the existing count and success/flake assertions
while making each detail lookup independent of queryTestDetails ordering.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: d67c79c2-a323-4559-9b9b-1895f58b479f

📥 Commits

Reviewing files that changed from the base of the PR and between f66444a and ba1a34e.

📒 Files selected for processing (12)
  • pkg/api/componentreadiness/component_report_test.go
  • pkg/api/componentreadiness/dataprovider/bigquery/provider.go
  • pkg/api/componentreadiness/dataprovider/bigquery/querygenerators.go
  • pkg/api/componentreadiness/dataprovider/interface.go
  • pkg/api/componentreadiness/dataprovider/mixed/provider.go
  • pkg/api/componentreadiness/dataprovider/postgres/provider.go
  • pkg/api/componentreadiness/middleware/releasefallback/releasefallback.go
  • pkg/api/componentreadiness/test_details.go
  • pkg/apis/api/componentreport/crstatus/summarize.go
  • pkg/apis/api/componentreport/crstatus/summarize_test.go
  • pkg/apis/api/componentreport/crstatus/types.go
  • test/integration/component_readiness_test.go

Comment thread pkg/api/componentreadiness/dataprovider/postgres/provider.go
Comment thread pkg/api/componentreadiness/middleware/releasefallback/releasefallback.go Outdated
Comment thread pkg/api/componentreadiness/test_details.go
Comment thread pkg/apis/api/componentreport/crstatus/types.go
@mstaeble
mstaeble force-pushed the worktree-test-details-base-stats-fallback branch from ba1a34e to 9d2a7f8 Compare August 1, 2026 14:32
@openshift-ci openshift-ci Bot added the ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review label Aug 1, 2026
@mstaeble
mstaeble marked this pull request as ready for review August 1, 2026 14:41
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 1, 2026
@openshift-ci
openshift-ci Bot requested review from petr-muller and smg247 August 1, 2026 14:42
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e

@mstaeble
mstaeble force-pushed the worktree-test-details-base-stats-fallback branch from 9d2a7f8 to 1f5d6e3 Compare August 4, 2026 03:52
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e

@mstaeble

mstaeble commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.


Your included review limit is currently reached under our Fair Usage Limits Policy. This review may still proceed through usage-based billing if eligible. Your next included review will be available in 59 minutes.

@mstaeble

mstaeble commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
pkg/api/componentreadiness/test_details.go (1)

514-520: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider a shared helper for lifecycle promotion.

This promotion rule repeats the logic in SummarizeTestJobRuns at pkg/apis/api/componentreport/crstatus/summarize.go lines 52-58. A small exported helper, for example crstatus.PromoteLifecycle(current, incoming string) string, would hold the rule in one place. Named constants for "informing" and "blocking" would also remove the repeated string literals across both files.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/api/componentreadiness/test_details.go` around lines 514 - 520, Extract
the duplicated lifecycle promotion rule from the surrounding test-detail logic
and SummarizeTestJobRuns into an exported crstatus.PromoteLifecycle(current,
incoming string) helper. Update both call sites to use it, and introduce shared
named constants for the informing and blocking lifecycle values instead of
repeating string literals.
pkg/api/componentreadiness/dataprovider/postgres/provider.go (1)

662-693: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Consider extracting the shared variant filter and key builder.

Lines 662-693 duplicate lines 409-440 of queryTestDetails: the same requestedVariantsByTestID map build, the same requested-variant match loop, and the same filterByDBGroupBy plus KeyWithVariants construction. A helper that takes the variant map, dbGroupBy, and the row's test ID and returns the encoded key plus a match flag would remove the duplication and keep both paths aligned when filtering rules change.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/api/componentreadiness/dataprovider/postgres/provider.go` around lines
662 - 693, Extract the shared requested-variant filtering and key construction
from queryTestDetails and the current result-building loop into a helper. Have
it accept the variant map, dbGroupBy, and row test ID, return the encoded
crtest.KeyWithVariants plus a match flag, and reuse it in both paths while
preserving existing filtering behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@pkg/api/componentreadiness/dataprovider/postgres/provider.go`:
- Around line 662-693: Extract the shared requested-variant filtering and key
construction from queryTestDetails and the current result-building loop into a
helper. Have it accept the variant map, dbGroupBy, and row test ID, return the
encoded crtest.KeyWithVariants plus a match flag, and reuse it in both paths
while preserving existing filtering behavior.

In `@pkg/api/componentreadiness/test_details.go`:
- Around line 514-520: Extract the duplicated lifecycle promotion rule from the
surrounding test-detail logic and SummarizeTestJobRuns into an exported
crstatus.PromoteLifecycle(current, incoming string) helper. Update both call
sites to use it, and introduce shared named constants for the informing and
blocking lifecycle values instead of repeating string literals.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 6f3f1248-01a6-420f-a402-9390775dc6b1

📥 Commits

Reviewing files that changed from the base of the PR and between 001ea40 and 1f5d6e3.

📒 Files selected for processing (12)
  • pkg/api/componentreadiness/component_report_test.go
  • pkg/api/componentreadiness/dataprovider/bigquery/provider.go
  • pkg/api/componentreadiness/dataprovider/bigquery/querygenerators.go
  • pkg/api/componentreadiness/dataprovider/interface.go
  • pkg/api/componentreadiness/dataprovider/mixed/provider.go
  • pkg/api/componentreadiness/dataprovider/postgres/provider.go
  • pkg/api/componentreadiness/middleware/releasefallback/releasefallback.go
  • pkg/api/componentreadiness/test_details.go
  • pkg/apis/api/componentreport/crstatus/summarize.go
  • pkg/apis/api/componentreport/crstatus/summarize_test.go
  • pkg/apis/api/componentreport/crstatus/types.go
  • test/integration/component_readiness_test.go

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e

@neisw

neisw commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Aug 4, 2026
@mstaeble
mstaeble force-pushed the worktree-test-details-base-stats-fallback branch from 8aff205 to 66462d9 Compare August 4, 2026 18:54
@openshift-ci openshift-ci Bot removed the lgtm Indicates that a PR is ready to be merged. label Aug 4, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
test/integration/component_readiness_test.go (2)

1609-1614: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Align the prefix-sum date comment with the value used.

The comment states the base window is [2024-05-15, 2024-06-01) and that lookupEnd = 2024-06-01. The earlier seed helper at lines 228-232 documents the opposite convention: lookupEnd = end - 1. Both conventions now appear in the same file, so a reader cannot tell which one the query implements.

State why this suite uses 2024-06-01 directly, or reference the query behavior that makes both correct.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/integration/component_readiness_test.go` around lines 1609 - 1614,
Clarify the comments surrounding baseLookupStart and baseLookupEnd in the
prefix-sum setup to explain why this suite passes 2024-06-01 directly as
lookupEnd, or reference the query behavior that makes this inclusive value
correct. Keep the existing date values and cumulative-summary calls unchanged.

1598-1647: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Consider extracting the repeated aggregate-fallback fixture setup.

Most subtests in TestQueryBaseJobRunTestStatus_AggregateFallback repeat the same block: one variant combination, one prow job, one test, one suite, one ownership, two createCumulativeSummary calls with the same prefix sums, and the same opts construction with RequestedVariants and IncludeVariants set to aws/ovn. The new report tests at lines 3211-3359 repeat the same aggregate base seed as well.

Extract a small helper such as seedAggregateFallback(t, dbc, release, jobName, testName, suiteName, uniqueID) that returns the created rows, plus an options helper for the aws/ovn request. This reduces the risk that one subtest drifts from the others and keeps the assertions visible.

As per coding guidelines: "Prefer table-driven Go tests with descriptive case names, and search the same package for existing test patterns before adding new tests."

Also applies to: 1904-1940, 2020-2068, 2070-2116

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@test/integration/component_readiness_test.go` around lines 1598 - 1647,
Extract the repeated aggregate-fallback fixture creation from
TestQueryBaseJobRunTestStatus_AggregateFallback into a helper such as
seedAggregateFallback, parameterized by release, job name, test name, suite
name, and ownership ID, returning the created entities needed by assertions. Add
a focused options helper for the shared aws/ovn RequestedVariants and
IncludeVariants setup, and update the affected subtests and aggregate report
tests to reuse both helpers while keeping assertions and descriptive
table-driven cases intact.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@test/integration/component_readiness_test.go`:
- Around line 1609-1614: Clarify the comments surrounding baseLookupStart and
baseLookupEnd in the prefix-sum setup to explain why this suite passes
2024-06-01 directly as lookupEnd, or reference the query behavior that makes
this inclusive value correct. Keep the existing date values and
cumulative-summary calls unchanged.
- Around line 1598-1647: Extract the repeated aggregate-fallback fixture
creation from TestQueryBaseJobRunTestStatus_AggregateFallback into a helper such
as seedAggregateFallback, parameterized by release, job name, test name, suite
name, and ownership ID, returning the created entities needed by assertions. Add
a focused options helper for the shared aws/ovn RequestedVariants and
IncludeVariants setup, and update the affected subtests and aggregate report
tests to reuse both helpers while keeping assertions and descriptive
table-driven cases intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Pro Plus

Run ID: 6a137991-e7e2-4536-89a6-dda6bc7269ad

📥 Commits

Reviewing files that changed from the base of the PR and between 1f5d6e3 and 66462d9.

📒 Files selected for processing (12)
  • pkg/api/componentreadiness/component_report_test.go
  • pkg/api/componentreadiness/dataprovider/bigquery/provider.go
  • pkg/api/componentreadiness/dataprovider/bigquery/querygenerators.go
  • pkg/api/componentreadiness/dataprovider/interface.go
  • pkg/api/componentreadiness/dataprovider/mixed/provider.go
  • pkg/api/componentreadiness/dataprovider/postgres/provider.go
  • pkg/api/componentreadiness/middleware/releasefallback/releasefallback.go
  • pkg/api/componentreadiness/test_details.go
  • pkg/apis/api/componentreport/crstatus/summarize.go
  • pkg/apis/api/componentreport/crstatus/summarize_test.go
  • pkg/apis/api/componentreport/crstatus/types.go
  • test/integration/component_readiness_test.go
🚧 Files skipped from review as they are similar to previous changes (10)
  • pkg/api/componentreadiness/dataprovider/interface.go
  • pkg/api/componentreadiness/dataprovider/bigquery/querygenerators.go
  • pkg/api/componentreadiness/dataprovider/mixed/provider.go
  • pkg/api/componentreadiness/dataprovider/bigquery/provider.go
  • pkg/api/componentreadiness/component_report_test.go
  • pkg/apis/api/componentreport/crstatus/summarize_test.go
  • pkg/api/componentreadiness/middleware/releasefallback/releasefallback.go
  • pkg/api/componentreadiness/test_details.go
  • pkg/apis/api/componentreport/crstatus/types.go
  • pkg/api/componentreadiness/dataprovider/postgres/provider.go

@mstaeble
mstaeble force-pushed the worktree-test-details-base-stats-fallback branch from 66462d9 to 50bdbaf Compare August 4, 2026 18:57
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mstaeble
mstaeble force-pushed the worktree-test-details-base-stats-fallback branch from 50bdbaf to 5140c74 Compare August 4, 2026 19:02
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e

@neisw

neisw commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Aug 4, 2026
@openshift-ci

openshift-ci Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mstaeble, neisw

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

The pull request process is described 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

@openshift-merge-bot
openshift-merge-bot Bot merged commit 7cc8f39 into openshift:main Aug 4, 2026
4 of 10 checks passed
@mstaeble
mstaeble deleted the worktree-test-details-base-stats-fallback branch August 4, 2026 21:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants