Skip to content

Query dev-preview stream in release controller for EC releases#3197

Open
joepvd wants to merge 1 commit into
openshift-eng:mainfrom
joepvd:fix-rc-dev-preview-query
Open

Query dev-preview stream in release controller for EC releases#3197
joepvd wants to merge 1 commit into
openshift-eng:mainfrom
joepvd:fix-rc-dev-preview-query

Conversation

@joepvd

@joepvd joepvd commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Fix TypeError: 'NoneType' object is not iterable crash in get_release_controller_versions_async() when the release controller returns {"tags": null} (e.g. for 5-stable which has no releases yet)
  • Query both {major}-stable and {major}-dev-preview release controller streams, since EC releases (e.g. 5.0.0-ec.5) are promoted to dev-preview, not stable
  • Extract HTTP+parse logic into _fetch_release_controller_tags() helper to avoid duplication

Test plan

  • Existing tests updated to account for two HTTP calls (stable + dev-preview)
  • New test: test_null_tags_returns_empty — verifies {"tags": null} returns []
  • New test: test_dev_preview_versions_included — verifies EC releases from dev-preview are returned
  • New test: test_union_of_stable_and_dev_preview — verifies deduplication across streams
  • All 3067 unit tests pass (make unit)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Improved release version discovery by checking both stable and developer-preview release streams.
    • Filters results to valid semantic versions matching the requested major and minor release.
    • Combines and deduplicates versions, including eligible EC releases, in descending version order.
    • Handles unavailable or empty tag data gracefully without failing.

The release controller query only checked {major}-stable, but EC releases
(e.g. 5.0.0-ec.5) are promoted to {major}-dev-preview. This caused
gen-assembly to crash for 5.0 EC assemblies because 5-stable returns
{"tags": null}, and data.get('tags', []) doesn't guard against explicit
null values.

Fix both issues:
- Use `data.get('tags') or []` to handle null tags without crashing
- Query both {major}-stable and {major}-dev-preview streams, unioning
  the results

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@openshift-ci

openshift-ci Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign rayfordj for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found 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

@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Walkthrough

get_release_controller_versions_async() now retrieves matching valid semver tags from both stable and dev-preview release-controller streams, merges and deduplicates them, and sorts them descending. Tests cover URL construction, filtering, invalid tags, null responses, EC versions, ordering, and union behavior.

Changes

Release controller versions

Layer / File(s) Summary
Fetch and merge release streams
artcommon/artcommonlib/ocp_version_ancestry.py
Added per-stream tag fetching with major/minor filtering and semver validation, then merged stable and dev-preview versions with deduplication and descending sorting.
Validate stream lookup behavior
artcommon/tests/test_ocp_version_ancestry.py
Expanded tests for two-stream requests, URL construction, invalid and null tags, dev-preview EC versions, sorting, filtering, and deduplication.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant get_release_controller_versions_async
  participant ReleaseController
  Caller->>get_release_controller_versions_async: request major.minor versions
  get_release_controller_versions_async->>ReleaseController: GET stable tags
  ReleaseController-->>get_release_controller_versions_async: stable tag data
  get_release_controller_versions_async->>ReleaseController: GET dev-preview tags
  ReleaseController-->>get_release_controller_versions_async: dev-preview tag data
  get_release_controller_versions_async-->>Caller: merged sorted versions
Loading

Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❌ Error The release-controller warning logs the full URL, which can expose internal hostnames or embedded credentials if a custom base URL is used. Redact the host/base URL in the warning, or log only the stream name and status/error without the full request URL.
Ai-Attribution ⚠️ Warning HEAD commit uses Co-Authored-By: Claude Opus 4.6 and lacks Assisted-by/Generated-by Red Hat attribution. Replace the AI Co-Authored-By line with a Red Hat Assisted-by or Generated-by trailer, and keep AI attribution out of co-author lines.
✅ Passed checks (9 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: querying the dev-preview release controller stream for EC releases.
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.
No-Weak-Crypto ✅ Passed No weak crypto or secret comparison was added; the PR only changes release-controller version fetching and tests.
Container-Privileges ✅ Passed PR only changes two Python files; no container/K8s manifests or privilege flags appear in the diff.
No-Hardcoded-Secrets ✅ Passed No added lines contain hardcoded secrets, embedded credentials, or suspicious secret-like literals in the changed files.
No-Injection-Vectors ✅ Passed Changed code uses yaml.safe_load and no eval/exec, shell=True, pickle.loads, os.system, SQL, or dangerous innerHTML patterns appear in the diff.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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: 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 `@artcommon/artcommonlib/ocp_version_ancestry.py`:
- Around line 376-385: Update the release-controller response parsing around the
tags/version extraction loop to validate each stream’s decoded payload before
accessing it: handle invalid JSON, non-object payloads, non-list tags, and
malformed tag entries by returning [] for that stream. Keep HTTP errors handled
as currently, and ensure parsing/shape failures are contained so the second
stream is still queried.
🪄 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-eng/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 9e1ed082-7968-412c-956e-35083cc387dc

📥 Commits

Reviewing files that changed from the base of the PR and between d3df44b and ec3d88e.

📒 Files selected for processing (2)
  • artcommon/artcommonlib/ocp_version_ancestry.py
  • artcommon/tests/test_ocp_version_ancestry.py

Comment on lines +376 to 385
tags = data.get('tags') or []

# Filter tags to only those matching the requested major.minor.
# Tag names are version strings like "4.18.3" or "4.18.0-rc.0".
version_pattern = re.compile(rf'^{major}\.{minor}\.')
versions = []
for tag in tags:
name = tag.get('name', '')
if version_pattern.match(name):
# Validate it's a proper semver string before including
try:
semver.VersionInfo.parse(name)
versions.append(name)

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.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

FILE="artcommon/artcommonlib/ocp_version_ancestry.py"

echo "== Line count =="
wc -l "$FILE"

echo
echo "== Outline =="
ast-grep outline "$FILE" --view expanded || true

echo
echo "== Relevant section =="
sed -n '320,450p' "$FILE" | cat -n

Repository: openshift-eng/art-tools

Length of output: 7535


Make release-controller parsing non-fatal. Invalid JSON, non-object payloads, non-list tags, or malformed tag entries can raise outside the httpx.HTTPError handler and stop the second stream from being queried. Validate the decoded payload per stream and return [] on parse/shape errors instead.

🧰 Tools
🪛 ast-grep (0.44.1)

[warning] 377-377: Regex pattern passed to re is built from a non-literal (variable, call, concatenation, or f-string) value. If that value is attacker-controlled it can introduce a malicious pattern with catastrophic backtracking (ReDoS). Use a hardcoded literal pattern, or validate/escape untrusted input with re.escape() and bound the regex complexity before compiling.
Context: re.compile(rf'^{major}.{minor}.')
Note: [CWE-1333] Inefficient Regular Expression Complexity.

(redos-non-literal-regex-python)

🤖 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 `@artcommon/artcommonlib/ocp_version_ancestry.py` around lines 376 - 385,
Update the release-controller response parsing around the tags/version
extraction loop to validate each stream’s decoded payload before accessing it:
handle invalid JSON, non-object payloads, non-list tags, and malformed tag
entries by returning [] for that stream. Keep HTTP errors handled as currently,
and ensure parsing/shape failures are contained so the second stream is still
queried.

@openshift-ci

openshift-ci Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

@joepvd: 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/art-pre-commit-check ec3d88e link false /test art-pre-commit-check
ci/prow/security ec3d88e link false /test security

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

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant