GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — ROX-37456: add compliance data freshness e2e tests by guzalv · Pull Request #24043 · stackrox/stackrox

Conversation

@guzalv

@guzalv guzalv commented Nov 12, 2026

Copy link
Copy Markdown
Contributor

Description

Adds end-to-end tests for the compliance "data freshness / stale data" feature (parent ROX-35712), matching the existing single-cluster compliance e2e suite in tests/compliance_operator_v2_test.go (//go:build compliance, TestComplianceV2*).

Three new tests in tests/compliance_operator_v2_freshness_test.go:

  • TestComplianceV2FreshnessCurrent — a normal scan run reports every check result CURRENT; proven via a per-check read and a STALE filter, both scoped to this test's scan config.
  • TestComplianceV2FreshnessStaleViaSweeper — drives the freshness sweeper to flip CURRENT→STALE by scheduling a tick shortly after the scan's completion and cutting off the sensor until the grace window elapses.
  • TestComplianceV2FreshnessStaleViaScanWatcherTimeout — drives the write-time scan-watcher-timeout hook to mark a run's prior results STALE by starving a rescan of sensor updates.

Supporting changes:

  • CI/deploy: shorten the three ROX_COMPLIANCE_* freshness timing env vars (scan-watcher 2m, schedule-watcher 1m, sweep 20s → grace 3m) for e2e only, mirroring the existing ROX_REDHAT_SIGNING_KEY_WATCH_INTERVAL precedent in deploy/common/k8sbased.sh (helm + kubectl-inject) and tests/e2e/lib.sh (operator). Production defaults (40m/45m/5m → 85m grace) are untouched. Each site carries a blast-radius note.
  • tests/Makefile: bump the compliance-v2-tests timeout 30m → 45m (the freshness tests add minutes of time-based waits).

Stacked on #23981 (v2-API wiring); also depends on #23851 (sweeper). The feature flag ROX_COMPLIANCE_SURFACE_STALE_DATA is already enabled in CI.

User-facing documentation

  • CHANGELOG.md is updated OR update is not needed
  • documentation PR is created and is linked above OR is not needed

Testing and quality

  • the change is production ready: the change is GA, or otherwise the functionality is gated by a feature flag
  • CI results are inspected

Automated testing

  • added unit tests
  • added e2e tests
  • added regression tests
  • added compatibility tests
  • modified existing tests

How I validated my change

Validated live on a single-cluster OpenShift environment (ga-ocp-cron) running the combined build (this branch's code + sweeper + API wiring), with the shortened grace window (3m).

  • All three tests PASS individually and in the full -run TestComplianceV2 suite (aggregate ~14m37s, under the new 45m budget). The only suite failure is the pre-existing, unrelated TestComplianceV2Integration "remote" cluster-name check.
  • Independent corroboration beyond go test for each test: direct curl of the per-check results and stats banner, plus Central log lines:
    • sweeper: sweeper.go:115 ... marked 89 check result(s) stale for scan configuration ... at the predicted tick + grace time.
    • scan-watcher timeout: scanwatcher.go:320 Timeout waiting for the scan ... + manager_impl.go:553 Marked 89 prior check results stale ... ~2m after the sensor was cut.
  • Cross-test isolation: per-check reads/filters are scoped by scan-config name (search.ComplianceOperatorScanConfigName), verified live that a bogus name returns 0 rows and the real name returns exactly this config's rows; the profile-global banner uses >= bounds rather than exact counts.

AI-assisted.

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

All reactions
guzalv added 3 commits November 11, 2026 10:55
@guzalv
ROX-39415: surface compliance data freshness through v2 API
f5ea5b9
The merged storage column `data_freshness` (ROX-35712 slice #23694) is written
by the freshness hooks and sweeper, but the v2 API converters never copied it,
so every endpoint returned UNKNOWN/0. The UI already consumes these fields
(per-check indicator, per-check/per-cluster rollup, stale-data banner), so it
showed nothing.

This wires the read path:
- Per-check `data_freshness`: new storage->v2 enum converter, populated in
  `clusterStatus` and `checkResult`.
- Aggregate rollup (`ComplianceCheckResultStatusCount`,
  `ComplianceClusterOverallStats`): new current/stale COUNT(...) FILTER selects
  via a dedicated freshness-count helper (applied only to the queries that surface it), rolled up to CURRENT/STALE/INCONSISTENT/UNKNOWN.
- Banner counts on `ComplianceProfileScanStats`: `stale_check_result_count`
  (stale rows) and `stale_cluster_count` (distinct clusters with any stale
  result, via COUNT(DISTINCT cluster_id) FILTER).

Filter/sort by freshness needs no backend change: the `data_freshness` search
field is already registered and flows through the existing raw-query/sort path.

Rollup rule favors surfacing staleness: any stale alongside any current is
INCONSISTENT, otherwise it reflects whichever is present, else UNKNOWN.

The response-level `ListComplianceCheckResultResponse.data_freshness` rollup is
intentionally left UNKNOWN for now (no consumer; correct population needs an
unpaginated current/stale count) - noted with a shortcut comment.

Depends only on master (the merged column), not on the hooks or sweeper PRs.
When the feature flag is off all rows are UNKNOWN, so the converters naturally
yield UNKNOWN/0 and the UI keeps the feature hidden.

Prompt: "build the API wiring in parallel with the sweeper (they should not
depend on each other)" for the compliance stale-data topic.

Partially generated by AI (Claude Opus 4.8).
@guzalv
ROX-39415: add doc comments for freshness converters and tests
81fd448
Address CodeRabbit docstring-coverage warning: add concise doc comments to the
new freshness converter and the freshness tests. No behavior change.

Partially generated by AI (Claude Opus 4.8).
@guzalv
ROX-39415: trim withFreshnessCountSelectQuery comment to drop caller …
f1bc887
…list

The call-site enumeration can go stale; keep only what the function does.

Partially generated by AI (Claude Opus 4.8).
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress label Nov 12, 2026
@openshift-ci

openshift-ci Bot commented Nov 12, 2026

Copy link
Copy Markdown

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

All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

@guzalv guzalv added the ai-assisted label Nov 12, 2026
@codecov

codecov Bot commented Nov 12, 2026 •
edited
Loading

Uh oh!

There was an error while loading. Please reload this page.

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 52.70%. Comparing base (60d8c9c) to head (9ac4537).

Additional details and impacted files
@@                          Coverage Diff                          @@
##           gualvare/rox-35712-freshness-api   #24043       +/-   ##
=====================================================================
+ Coverage                             40.78%   52.70%   +11.92%     
=====================================================================
  Files                                  2751     2815       +64     
  Lines                                175114   177519     +2405     
=====================================================================
+ Hits                                  71414    93562    +22148     
+ Misses                                98070    75759    -22311     
- Partials                               5630     8198     +2568     
Flag Coverage Δ
go-unit-tests 52.70% <ø> (+11.92%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.
All reactions

Sorry, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

guzalv added 7 commits November 12, 2026 17:24
@guzalv
ROX-39415: allow-list large compliance datastore test file
60d8c9c
datastore_impl_test.go grew past the ~50KB no-large-files limit after
adding the v2-API freshness converter/stats tests. Allow-list it, matching
the existing central/cluster and central/processlisteningonport
datastore_impl_test.go entries.

Partially generated by AI (opencode).
@guzalv
ROX-35712: add compliance data-freshness e2e tests
bb97739
Adds TestComplianceV2FreshnessCurrent, TestComplianceV2FreshnessStaleViaSweeper,
and TestComplianceV2FreshnessStaleViaScanWatcherTimeout to
tests/compliance_operator_v2_freshness_test.go, covering the CURRENT write-time
path, the time-driven freshness sweeper, and the scan-watcher-timeout stale
marking path, plus the v2 API freshness/banner fields and the
'Compliance Check Data Freshness' search filter. Not run against a live cluster
in this change (compile/vet only).

Partially generated with AI assistance.
@guzalv
ROX-35712: shorten compliance freshness timings for e2e
d52196c
Sets ROX_COMPLIANCE_SCAN_WATCHER_TIMEOUT=2m, ROX_COMPLIANCE_SCAN_SCHEDULE_WATCHER_TIMEOUT=1m,
and ROX_COMPLIANCE_FRESHNESS_SWEEP_INTERVAL=20s for e2e Central deployments (helm and
operator-managed paths), mirroring the existing ROX_REDHAT_SIGNING_KEY_WATCH_INTERVAL
precedent. Production defaults (40m/45m/5m) give the sweeper/scan-watcher-timeout tests
in compliance_operator_v2_freshness_test.go an ~85m grace window; shortened to ~3m so
they finish within e2e test timeouts. Does not touch ROX_COMPLIANCE_SURFACE_STALE_DATA,
already enabled in CI. Searched tests/ and qa-tests-backend/ for existing assertions on
DataFreshness/StaleClusterCount/StaleCheckResultCount: none found, so this is safe to
shorten globally.

Partially generated with AI assistance.
@guzalv
ROX-35712: fix sweeper test tick to avoid a start-time tie
9c21933
TestComplianceV2FreshnessStaleViaSweeper failed on a real cluster: it scheduled
the sweeper's tick at (client-side scanStart + 1 minute), truncated to whole
minutes. Compliance Operator stamps LastStartedTime with second granularity
and started the scan within ~1s of the request, landing both values in the
same minute (observed: tick 12:58, LastStartedTime 2026-11-12T12:58:00Z
exactly) so LastStartedTime < cutoff was never true and the sweeper never
marked anything stale (confirmed: no sweeper log output, condition never
satisfied after 6m).

Fix: derive the tick from Central's own LastScanTime (scan completion, always
>= every result's LastStartedTime) returned by
GetComplianceProfileClusterResults, plus a 2-minute buffer, instead of a
client-side guess of the scan's start time. waitForCheckResultsFreshness now
returns the last successful response so the caller can read it.

Verified against ga-ocp-cron: PASS, central logs show
'compliance freshness sweeper: marked 89 check result(s) stale for scan
configuration ...' at the expected time (tick+grace).

Partially generated with AI assistance.
@guzalv
ROX-35712: scope freshness reads per scan config; robustify rescan wait
fdab9da
Finding 2 (cross-test contamination): GetComplianceProfileClusterResults and
GetComplianceProfileStats are keyed by profile+cluster, not by scan config, so
'all results CURRENT/STALE' could see rows left behind by any other scan
config (deleted or not) that has used ocp4-cis on this cluster -- confirmed
live: a stray leftover scan config using ocp4-cis was found on ga-ocp-cron
from an earlier session. Fix:
- Added scanConfigQuery() building a 'Compliance Scan Config Name:<name>'
  filter (search.ComplianceOperatorScanConfigName), confirmed live that it
  correctly isolates one config's rows (bogus name -> 0 rows; AND'd with a
  freshness clause via '+' also verified live).
- waitForCheckResultsFreshness and every per-check read/filter assertion in
  all 3 tests now scope to the test's own scan config name.
- The stale-data banner (GetComplianceProfileStats) can't be scoped by config
  (it's profile-global), so: TestComplianceV2FreshnessCurrent drops the
  global Stale*==0 assertion and instead proves CURRENT-ness via the scoped
  per-check wait + a scoped STALE-filter query (must return 0 rows);
  TestComplianceV2FreshnessStaleViaSweeper/...ScanWatcherTimeout relax the
  banner assertions to >= bounds derived from this test's own known result
  count instead of exact/== 1 values.

Finding 4: replaced the Compliance-Operator-CRD RUNNING poll + blind 15s sleep
in TestComplianceV2FreshnessStaleViaScanWatcherTimeout with
waitForScanConfigRescanObserved, which polls Central's OWN view of the scan
config (GetComplianceScanConfiguration) until its suite phase moves off DONE.
That only happens once sensor has relayed a new ComplianceSuite update to
Central, which is a stronger 'the rescan started and Central knows it' signal
than the raw CRD. A short 10s buffer remains for the separate scan/check-result
relay that creates the scan watcher.

Nit: dropped the now-unused complianceoperatorv1/types imports.

Partially generated with AI assistance.
@guzalv
ROX-35712: bump compliance-v2-tests timeout to 45m
03b2ef7
The freshness tests (TestComplianceV2Freshness*) each add several minutes of
time-based waits (sweeper grace window up to 8m, scan-watcher timeout up to
4m), which doesn't comfortably fit the suite's previous 30m -timeout alongside
the other TestComplianceV2* tests.

Partially generated with AI assistance.
@guzalv
ROX-35712: document blast radius of the freshness timing env vars
9ac4537
Finding 3: add a short note at each ROX_COMPLIANCE_SCAN_WATCHER_TIMEOUT /
ROX_COMPLIANCE_SCAN_SCHEDULE_WATCHER_TIMEOUT / ROX_COMPLIANCE_FRESHNESS_SWEEP_INTERVAL
site explaining why shortening them is e2e-only and benign: a first scan has
no prior results (so a short scan-watcher timeout is a no-op for it), no
existing e2e test reads the freshness column or stale-data banner besides the
new freshness tests, and a short timeout only sets that column and skips
DeleteOldResults, both invisible to every other test.

Partially generated with AI assistance.
@guzalv
guzalv force-pushed the gualvare/rox-37456-freshness-e2e branch from 6c279ef to 9ac4537 Compare November 12, 2026 17:26
@guzalv
guzalv force-pushed the gualvare/rox-35712-freshness-api branch from 60d8c9c to 45cfeef Compare November 12, 2026 17:49

This branch has not been deployed

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

Reviewers

No reviews

Uh oh!

There was an error while loading. Please reload this page.

Assignees

No one assigned

Labels

ai-assisted do-not-merge/work-in-progress

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

Uh oh!

There was an error while loading. Please reload this page.

1 participant

@guzalv
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.