Skip to content

TRT-2814: Eliminate prow_job_runs_report_matview#3828

Open
mstaeble wants to merge 1 commit into
openshift:mainfrom
mstaeble:TRT-2814-eliminate-job-runs-matview
Open

TRT-2814: Eliminate prow_job_runs_report_matview#3828
mstaeble wants to merge 1 commit into
openshift:mainfrom
mstaeble:TRT-2814-eliminate-job-runs-matview

Conversation

@mstaeble

@mstaeble mstaeble commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replaces prow_job_runs_report_matview with a two-phase direct query in JobsRunsReportFromDB: Phase 1 paginates from base tables (prow_job_runs + prow_jobs), Phase 2 enriches the paginated page with test counts, test name arrays, pull request data, and annotations via errgroup.
  • Removes the matview definition and its entry from PostgresMatViews, eliminating a ~90-second refresh that blocked data loading.
  • Refactors pkg/filter to export FilterItemToSQL (column-expression based) and FilterFieldToSQL (type-aware with array/timestamp handling), replacing the unexported orFilterToSQL.
  • Adds sortable: false to test name columns in the frontend and returns ValidationError for unsortable sort fields.

Key design decisions

  • Conditional JOINs: Flake CTE and PR join are added only when needed for filtering or sorting, split into filter-required (before COUNT) and sort-only (after COUNT) to avoid unnecessary work during pagination counting.
  • NULL-safe HasEntry: Uses COALESCE(col, '{}') to ensure NOT wrapping works correctly for NULL arrays.
  • Test name filtering: Uses EXISTS subqueries against prow_job_run_tests rather than array column filters, matching the previous matview behavior.

Future work

  • TRT-2834: Add a stored flaked_test_count column to prow_job_runs (populated at insert time by the prow loader), bringing flake count data on par with the existing test_failures column and eliminating the runtime subquery currently needed to compute flake counts.

Test plan

  • Lint passes (make lint)
  • Unit tests pass (make test)
  • Parity tested against old matview server with 17 test cases covering filters, sorts, and edge cases
  • Benchmarked on staging: direct query performs comparably to matview reads while eliminating refresh overhead
  • Independent code review found no correctness issues

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Improved job-run reporting with more flexible filtering, including test-name and flake-related filters.
    • Added richer job-run details, including test names, pull-request information, flake counts, and annotations.
  • Bug Fixes

    • Improved handling of negated and empty-value filters.
    • Disabled sorting for hidden test-name fields in the job-runs table.
  • Performance

    • Job-run result enrichment now runs concurrently for faster report loading.

@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 25, 2026
@openshift-ci

openshift-ci Bot commented Jul 25, 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-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Jul 25, 2026
@openshift-ci-robot

openshift-ci-robot commented Jul 25, 2026

Copy link
Copy Markdown

@mstaeble: This pull request references TRT-2814 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

  • Replaces prow_job_runs_report_matview with a two-phase direct query in JobsRunsReportFromDB: Phase 1 paginates from base tables (prow_job_runs + prow_jobs), Phase 2 enriches the paginated page with test counts, test name arrays, pull request data, and annotations via errgroup.
  • Removes the matview definition and its entry from PostgresMatViews, eliminating a ~90-second refresh that blocked data loading.
  • Refactors pkg/filter to export FilterItemToSQL (column-expression based) and FilterFieldToSQL (type-aware with array/timestamp handling), replacing the unexported orFilterToSQL.
  • Adds sortable: false to test name columns in the frontend and returns ValidationError for unsortable sort fields.

Key design decisions

  • Conditional JOINs: Flake CTE and PR join are added only when needed for filtering or sorting, split into filter-required (before COUNT) and sort-only (after COUNT) to avoid unnecessary work during pagination counting.
  • NULL-safe HasEntry: Uses COALESCE(col, '{}') to ensure NOT wrapping works correctly for NULL arrays.
  • Test name filtering: Uses EXISTS subqueries against prow_job_run_tests rather than array column filters, matching the previous matview behavior.

Test plan

  • Lint passes (make lint)
  • Unit tests pass (make test)
  • Parity tested against old matview server with 17 test cases covering filters, sorts, and edge cases
  • Benchmarked on staging: direct query performs comparably to matview reads while eliminating refresh overhead
  • Independent code review found no correctness issues

🤖 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.

@openshift-ci

openshift-ci Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: mstaeble

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-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 25, 2026
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Tip

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

@openshift-ci-robot Acknowledged. TRT-2814 needs its Jira target version set to 5.0.0 for this PR’s target branch.

@mstaeble

Copy link
Copy Markdown
Contributor Author

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Full review finished.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

Changes

Job runs reporting

Layer / File(s) Summary
Filter SQL contracts
pkg/filter/filterable.go
Adds reusable negation and field-aware SQL conversion helpers for scalar, array, timestamp, and ILIKE filters.
Dynamic report query and enrichment
pkg/api/job_runs.go, sippy-ng/src/jobs/JobRunsTable.jsx
Replaces the materialized-view report path with dynamic filtering, conditional joins, concurrent enrichment, and disabled sorting for hidden test-name fields.
Materialized-view removal
pkg/db/views.go, pkg/flags/postgres_benchmarking_test.go
Removes materialized-view synchronization, SQL definition, and its benchmark.

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

Sequence Diagram(s)

sequenceDiagram
  participant JobsRunsReportFromDB
  participant PostgreSQL
  participant errgroup
  JobsRunsReportFromDB->>PostgreSQL: Execute dynamic paginated job-run query
  PostgreSQL-->>JobsRunsReportFromDB: Return base job-run rows
  JobsRunsReportFromDB->>errgroup: Start concurrent enrichment tasks
  errgroup->>PostgreSQL: Query flakes, test names, pull requests, and annotations
  PostgreSQL-->>errgroup: Return enrichment data
  errgroup-->>JobsRunsReportFromDB: Complete enriched report rows
Loading

Suggested reviewers: dgoodwin, smg247


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (1 error, 2 warnings)

Check name Status Explanation Resolution
Sql Injection Prevention ❌ Error User-supplied columnField values are interpolated with %q in SQL builders, not a real identifier quote, so crafted fields can alter the WHERE clause. Replace %q field formatting with pq.QuoteIdentifier or a strict allowlist, and reject unknown operators/fields with validation errors.
Go Error Handling ⚠️ Warning New code still returns raw DB errors and maps unknown operators to UnknownFilterOperator() instead of an error. Wrap new DB/query failures with fmt.Errorf(...%w) and return an error for unsupported operators in FilterItemToSQL/testNameFilterSQL.
Test Coverage For New Features ⚠️ Warning No unit tests cover the new SQL helpers or job_runs query paths; the only related test ref is a benchmark, and the JSX change has no corresponding test. Add unit tests for WrapNot/FilterItemToSQL/FilterFieldToSQL/testNameFilterSQL and a frontend test for JobRunsTable sortable behavior and sort-field fallback.
✅ 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 matches the main change: removing prow_job_runs_report_matview.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
Excessive Css In React Should Use Styles ✅ Passed JobRunsTable.jsx only adds sortable: false; no new inline style object exceeds the 3-4 property threshold.
Single Responsibility And Clear Naming ✅ Passed The PR splits work into clearly named, single-purpose helpers; new methods have modest signatures and no generic Manager/Util-style abstractions.
Feature Documentation ✅ Passed PASS: no docs/features file covers the changed job-runs report; the only feature doc is unrelated symptoms/labels content.
Stable And Deterministic Test Names ✅ Passed No Ginkgo titles were added/changed; the touched Go tests use static t.Run names, and the removed benchmark had no dynamic titles.
Test Structure And Quality ✅ Passed No Ginkgo specs were added or modified; the only touched test file is a plain Go benchmark, so the checklist is not applicable.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the only test change deletes a benchmark, and the rest is non-e2e app code.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The diff only touches API, filter, view, benchmark, and JSX files; no new Ginkgo e2e tests were added, so no SNO-specific guard is needed.
Topology-Aware Scheduling Compatibility ✅ Passed Only API/filter/test/frontend files changed; no deployment manifests, operator/controller code, or scheduling constraints were added.
Ote Binary Stdout Contract ✅ Passed No changed process-level code writes to stdout; the only fmt.Print/Printf calls are in benchmark test helpers, not main/init/TestMain/suite setup.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; touched test code is a Go benchmark file, with no IPv4-specific or external-network assumptions.
No-Weak-Crypto ✅ Passed Touched files only add SQL/filtering/frontend logic; no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB or secret-comparison code appears.
Container-Privileges ✅ Passed PR only changes Go/JS code; no container/K8s manifests or privilege settings (privileged, hostPID/Network/IPC, SYS_ADMIN, allowPrivilegeEscalation) were added.
No-Sensitive-Data-In-Logs ✅ Passed No new logging was added in the PR diff, and the changed code contains no sensitive-data log statements.
✨ 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 (4)
pkg/api/job_runs.go (2)

151-175: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Use errgroup.WithContext and add context to enrichment errors.

Four independent queries fan out per request with no cancellation and no error context. When one fails, the others keep running to completion against the pool, and the caller receives a bare driver error with no indication of which enrichment failed. errgroup.WithContext plus a short fmt.Errorf("...: %w", err) per branch (or per helper) makes failures diagnosable and lets siblings abort early.

🤖 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/job_runs.go` around lines 151 - 175, The enrichment fan-out around
the errgroup in the job-run loading flow lacks cancellation and identifies no
failing enrichment. Replace the plain errgroup with errgroup.WithContext, pass
the derived context into each enrichment helper if supported, and wrap each
branch’s error with a short enrichment-specific fmt.Errorf using %w so sibling
queries cancel when one fails.

204-233: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add unit tests for the new pure helpers.

analyzeJobRunFilters, isTestNameField, and testNameFilterSQL are dependency-free and encode the join/dispatch decisions the whole refactor rests on; pkg/api/job_runs_test.go already exists. Table-driven cases (sort on test_flakes, sort on a PR column, mixed filter fields, each test-name operator) would lock in behavior without a database.

As per coding guidelines, "new Go functions and methods need unit 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/api/job_runs.go` around lines 204 - 233, Add table-driven unit tests in
the existing pkg/api/job_runs_test.go for analyzeJobRunFilters, isTestNameField,
and testNameFilterSQL. Cover sorting by test_flakes, sorting by a pull-request
column, mixed filter fields, and every supported test-name operator, asserting
the expected helper outputs without database dependencies.

Source: Coding guidelines

pkg/filter/filterable.go (2)

148-151: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Unknown operator silently produces invalid SQL.

The default branch emits UnknownFilterOperator() as a SQL fragment. Callers (e.g. applyJobRunFilters in pkg/api/job_runs.go) splice this straight into the WHERE clause, so a bad operatorValue from the client surfaces as a Postgres "function does not exist" error / 500 rather than a 400 validation error. Consider returning an error (or an empty fragment the caller can reject) so the API can respond with ValidationError.

Note this is a behavior widening compared to andFilterToSQL, which simply ignores unknown operators.

🤖 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/filter/filterable.go` around lines 148 - 151, The default branch in the
filter-to-SQL conversion must reject unknown operators instead of returning the
invalid “UnknownFilterOperator()” SQL fragment. Update the relevant filter
conversion method and its callers, including applyJobRunFilters, to propagate
the validation error so invalid client operators produce a ValidationError/400
response; preserve handling for supported operators and the existing
andFilterToSQL behavior.

154-176: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add unit coverage for the new exported SQL generators.

FilterItemToSQL and FilterFieldToSQL now carry the negation/array/timestamp semantics that orFilterToSQL used to own, and they are consumed cross-package by pkg/api/job_runs.go. pkg/filter/filterable_test.go is the natural home for table-driven assertions on the emitted fragment + param per operator (especially OperatorHasEntry with Not, and OperatorIsNotEmpty, where the old optNot(!f.Not) inversion was replaced by WrapNot).

As per coding guidelines, "new Go functions and methods need unit 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/filter/filterable.go` around lines 154 - 176, Add table-driven unit tests
in filterable_test.go covering the exported FilterItemToSQL and FilterFieldToSQL
methods, asserting both emitted SQL fragments and parameters for each operator.
Include array-aware negation for OperatorHasEntry with Not, timestamp handling
in FilterFieldToSQL, and the OperatorIsNotEmpty behavior using WrapNot rather
than the former optNot inversion. Reuse existing test conventions and cover
representative scalar, array, and timestamp cases.

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.

Inline comments:
In `@pkg/api/job_runs.go`:
- Around line 318-352: Reject unsupported operators instead of converting them
into SQL. In pkg/api/job_runs.go lines 318-352, update testNameFilterSQL to
handle only supported operators explicitly and return an error for unknown
values, propagating it to the existing 400 ValidationError path. In
pkg/filter/filterable.go lines 148-151, change FilterItemToSQL to return an
error or empty fragment with an ok indicator rather than
UnknownFilterOperator(), and update its callers to reject invalid operators as
client validation errors.
- Around line 305-311: Update the clause construction in the job-run query
around the filter.LinkOperatorOr branch so OR-joined clauses are explicitly
grouped in parentheses before passing them to q.Where. Preserve the existing AND
join behavior and argument ordering, ensuring subsequent release and timestamp
conditions cannot change the OR expression’s precedence.
- Around line 386-421: Update enrichJobRunsWithTestNames and its query to
populate the ran_test_names API field with all test names associated with each
job run, while retaining the existing failed and flaked name projections for
statuses 12 and 13. Ensure job runs with tests outside those statuses receive
their names so frontend results do not default to Pass.

In `@sippy-ng/src/jobs/JobRunsTable.jsx`:
- Around line 365-381: Update the sortField initialization or validation in the
JobRunsTable component so URL-provided fields that map to columns with sortable:
false fall back to the existing default sort field. Preserve valid sortable URL
values and use the column definitions as the source of truth, including
flaked_test_names and ran_test_names.

---

Nitpick comments:
In `@pkg/api/job_runs.go`:
- Around line 151-175: The enrichment fan-out around the errgroup in the job-run
loading flow lacks cancellation and identifies no failing enrichment. Replace
the plain errgroup with errgroup.WithContext, pass the derived context into each
enrichment helper if supported, and wrap each branch’s error with a short
enrichment-specific fmt.Errorf using %w so sibling queries cancel when one
fails.
- Around line 204-233: Add table-driven unit tests in the existing
pkg/api/job_runs_test.go for analyzeJobRunFilters, isTestNameField, and
testNameFilterSQL. Cover sorting by test_flakes, sorting by a pull-request
column, mixed filter fields, and every supported test-name operator, asserting
the expected helper outputs without database dependencies.

In `@pkg/filter/filterable.go`:
- Around line 148-151: The default branch in the filter-to-SQL conversion must
reject unknown operators instead of returning the invalid
“UnknownFilterOperator()” SQL fragment. Update the relevant filter conversion
method and its callers, including applyJobRunFilters, to propagate the
validation error so invalid client operators produce a ValidationError/400
response; preserve handling for supported operators and the existing
andFilterToSQL behavior.
- Around line 154-176: Add table-driven unit tests in filterable_test.go
covering the exported FilterItemToSQL and FilterFieldToSQL methods, asserting
both emitted SQL fragments and parameters for each operator. Include array-aware
negation for OperatorHasEntry with Not, timestamp handling in FilterFieldToSQL,
and the OperatorIsNotEmpty behavior using WrapNot rather than the former optNot
inversion. Reuse existing test conventions and cover representative scalar,
array, and timestamp cases.
🪄 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: 87c0d531-857b-4583-a19c-e8b85ce1e8ae

📥 Commits

Reviewing files that changed from the base of the PR and between 1c5aaf7 and 1157298.

📒 Files selected for processing (5)
  • pkg/api/job_runs.go
  • pkg/db/views.go
  • pkg/filter/filterable.go
  • pkg/flags/postgres_benchmarking_test.go
  • sippy-ng/src/jobs/JobRunsTable.jsx
💤 Files with no reviewable changes (2)
  • pkg/db/views.go
  • pkg/flags/postgres_benchmarking_test.go

Comment thread pkg/api/job_runs.go
Comment thread pkg/api/job_runs.go Outdated
Comment thread pkg/api/job_runs.go
Comment thread sippy-ng/src/jobs/JobRunsTable.jsx
@mstaeble
mstaeble force-pushed the TRT-2814-eliminate-job-runs-matview branch from 1157298 to 59c83ec Compare July 26, 2026 14:13
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@mstaeble
mstaeble force-pushed the TRT-2814-eliminate-job-runs-matview branch from 59c83ec to d771bb9 Compare July 26, 2026 14:39
@mstaeble
mstaeble marked this pull request as ready for review July 26, 2026 15:00
@mstaeble mstaeble changed the title [WIP] TRT-2814: Eliminate prow_job_runs_report_matview TRT-2814: Eliminate prow_job_runs_report_matview Jul 26, 2026
@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 Jul 26, 2026
@openshift-ci
openshift-ci Bot requested review from smg247 and xueqzhan July 26, 2026 15:00
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e

@openshift-ci

openshift-ci Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

@mstaeble: 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.

@mstaeble

Copy link
Copy Markdown
Contributor Author

@coderabbitai resolve

@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 Jul 26, 2026
@coderabbitai

coderabbitai Bot commented Jul 26, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Comments resolved and changes approved.

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. 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.

2 participants