Skip to content

ci-operator-checkconfig: Add cluster profile sets allowlist#5171

Merged
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
danilo-gemoli:feat/ci-operator-checkconfig/cps-ignore-list
May 12, 2026
Merged

ci-operator-checkconfig: Add cluster profile sets allowlist#5171
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
danilo-gemoli:feat/ci-operator-checkconfig/cps-ignore-list

Conversation

@danilo-gemoli
Copy link
Copy Markdown
Contributor

@danilo-gemoli danilo-gemoli commented May 11, 2026

Revisit the Cluster Profile Sets policy that has been introduced with #5087 by adding a whitelist that allows some tests to use the underlying cluster profile rather than the cluster profile set.

With the actual policy, the following test in ci-operator/config/openshift/openshift-tests-private/openshift-openshift-tests-private-release-4.22__multi-nightly.yaml doesn't pass the validation since it is using aws rather than openshift-org-aws:

tests:
- as: aws-ipi-public-ipv4-pool-byo-subnet-mini-perm-arm-f14
  cron: 33 8 4,18 * *
  steps:
    cluster_profile: aws

After we merge this PR along with another one in openshift/release that would produce an allowlist like the following one, the test will pass the validation:

{
  "cluster_profile_sets": {
    "openshift-org-aws": [
      "aws",
      "aws-2",
      "aws-3",
      "aws-4",
      "aws-5"
    ],
  "tests_allowlist": {
    "openshift/openshift-tests-private": {
      "release-4.22": {
        "multi-nightly": [
          "aws-ipi-public-ipv4-pool-byo-subnet-mini-perm-arm-f14"
        ]
      }
    }
  }
}

The tests_allowlist consists of:

{
  "tests_allowlist" : {
     "${ORG}/${REPO}": {   // Regex allowed
       "${BRANCH}": {      // Regex allowed
         "${VARIANT}": [   // Regex allowed
           "${TEST_NAME}"  // Plain text, NO regex allowed
         ]
       }
     }
  }
}

The type ClusterProfileSetDetailsNew is temporary and will be deleted once we merge a PR in openshift/release that will modify the cluster-profile-set-details.json schema to accomodate the new tests_whitelist stanza.
The combination of both ClusterProfileSetDetails and ClusterProfileSetDetailsNew makes sure we are backward compatible until the migration is complete.

Summary by CodeRabbit

  • New Features
    • Added a regex-based allowlist for cluster profile set usage so specific tests can continue using legacy cluster profiles.
    • Backwards-compatible loading of both legacy and new allowlist JSON shapes.
  • Validation
    • Validation now enforces per-test allowlisting, suggests appropriate cluster profile sets, and skips allowlisted tests.
  • Tests
    • Expanded unit tests covering legacy/new schemas, allowlist behavior, and regexp utilities.

@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

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

📝 Walkthrough

Walkthrough

Refactors cluster-profile-set handling to a new exported api.ClusterProfileSetDetails with schema migration and per-test allowlisting, adds regex utilities, updates loader and CLI wiring, and enforces allowlisted cluster profile validation in the validator and tests.

Changes

Cluster Profile Allowlisting with Schema Migration

Layer / File(s) Summary
Regex utility and tests
pkg/util/regexp/regexp.go, pkg/util/regexp/regexp_test.go
Adds exported Regexp wrapper that stores the original expression and compiled *regexp.Regexp, implements text marshal/unmarshal, Compile, and generic LookupByMatch[T] plus unit tests validating compile, marshal/unmarshal, and match lookup behaviors.
API type: ClusterProfileSetDetails + helpers + tests
pkg/api/types.go, pkg/api/types_test.go
Introduces exported ClusterProfileSetDetails with custom UnmarshalJSON to accept old (map[ClusterProfile][]string) and new (ClusterProfileSetDetailsNew) schemas. ClusterProfileSetDetailsNew contains ClusterProfileSets and TestsAllowlist keyed by utilregexp.Regexp. Adds FindSetByProfile and IsTestAllowlisted. Adds unit test for unmarshalling both schemas.
Loader: read & unmarshal cluster-profile-set file
pkg/load/load.go
Adds ClusterProfileSetDetails(path string) (api.ClusterProfileSetDetails, error) which reads a file and unmarshals it into api.ClusterProfileSetDetails, returning errors for read/unmarshal failures.
CLI wiring: flag parsing & options type update
cmd/ci-operator-checkconfig/main.go
Changes options.clusterProfileSetDetails type to api.ClusterProfileSetDetails, updates flag parsing to call load.ClusterProfileSetDetails(...) directly, and removes the old helper that performed JSON unmarshal into the legacy map type.
Validator wiring and initialization
pkg/validation/config.go
Replaces the removed local ClusterProfileSetDetails alias with api.ClusterProfileSetDetails for Validator.cpsDetails, updates WithClusterProfileSetDetails signature, and initializes cpsDetails as an empty api.ClusterProfileSetDetails{} in NewValidator.
Per-test cluster profile validation
pkg/validation/test.go
validateClusterProfile now receives a test string param, requires non-nil metadata, checks that the profile is known, consults v.cpsDetails.IsTestAllowlisted(test, *metadata) and uses FindSetByProfile for suggestions on rejection; validateTestConfigurationType passes test.As into these checks for both literal and referenced configs.
Validation tests updated for allowlists
pkg/validation/test_test.go
Updates test calls to pass non-nil *api.Metadata, refactors TestValidateClusterProfiles to use per-test scenarios with api.ClusterProfileSetDetails including regex allowlists, adds helper re() to compile regexes, and adds cases verifying allowlist skipping and pattern matching.

Sequence Diagram

sequenceDiagram
  participant CLI as "ci-operator-checkconfig CLI"
  participant Loader as "pkg/load"
  participant API as "pkg/api (types)"
  participant Validator as "pkg/validation"

  CLI->>Loader: ClusterProfileSetDetails(path)
  Loader->>API: json.Unmarshal -> ClusterProfileSetDetails (handles old/new schema)
  API-->>Loader: ClusterProfileSetDetails struct
  CLI->>Validator: pass ClusterProfileSetDetails into options
  Validator->>API: IsTestAllowlisted(test, metadata) / FindSetByProfile(profile)
  API-->>Validator: allowlist decision / suggestion
  Validator-->>CLI: validation result / errors
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

  • openshift/ci-tools#5088: Modifies cluster-profile-set handling and validator wiring; closely related changes.
  • openshift/ci-tools#5087: Implements initial cluster-profile-set support, loader, and validation wiring similar to this PR.

Suggested labels

lgtm

Suggested reviewers

  • droslean
  • jmguzik
  • Prucek
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 26.32% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main change: adding cluster profile sets allowlist functionality, which is the primary objective and central to all modifications across multiple files.
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot requested review from droslean and jmguzik May 11, 2026 08:54
@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label May 11, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 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/validation/config.go`:
- Line 45: Fix the typo in the comment for the TestsWhitelist field: change
"enfoce" to "enforce" in the comment that reads "TestsWhitelist holds a list of
tests for which we do not enfoce policy" (search for the TestsWhitelist comment
in pkg/validation/config.go and update the text accordingly).
🪄 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: Enterprise

Run ID: 4b24535d-a229-4ecf-8af4-8093fb722155

📥 Commits

Reviewing files that changed from the base of the PR and between e47f9fa and 5d52c72.

📒 Files selected for processing (5)
  • cmd/ci-operator-checkconfig/main.go
  • pkg/validation/config.go
  • pkg/validation/config_test.go
  • pkg/validation/test.go
  • pkg/validation/test_test.go

Comment thread pkg/validation/config.go Outdated
@danilo-gemoli
Copy link
Copy Markdown
Contributor Author

/test e2e

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label May 11, 2026
@openshift-merge-bot
Copy link
Copy Markdown
Contributor

Tests from second stage were triggered manually. Pipeline can be controlled only manually, until HEAD changes. Use command to trigger second stage.

@petr-muller
Copy link
Copy Markdown
Member

  1. Can we call it "allowlist" instead of "whitelist"?
  2. I'm worried about the maintenance of a separate allowlist long-term, e.g. in events such as branch cuts but also copies in openshift-priv. Do we plan to extend the tools that propagate jobs through the system to manage the allowlist too, or is it expected to be maintained manually?

@danilo-gemoli
Copy link
Copy Markdown
Contributor Author

/hold

@openshift-ci openshift-ci Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 11, 2026
@danilo-gemoli
Copy link
Copy Markdown
Contributor Author

Can we call it "allowlist" instead of "whitelist"?

Sure.

I'm worried about the maintenance of a separate allowlist long-term, e.g. in events such as branch cuts but also copies in openshift-priv. Do we plan to extend the tools that propagate jobs through the system to manage the allowlist too, or is it expected to be maintained manually?

Good point. The allowlist is manually maintained in and generated by core-services/prow/02_config/generate-boskos.py. The output looks like what follows:

{
  "cluster_profile_sets": {
    "openshift-org-aws": [
      "aws",
      "aws-2",
      "aws-3",
      "aws-4",
      "aws-5"
    ],
    "openshift-org-azure": [
      "azure-2",
      "azure4"
    ],
    "openshift-org-gcp": [
      "gcp",
      "gcp-arm64",
      "gcp-openshift-gce-devel-ci-2",
      "gcp-3"
    ]
  },
  "tests_whitelist": {
    "openshift/openshift-tests-private": {
      "release-4.22": {
        "multi-nightly": [
          "aws-ipi-public-ipv4-pool-byo-subnet-mini-perm-arm-f14"
        ]
      }
    }
  }
}

I can think of several approaches to address your, very valid, concerns:

  1. Regex:
"tests_whitelist": {
  "openshift(-priv)?/openshift-tests-private": { // openshift or openshift-priv
    ".+": { // Any branch
      ".*": [ // Any or no variant
        "aws-ipi-public-ipv4-pool-byo-subnet-mini-perm-arm-f14"
      ]
    }
  }
}
  1. Extend the cluster_profile stanza to something like this:
tests:
- as: aws-ipi-public-ipv4-pool-byo-subnet-mini-perm-arm-f14
  cron: 33 8 4,18 * *
  steps:
    cluster_profile:
      name: aws
      enforce_cluster_profile_set_policy: false
  1. When performing the validation, raise a warning to the user rather than a failure.

  2. Define both Cluster Profile Sets and the allowlist outside of core-services/prow/02_config/generate-boskos.py and modify our tools such that they will keep the new config up to date.

To me, the least complex that keeps enforcing the policy and requires little to no long term, manual, maintenance is (1).
WDYT?

@openshift-merge-bot
Copy link
Copy Markdown
Contributor

Tests from second stage were triggered manually. Pipeline can be controlled only manually, until HEAD changes. Use command to trigger second stage.

@danilo-gemoli danilo-gemoli force-pushed the feat/ci-operator-checkconfig/cps-ignore-list branch from 5d52c72 to 287468d Compare May 12, 2026 09:52
@openshift-ci openshift-ci Bot removed the lgtm Indicates that a PR is ready to be merged. label May 12, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

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

454-516: ⚡ Quick win

Add migration coverage for allowlist key aliases

This test only covers old map vs cluster_profile_sets. Please add cases for allowlist, tests_allowlist, and tests_whitelist so schema migration behavior is locked in.

As per coding guidelines pkg/api/**: "Backward compatibility matters — new fields should have zero-value defaults that preserve existing behavior."

🤖 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/types_test.go` around lines 454 - 516, Extend
TestUnmarshalClusterProfileSetDetails to include additional test cases that
verify the schema migration handles legacy key aliases: "allowlist",
"tests_allowlist", and "tests_whitelist"; for each new case (add to the tc slice
in TestUnmarshalClusterProfileSetDetails) provide JSON input using the legacy
key with the same array value as the existing cases and set
wantClusterProfileSetDetails to the same
ClusterProfileSetDetails/ClusterProfileSetDetailsNew value with
ClusterProfileSets populated for "openshift-org-aws"; ensure the test still
unmarshals into ClusterProfileSetDetails and compares via cmp.Diff so
backwards-compatibility for those aliases is asserted.
pkg/api/types.go (1)

3118-3161: ⚡ Quick win

Add GoDoc for new exported API surface

ClusterProfileSetDetails, ClusterProfileSetDetailsNew, FindSetByProfile, and IsTestAllowlisted are exported and should have doc comments.

As per coding guidelines **/*.go: "Ensure Go documentation on functions, classes, and fields are written properly."

🤖 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/types.go` around lines 3118 - 3161, Add GoDoc comments for the newly
exported API: document ClusterProfileSetDetails and ClusterProfileSetDetailsNew
(describe purpose and JSON field meanings for ClusterProfileSets and Allowlist),
and document the methods FindSetByProfile and IsTestAllowlisted (describe
parameters, return values and behavior). Use proper GoDoc style (each comment
begins with the symbol name, concise description, mention JSON semantics for
ClusterProfileSets and the nested allowlist structure) and place comments
immediately above the type/func declarations for ClusterProfileSetDetails,
ClusterProfileSetDetailsNew, ClusterProfileSets, Allowlist, FindSetByProfile,
and IsTestAllowlisted.
🤖 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/types.go`:
- Around line 3122-3136: The UnmarshalJSON for ClusterProfileSetDetails should
not rely on strings.Contains; instead first unmarshal the top-level JSON into a
map[string]json.RawMessage (an "envelope") and inspect whether the
"cluster_profile_sets" key exists, then unmarshal the corresponding raw message
into the old cpsDetails map or into ClusterProfileSetDetailsNew accordingly;
update the ClusterProfileSetDetails.UnmarshalJSON function to use this
envelope-based detection and then set cps.ClusterProfileSets or
cps.ClusterProfileSetDetailsNew as before.

In `@pkg/load/load.go`:
- Around line 317-318: The json.Unmarshal error for cpsDetailsBytes into cpsd
doesn't include which file failed to parse; update the error wrapping (the
fmt.Errorf call) to include the source filename or path used to produce
cpsDetailsBytes (e.g., the variable that holds the path or the function
parameter that names the file) so the message becomes something like "unmarshal
<filename>: %w"; locate the json.Unmarshal call and the fmt.Errorf return in the
function handling cpsDetailsBytes/cpsd and augment the error string to include
that filename variable.

---

Nitpick comments:
In `@pkg/api/types_test.go`:
- Around line 454-516: Extend TestUnmarshalClusterProfileSetDetails to include
additional test cases that verify the schema migration handles legacy key
aliases: "allowlist", "tests_allowlist", and "tests_whitelist"; for each new
case (add to the tc slice in TestUnmarshalClusterProfileSetDetails) provide JSON
input using the legacy key with the same array value as the existing cases and
set wantClusterProfileSetDetails to the same
ClusterProfileSetDetails/ClusterProfileSetDetailsNew value with
ClusterProfileSets populated for "openshift-org-aws"; ensure the test still
unmarshals into ClusterProfileSetDetails and compares via cmp.Diff so
backwards-compatibility for those aliases is asserted.

In `@pkg/api/types.go`:
- Around line 3118-3161: Add GoDoc comments for the newly exported API: document
ClusterProfileSetDetails and ClusterProfileSetDetailsNew (describe purpose and
JSON field meanings for ClusterProfileSets and Allowlist), and document the
methods FindSetByProfile and IsTestAllowlisted (describe parameters, return
values and behavior). Use proper GoDoc style (each comment begins with the
symbol name, concise description, mention JSON semantics for ClusterProfileSets
and the nested allowlist structure) and place comments immediately above the
type/func declarations for ClusterProfileSetDetails,
ClusterProfileSetDetailsNew, ClusterProfileSets, Allowlist, FindSetByProfile,
and IsTestAllowlisted.
🪄 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: Enterprise

Run ID: 7a69c4cc-3842-494a-b5d6-22f8d7a52222

📥 Commits

Reviewing files that changed from the base of the PR and between 5d52c72 and 287468d.

📒 Files selected for processing (9)
  • cmd/ci-operator-checkconfig/main.go
  • pkg/api/types.go
  • pkg/api/types_test.go
  • pkg/load/load.go
  • pkg/util/regexp/regexp.go
  • pkg/util/regexp/regexp_test.go
  • pkg/validation/config.go
  • pkg/validation/test.go
  • pkg/validation/test_test.go
✅ Files skipped from review due to trivial changes (2)
  • pkg/util/regexp/regexp.go
  • pkg/util/regexp/regexp_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/validation/test_test.go
  • pkg/validation/test.go

Comment thread pkg/api/types.go
Comment on lines +3122 to +3136
func (cps *ClusterProfileSetDetails) UnmarshalJSON(data []byte) error {
cpsDetails := make(map[ClusterProfile][]string)

if strings.Contains(string(data), `"cluster_profile_sets"`) {
newCPSDetails := ClusterProfileSetDetailsNew{}
if err := json.Unmarshal(data, &newCPSDetails); err != nil {
return fmt.Errorf("new ClusterProfileSetDetails schema: %w", err)
}
cps.ClusterProfileSetDetailsNew = newCPSDetails
} else {
if err := json.Unmarshal(data, &cpsDetails); err != nil {
return fmt.Errorf("old ClusterProfileSetDetails schema: %w", err)
}
cps.ClusterProfileSets = cpsDetails
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Avoid substring-based schema detection in UnmarshalJSON

Using strings.Contains on raw JSON can select the wrong branch based on content text rather than actual top-level keys. Parse an envelope key instead.

💡 Safer schema detection
 func (cps *ClusterProfileSetDetails) UnmarshalJSON(data []byte) error {
-	cpsDetails := make(map[ClusterProfile][]string)
-
-	if strings.Contains(string(data), `"cluster_profile_sets"`) {
+	cpsDetails := make(map[ClusterProfile][]string)
+	var probe struct {
+		ClusterProfileSets json.RawMessage `json:"cluster_profile_sets"`
+	}
+	if err := json.Unmarshal(data, &probe); err != nil {
+		return fmt.Errorf("probe ClusterProfileSetDetails schema: %w", err)
+	}
+
+	if probe.ClusterProfileSets != nil {
 		newCPSDetails := ClusterProfileSetDetailsNew{}
 		if err := json.Unmarshal(data, &newCPSDetails); err != nil {
 			return fmt.Errorf("new ClusterProfileSetDetails schema: %w", err)
 		}
+		newCPSDetails.normalizeAllowlist()
 		cps.ClusterProfileSetDetailsNew = newCPSDetails
 	} else {
 		if err := json.Unmarshal(data, &cpsDetails); err != nil {
 			return fmt.Errorf("old ClusterProfileSetDetails schema: %w", err)
 		}
-		cps.ClusterProfileSets = cpsDetails
+		cps.ClusterProfileSetDetailsNew = ClusterProfileSetDetailsNew{
+			ClusterProfileSets: cpsDetails,
+		}
 	}
🤖 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/types.go` around lines 3122 - 3136, The UnmarshalJSON for
ClusterProfileSetDetails should not rely on strings.Contains; instead first
unmarshal the top-level JSON into a map[string]json.RawMessage (an "envelope")
and inspect whether the "cluster_profile_sets" key exists, then unmarshal the
corresponding raw message into the old cpsDetails map or into
ClusterProfileSetDetailsNew accordingly; update the
ClusterProfileSetDetails.UnmarshalJSON function to use this envelope-based
detection and then set cps.ClusterProfileSets or cps.ClusterProfileSetDetailsNew
as before.

Comment thread pkg/api/types.go Outdated
Comment thread pkg/load/load.go Outdated
Comment on lines +317 to +318
if err := json.Unmarshal(cpsDetailsBytes, &cpsd); err != nil {
return cpsd, fmt.Errorf("unmarshal: %w", err)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Include file path in unmarshal error context

The current message loses which file failed JSON parsing.

💡 Small fix
-	if err := json.Unmarshal(cpsDetailsBytes, &cpsd); err != nil {
-		return cpsd, fmt.Errorf("unmarshal: %w", err)
+	if err := json.Unmarshal(cpsDetailsBytes, &cpsd); err != nil {
+		return cpsd, fmt.Errorf("unmarshal file %s: %w", p, err)
 	}
As per coding guidelines "Ensure error messages are informative enough for developers to understand the error."
🤖 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/load/load.go` around lines 317 - 318, The json.Unmarshal error for
cpsDetailsBytes into cpsd doesn't include which file failed to parse; update the
error wrapping (the fmt.Errorf call) to include the source filename or path used
to produce cpsDetailsBytes (e.g., the variable that holds the path or the
function parameter that names the file) so the message becomes something like
"unmarshal <filename>: %w"; locate the json.Unmarshal call and the fmt.Errorf
return in the function handling cpsDetailsBytes/cpsd and augment the error
string to include that filename variable.

@danilo-gemoli danilo-gemoli force-pushed the feat/ci-operator-checkconfig/cps-ignore-list branch from 287468d to c1b5e76 Compare May 12, 2026 10:30
@danilo-gemoli danilo-gemoli changed the title ci-operator-checkconfig: Add cluster profile sets whitelist ci-operator-checkconfig: Add cluster profile sets allowlist May 12, 2026
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
pkg/load/load.go (1)

309-309: ⚡ Quick win

Add GoDoc for exported ClusterProfileSetDetails

Please add a doc comment starting with ClusterProfileSetDetails above the declaration so intent is discoverable and Go tooling stays clean.

As per coding guidelines "Ensure Go documentation on functions, classes, and fields are written properly".

Suggested patch
+// ClusterProfileSetDetails loads cluster profile set details from a JSON file.
 func ClusterProfileSetDetails(path string) (api.ClusterProfileSetDetails, error) {
 	cpsd := api.ClusterProfileSetDetails{}
🤖 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/load/load.go` at line 309, Add a GoDoc comment for the exported function
ClusterProfileSetDetails: place a comment immediately above the function
declaration that begins with "ClusterProfileSetDetails" and briefly describes
what the function does, the meaning of the path parameter, and what the returned
api.ClusterProfileSetDetails and error represent (e.g., successful load vs.
failure). Keep it concise and idiomatic (one or two sentences starting with the
function name) so Go tooling and users can discover the intent.
pkg/util/regexp/regexp.go (1)

7-10: ⚡ Quick win

Add GoDoc for exported API elements

Pattern (exported field) and Compile (exported function) need explicit doc comments to meet package documentation standards.

As per coding guidelines Ensure Go documentation on functions, classes, and fields are written properly.

Also applies to: 34-40

🤖 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/util/regexp/regexp.go` around lines 7 - 10, Add GoDoc comments for the
exported Regexp type, its exported field Pattern, and the exported Compile
function: write concise package-style comments above the type Regexp describing
its purpose, above the Pattern field describing that it holds the compiled
*regexp.Regexp for the expression, and above the Compile function describing its
behavior, inputs, return values, and any error semantics so the exported API is
documented for godoc consumers.
pkg/util/regexp/regexp_test.go (1)

142-150: ⚡ Quick win

Overlap test does not verify the declared “first wins” behavior

This case currently skips value assertion, so it can’t detect resolution-order regressions. Once precedence is defined in LookupByMatch, assert the exact winner here.

🤖 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/util/regexp/regexp_test.go` around lines 142 - 150, The test "multiple
patterns could match - first wins" currently sets skipValueCheck so it cannot
catch precedence regressions; update the case to assert the exact winner from
LookupByMatch instead of skipping: remove skipValueCheck and add wantValue
(expect "specific" for input "test-cluster" since "^test-.*" should win over
".*"). If LookupByMatch defines precedence by input order rather than map
iteration, change patternPairs from a map to an ordered structure (e.g., a slice
of pattern/value pairs used by the test) so the test reliably encodes the
intended order.
🤖 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/util/regexp/regexp.go`:
- Around line 44-49: LookupByMatch is nondeterministic because it iterates a map
and returns the first matching Regexp, so overlapping patterns can yield random
results; fix by making matching deterministic: collect the map entries (keys or
key/value pairs) into a slice, sort that slice by a stable key (e.g., the Regexp
pattern string via re.Pattern.String() or a priority field on the Regexp type if
present), then iterate the sorted slice and return the first match. Update
LookupByMatch to use sort.Slice on the slice of patterns before performing
re.Pattern.Match to ensure stable, repeatable matching.

---

Nitpick comments:
In `@pkg/load/load.go`:
- Line 309: Add a GoDoc comment for the exported function
ClusterProfileSetDetails: place a comment immediately above the function
declaration that begins with "ClusterProfileSetDetails" and briefly describes
what the function does, the meaning of the path parameter, and what the returned
api.ClusterProfileSetDetails and error represent (e.g., successful load vs.
failure). Keep it concise and idiomatic (one or two sentences starting with the
function name) so Go tooling and users can discover the intent.

In `@pkg/util/regexp/regexp_test.go`:
- Around line 142-150: The test "multiple patterns could match - first wins"
currently sets skipValueCheck so it cannot catch precedence regressions; update
the case to assert the exact winner from LookupByMatch instead of skipping:
remove skipValueCheck and add wantValue (expect "specific" for input
"test-cluster" since "^test-.*" should win over ".*"). If LookupByMatch defines
precedence by input order rather than map iteration, change patternPairs from a
map to an ordered structure (e.g., a slice of pattern/value pairs used by the
test) so the test reliably encodes the intended order.

In `@pkg/util/regexp/regexp.go`:
- Around line 7-10: Add GoDoc comments for the exported Regexp type, its
exported field Pattern, and the exported Compile function: write concise
package-style comments above the type Regexp describing its purpose, above the
Pattern field describing that it holds the compiled *regexp.Regexp for the
expression, and above the Compile function describing its behavior, inputs,
return values, and any error semantics so the exported API is documented for
godoc consumers.
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 65a935c7-4755-4074-81f5-cd9179fb8c8c

📥 Commits

Reviewing files that changed from the base of the PR and between 287468d and c1b5e76.

📒 Files selected for processing (9)
  • cmd/ci-operator-checkconfig/main.go
  • pkg/api/types.go
  • pkg/api/types_test.go
  • pkg/load/load.go
  • pkg/util/regexp/regexp.go
  • pkg/util/regexp/regexp_test.go
  • pkg/validation/config.go
  • pkg/validation/test.go
  • pkg/validation/test_test.go
✅ Files skipped from review due to trivial changes (1)
  • pkg/api/types_test.go
🚧 Files skipped from review as they are similar to previous changes (5)
  • pkg/validation/config.go
  • pkg/validation/test.go
  • pkg/validation/test_test.go
  • cmd/ci-operator-checkconfig/main.go
  • pkg/api/types.go

Comment thread pkg/util/regexp/regexp.go
Comment on lines +44 to +49
func LookupByMatch[T any](patterns map[Regexp]T, s string) (T, bool) {
for re, val := range patterns {
if re.Pattern.Match([]byte(s)) {
return val, true
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Lookup result is nondeterministic when multiple regexes match

LookupByMatch returns the first match from a Go map iteration, which is random. If allowlist patterns overlap, behavior can flip between runs and incorrectly allow/deny entries.

💡 Deterministic matching sketch
+import "sort"
...
func LookupByMatch[T any](patterns map[Regexp]T, s string) (T, bool) {
-	for re, val := range patterns {
-		if re.Pattern.Match([]byte(s)) {
-			return val, true
-		}
-	}
+	keys := make([]Regexp, 0, len(patterns))
+	for re := range patterns {
+		keys = append(keys, re)
+	}
+	sort.Slice(keys, func(i, j int) bool { return keys[i].expr < keys[j].expr })
+	for _, re := range keys {
+		if re.Pattern.MatchString(s) {
+			return patterns[re], true
+		}
+	}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
func LookupByMatch[T any](patterns map[Regexp]T, s string) (T, bool) {
for re, val := range patterns {
if re.Pattern.Match([]byte(s)) {
return val, true
}
}
func LookupByMatch[T any](patterns map[Regexp]T, s string) (T, bool) {
keys := make([]Regexp, 0, len(patterns))
for re := range patterns {
keys = append(keys, re)
}
sort.Slice(keys, func(i, j int) bool { return keys[i].expr < keys[j].expr })
for _, re := range keys {
if re.Pattern.MatchString(s) {
return patterns[re], true
}
}
var zero T
return zero, 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/util/regexp/regexp.go` around lines 44 - 49, LookupByMatch is
nondeterministic because it iterates a map and returns the first matching
Regexp, so overlapping patterns can yield random results; fix by making matching
deterministic: collect the map entries (keys or key/value pairs) into a slice,
sort that slice by a stable key (e.g., the Regexp pattern string via
re.Pattern.String() or a priority field on the Regexp type if present), then
iterate the sorted slice and return the first match. Update LookupByMatch to use
sort.Slice on the slice of patterns before performing re.Pattern.Match to ensure
stable, repeatable matching.

@openshift-merge-bot
Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e

@danilo-gemoli
Copy link
Copy Markdown
Contributor Author

/test e2e

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 12, 2026

@danilo-gemoli: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/breaking-changes c1b5e76 link false /test breaking-changes

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.

@petr-muller
Copy link
Copy Markdown
Member

I'm not a greatest fan of regexp in configuration files but here it seems like a pragmatic choice. I think eventually someone will ask you for a regex in the job names too (the list items) ;)

/hold cancel

@openshift-ci openshift-ci Bot removed the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label May 12, 2026
@danilo-gemoli
Copy link
Copy Markdown
Contributor Author

I'm not a greatest fan of regexp

Neither am I.

someone will ask you for a regex in the job names too

and I won't do anything until then because:

I'm not a greatest fan of regexp

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label May 12, 2026
@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented May 12, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: danilo-gemoli, Prucek

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:
  • OWNERS [Prucek,danilo-gemoli]

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 aeb8c9d into openshift:main May 12, 2026
16 of 17 checks passed
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. lgtm Indicates that a PR is ready to be merged.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants