Skip to content

add tide-query-manager#4924

Open
Prucek wants to merge 1 commit intoopenshift:mainfrom
Prucek:tide-query-manager
Open

add tide-query-manager#4924
Prucek wants to merge 1 commit intoopenshift:mainfrom
Prucek:tide-query-manager

Conversation

@Prucek
Copy link
Member

@Prucek Prucek commented Feb 3, 2026

This tool could replace tide-config-manager. It could be added as a skill for Claude and for a given lifecycle event; only a correct condition is needed, which could be in a readme.

@openshift-ci-robot
Copy link
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

coderabbitai bot commented Feb 3, 2026

Walkthrough

Introduces a new Python utility in hack/tide-query-manager.py that enables query-based modification of Prow Tide configurations across sharded config files. Supports query parsing, pattern matching, YAML config handling, and dry-run mode.

Changes

Cohort / File(s) Summary
Tide Query Manager Utility
hack/tide-query-manager.py
New utility providing query parsing (QueryCondition class), Tide configuration matching and modification (TideQueryManager class), branch/label pattern matching logic, YAML config loading/saving, dry-run support, and CLI interface for managing Prow Tide configurations across sharded deployments.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Failure to add the new IP will result in interrupted reviews.


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

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 3, 2026

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: 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:

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 Feb 3, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@hack/tide-query-manager.py`:
- Around line 59-60: The comment "Split by spaces while respecting quotes" is
inaccurate for the parts = query.split() call in this code; either remove/adjust
the comment to reflect that query.split() does not handle quotes, or replace the
splitting logic with a quote-aware splitter by importing and using
shlex.split(query) wherever parts is produced. Locate the parts = query.split()
usage and update the comment or change to shlex.split, ensuring any necessary
import of the shlex module and that downstream code still expects a list of
tokens.
- Around line 146-158: Update the file I/O in load_config and save_config to
always open files with explicit UTF-8 encoding: in load_config (which uses
open(...) and yaml.safe_load) open the file with encoding='utf-8', and in
save_config (which calls open(...) and yaml.dump) open the file with
encoding='utf-8' as well; keep the existing Path parent mkdir logic and
yaml.dump options (default_flow_style=False, sort_keys=False).
- Around line 218-219: The two unconditional debug prints referencing
self.sharded_config_dir and len(config_files) should be gated by the object's
verbosity flag; update the code around those prints (the DEBUG lines) to only
execute when self.verbose is truthy so they don't always appear — i.e., wrap or
guard the print statements with an if self.verbose (or equivalent) check in the
method where self.sharded_config_dir and config_files are used.
- Around line 229-242: The org-level config detection is wrong because repo is
modified before testing; change the logic in the block handling len(parts) == 2
so you first check if parts[1] == '_prowconfig.yaml' (org-level) and set repo =
org and full_repo = org in that branch, otherwise set repo =
parts[1].replace('_prowconfig.yaml', '') and full_repo = f"{org}/{repo}"; update
the len(parts) == 2 branch in hack/tide-query-manager.py accordingly to avoid
producing "org/".

Comment on lines +59 to +60
# Split by spaces while respecting quotes
parts = query.split()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Comment claims quote handling that isn't implemented.

The comment states "Split by spaces while respecting quotes" but query.split() does not handle quoted values. If this is intentional (labels don't contain spaces), remove the misleading comment. If quote support is needed, consider using shlex.split().

🤖 Prompt for AI Agents
In `@hack/tide-query-manager.py` around lines 59 - 60, The comment "Split by
spaces while respecting quotes" is inaccurate for the parts = query.split() call
in this code; either remove/adjust the comment to reflect that query.split()
does not handle quotes, or replace the splitting logic with a quote-aware
splitter by importing and using shlex.split(query) wherever parts is produced.
Locate the parts = query.split() usage and update the comment or change to
shlex.split, ensuring any necessary import of the shlex module and that
downstream code still expects a list of tokens.

Comment on lines +146 to +158
def load_config(self, file_path: Path) -> Optional[dict]:
"""Load a YAML configuration file."""
if not file_path.exists():
return None

with open(file_path, 'r') as f:
return yaml.safe_load(f)

def save_config(self, file_path: Path, config: dict):
"""Save a YAML configuration file."""
file_path.parent.mkdir(parents=True, exist_ok=True)
with open(file_path, 'w') as f:
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Specify explicit UTF-8 encoding for file operations.

Missing explicit encoding can cause issues on systems with non-UTF-8 default locale, potentially corrupting config files with non-ASCII characters.

Proposed fix
     def load_config(self, file_path: Path) -> Optional[dict]:
         """Load a YAML configuration file."""
         if not file_path.exists():
             return None

-        with open(file_path, 'r') as f:
+        with open(file_path, 'r', encoding='utf-8') as f:
             return yaml.safe_load(f)

     def save_config(self, file_path: Path, config: dict):
         """Save a YAML configuration file."""
         file_path.parent.mkdir(parents=True, exist_ok=True)
-        with open(file_path, 'w') as f:
+        with open(file_path, 'w', encoding='utf-8') as f:
             yaml.dump(config, f, default_flow_style=False, sort_keys=False)
📝 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
def load_config(self, file_path: Path) -> Optional[dict]:
"""Load a YAML configuration file."""
if not file_path.exists():
return None
with open(file_path, 'r') as f:
return yaml.safe_load(f)
def save_config(self, file_path: Path, config: dict):
"""Save a YAML configuration file."""
file_path.parent.mkdir(parents=True, exist_ok=True)
with open(file_path, 'w') as f:
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
def load_config(self, file_path: Path) -> Optional[dict]:
"""Load a YAML configuration file."""
if not file_path.exists():
return None
with open(file_path, 'r', encoding='utf-8') as f:
return yaml.safe_load(f)
def save_config(self, file_path: Path, config: dict):
"""Save a YAML configuration file."""
file_path.parent.mkdir(parents=True, exist_ok=True)
with open(file_path, 'w', encoding='utf-8') as f:
yaml.dump(config, f, default_flow_style=False, sort_keys=False)
🤖 Prompt for AI Agents
In `@hack/tide-query-manager.py` around lines 146 - 158, Update the file I/O in
load_config and save_config to always open files with explicit UTF-8 encoding:
in load_config (which uses open(...) and yaml.safe_load) open the file with
encoding='utf-8', and in save_config (which calls open(...) and yaml.dump) open
the file with encoding='utf-8' as well; keep the existing Path parent mkdir
logic and yaml.dump options (default_flow_style=False, sort_keys=False).

Comment on lines +218 to +219
print(f"DEBUG: Searching in: {self.sharded_config_dir}")
print(f"DEBUG: Found {len(config_files)} config files")
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

DEBUG prints are always shown regardless of verbose flag.

These debug statements should be gated by self.verbose to avoid cluttering output in normal operation.

Proposed fix
-        print(f"DEBUG: Searching in: {self.sharded_config_dir}")
-        print(f"DEBUG: Found {len(config_files)} config files")
+        if self.verbose:
+            print(f"DEBUG: Searching in: {self.sharded_config_dir}")
+            print(f"DEBUG: Found {len(config_files)} config files")
📝 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
print(f"DEBUG: Searching in: {self.sharded_config_dir}")
print(f"DEBUG: Found {len(config_files)} config files")
if self.verbose:
print(f"DEBUG: Searching in: {self.sharded_config_dir}")
print(f"DEBUG: Found {len(config_files)} config files")
🤖 Prompt for AI Agents
In `@hack/tide-query-manager.py` around lines 218 - 219, The two unconditional
debug prints referencing self.sharded_config_dir and len(config_files) should be
gated by the object's verbosity flag; update the code around those prints (the
DEBUG lines) to only execute when self.verbose is truthy so they don't always
appear — i.e., wrap or guard the print statements with an if self.verbose (or
equivalent) check in the method where self.sharded_config_dir and config_files
are used.

Comment on lines +229 to +242
if len(parts) == 2:
# org/repo/_prowconfig.yaml
org, repo = parts[0], parts[1].replace('_prowconfig.yaml', '')
if repo == '_prowconfig.yaml': # org-level config
repo = parts[0]
full_repo = org
else:
full_repo = f"{org}/{repo}"
elif len(parts) == 3:
# org/repo/_prowconfig.yaml
org, repo = parts[0], parts[1]
full_repo = f"{org}/{repo}"
else:
continue
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Logic bug in org-level config path parsing.

The check at line 232 always evaluates to False because repo has already been transformed by replace() at line 231. For a path like org/_prowconfig.yaml, this produces full_repo = "org/" instead of just "org".

Proposed fix
             if len(parts) == 2:
                 # org/repo/_prowconfig.yaml
-                org, repo = parts[0], parts[1].replace('_prowconfig.yaml', '')
-                if repo == '_prowconfig.yaml':  # org-level config
-                    repo = parts[0]
-                    full_repo = org
+                org = parts[0]
+                filename = parts[1]
+                if filename == '_prowconfig.yaml':  # org-level config
+                    full_repo = org
                 else:
+                    repo = filename.replace('_prowconfig.yaml', '')
                     full_repo = f"{org}/{repo}"
             elif len(parts) == 3:
🤖 Prompt for AI Agents
In `@hack/tide-query-manager.py` around lines 229 - 242, The org-level config
detection is wrong because repo is modified before testing; change the logic in
the block handling len(parts) == 2 so you first check if parts[1] ==
'_prowconfig.yaml' (org-level) and set repo = org and full_repo = org in that
branch, otherwise set repo = parts[1].replace('_prowconfig.yaml', '') and
full_repo = f"{org}/{repo}"; update the len(parts) == 2 branch in
hack/tide-query-manager.py accordingly to avoid producing "org/".

@openshift-ci-robot
Copy link
Contributor

Scheduling required tests:
/test e2e

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Feb 3, 2026

@Prucek: The following tests 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/security 28f5712 link false /test security
ci/prow/breaking-changes 28f5712 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.

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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants