Skip to content

[IUO] Install plan upgrade test#4394

Open
hmeir wants to merge 1 commit intoRedHatQE:mainfrom
hmeir:install-plan-upgrade-test
Open

[IUO] Install plan upgrade test#4394
hmeir wants to merge 1 commit intoRedHatQE:mainfrom
hmeir:install-plan-upgrade-test

Conversation

@hmeir
Copy link
Copy Markdown
Contributor

@hmeir hmeir commented Apr 12, 2026

Short description:

This PR implements an early InstallPlan validation test to catch configuration errors immediately at the start of the execution suite.

More details:

To prevent failing after 1+ hours of runtime due to incorrect channels or images, this PR introduces a "fail early" mechanism. A new InstallPlan validation test is added to the start of the suite to verify that the correct InstallPlan is created according to the source/target versions and channels before proceeding.

New Execution Order:
InstallPlan test -> pre-upgrade tests -> cnv upgrade test -> post upgrade tests

What this PR does / why we need it:
  • Reduces Feedback Loop: Detects configuration errors in minutes rather than hours.
  • Optimizes Resource Usage: Prevents wasting CI time on runs that are destined to fail due to initial config errors.
Special notes for reviewer:

Focuses specifically on the new validation logic in the initial test phase.

jira-ticket:

Signed-off-by: Harel Meir <hmeir@redhat.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 12, 2026

📝 Walkthrough

Walkthrough

This PR refactors CNV upgrade testing infrastructure by introducing EUS upgrade stream detection, reorganizing fixture dependencies with production source awareness, and decomposing install plan creation into a separate gated test. It also refactors IDMS mirror application logic to conditionally update existing entries, adds Konflux-related constants, and enhances subscription-scoped fixture wiring throughout the upgrade test suite.

Changes

Cohort / File(s) Summary
Upgrade Stream Detection & Constants
utilities/constants.py, utilities/pytest_utils.py, tests/conftest.py
Added UpgradeStreams.EUS constant; updated get_cnv_version_explorer_url() to accept "cnv" upgrade value; added EUS upgrade path detection when target minor is even and exactly two minors higher than current minor.
Core Install Plan & CNV Upgrade Flow
tests/install_upgrade_operators/product_upgrade/conftest.py, tests/install_upgrade_operators/product_upgrade/utils.py
Replaced cnv_image_name session fixture with iib_build_info that parses IIB number and queries version explorer; updated perform_cnv_upgrade() to accept cnv_subscription parameter; removed approve_cnv_upgrade_install_plan() helper and moved install plan fetching inline; refactored IDMS mirror application to gate on iib_build_info["pipeline"] instead of hotfix detection.
Test Structure & Execution
tests/install_upgrade_operators/product_upgrade/test_upgrade.py, tests/virt/upgrade/test_upgrade_virt.py
Added new test_cnv_upgrade_install_plan_creation() as first gated test to handle install plan approval separately; converted pytestmark from decorator assignment to fixture list; removed obsolete fixture parameters from test_cnv_upgrade_process(); updated test execution order marker from "first" to "second".
Fixture Signature & Production Source Support
tests/install_upgrade_operators/conftest.py
Added is_production_source parameter to disabled_default_sources_in_operatorhub fixture; now skips disabling behavior when either installing_cnv or is_production_source is true.
Configuration Constants & Imports
tests/install_upgrade_operators/constants.py, tests/install_upgrade_operators/product_install/conftest.py
Added five Konflux/registry constants: KONFLUX_IDMS_NAME, KONFLUX_MIRROR_BASE_URL, RH_IDMS_SOURCE, KONFLUX_PIPELINE, BREW_MIRROR_BASE_URL; migrated imports from utils to constants.
IDMS Mirror Application & Install Plan Resolution
tests/install_upgrade_operators/product_install/conftest.py, tests/install_upgrade_operators/utils.py
Updated wait_for_install_plan() to accept cnv_subscription parameter instead of fetching subscription internally; refactored apply_konflux_idms() to compute per-entry mirror updates when IDMS exists, appending only missing mirror URLs to existing entries; removed idms_has_all_mirrors() helper and introduced _get_entries_with_missing_mirrors(); removed unconditional IDMS application in product install conftest, now applied only when is_production_source is false.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 30.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title '[IUO] Install plan upgrade test' is partially related to the changeset—it references the main InstallPlan validation feature but misses the significant IDMS patching logic modification, which comprises a substantial portion of the changes.
Description check ✅ Passed The PR description includes all required sections with substantive content addressing the rationale, scope, benefits, and implementation approach for the early InstallPlan validation mechanism.

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

✨ 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 and usage tips.

@openshift-virtualization-qe-bot
Copy link
Copy Markdown

Report bugs in Issues

Welcome! 🎉

This pull request will be automatically processed with the following features:

🔄 Automatic Actions

  • Reviewer Assignment: Reviewers are automatically assigned based on the OWNERS file in the repository root
  • Size Labeling: PR size labels (XS, S, M, L, XL, XXL) are automatically applied based on changes
  • Issue Creation: A tracking issue is created for this PR and will be closed when the PR is merged or closed
  • Branch Labeling: Branch-specific labels are applied to track the target branch
  • Auto-verification: Auto-verified users have their PRs automatically marked as verified
  • Labels: Enabled categories: branch, can-be-merged, cherry-pick, has-conflicts, hold, needs-rebase, size, verified, wip

📋 Available Commands

PR Status Management

  • /wip - Mark PR as work in progress (adds WIP: prefix to title)
  • /wip cancel - Remove work in progress status
  • /hold - Block PR merging (approvers only)
  • /hold cancel - Unblock PR merging
  • /verified - Mark PR as verified
  • /verified cancel - Remove verification status
  • /reprocess - Trigger complete PR workflow reprocessing (useful if webhook failed or configuration changed)
  • /regenerate-welcome - Regenerate this welcome message

Review & Approval

  • /lgtm - Approve changes (looks good to me)
  • /approve - Approve PR (approvers only)
  • /assign-reviewers - Assign reviewers based on OWNERS file
  • /assign-reviewer @username - Assign specific reviewer
  • /check-can-merge - Check if PR meets merge requirements

Testing & Validation

  • /retest tox - Run Python test suite with tox
  • /retest build-container - Rebuild and test container image
  • /retest verify-bugs-are-open - verify-bugs-are-open
  • /retest all - Run all available tests

Container Operations

  • /build-and-push-container - Build and push container image (tagged with PR number)
    • Supports additional build arguments: /build-and-push-container --build-arg KEY=value

Cherry-pick Operations

  • /cherry-pick <branch> - Schedule cherry-pick to target branch when PR is merged
    • Multiple branches: /cherry-pick branch1 branch2 branch3

Label Management

  • /<label-name> - Add a label to the PR
  • /<label-name> cancel - Remove a label from the PR

✅ Merge Requirements

This PR will be automatically approved when the following conditions are met:

  1. Approval: /approve from at least one approver
  2. LGTM Count: Minimum 2 /lgtm from reviewers
  3. Status Checks: All required status checks must pass
  4. No Blockers: No wip, hold, has-conflicts labels and PR must be mergeable (no conflicts)
  5. Verified: PR must be marked as verified

📊 Review Process

Approvers and Reviewers

Approvers:

  • dshchedr
  • myakove
  • rnetser
  • vsibirsk

Reviewers:

  • OhadRevah
  • RoniKishner
  • SamAlber
  • SiboWang1997
  • akri3i
  • albarker-rh
  • dshchedr
  • geetikakay
  • hmeir
  • jerry7z
  • kbidarkar
  • rlobillo
  • rnetser
  • vsibirsk
Available Labels
  • hold
  • verified
  • wip
  • lgtm
  • approve
AI Features
  • Cherry-Pick Conflict Resolution: Enabled (claude/claude-opus-4-6[1m])

💡 Tips

  • WIP Status: Use /wip when your PR is not ready for review
  • Verification: The verified label is removed on new commits unless the push is detected as a clean rebase
  • Cherry-picking: Cherry-pick labels are processed when the PR is merged
  • Container Builds: Container images are automatically tagged with the PR number
  • Permission Levels: Some commands require approver permissions
  • Auto-verified Users: Certain users have automatic verification and merge privileges

For more information, please refer to the project documentation or contact the maintainers.

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 12, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.65%. Comparing base (b4ad2e0) to head (c2b697a).
⚠️ Report is 53 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #4394      +/-   ##
==========================================
+ Coverage   98.63%   98.65%   +0.02%     
==========================================
  Files          25       25              
  Lines        2420     2460      +40     
==========================================
+ Hits         2387     2427      +40     
  Misses         33       33              
Flag Coverage Δ
utilities 98.65% <100.00%> (+0.02%) ⬆️

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

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

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown
Contributor

@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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
tests/conftest.py (1)

1788-1793: ⚠️ Potential issue | 🔴 Critical

CRITICAL: EUS branch is unreachable because Line 1788 matches first.

At Line 1788, any target.minor > current.minor returns Y_STREAM, so the EUS condition at Lines 1792-1793 never executes.
Why this matters: specific routing rules must be evaluated before generic ones, or the specific path is effectively dead code.

💡 Proposed fix
-    elif current_cnv_version.minor < target_cnv_version.minor:
-        return UpgradeStreams.Y_STREAM
+    elif (
+        current_cnv_version.major == target_cnv_version.major
+        and target_cnv_version.minor % 2 == 0
+        and target_cnv_version.minor - current_cnv_version.minor == 2
+    ):
+        return UpgradeStreams.EUS
+    elif current_cnv_version.minor < target_cnv_version.minor:
+        return UpgradeStreams.Y_STREAM
     elif current_cnv_version.micro < target_cnv_version.micro:
         return UpgradeStreams.Z_STREAM
-    elif target_cnv_version.minor % 2 == 0 and target_cnv_version.minor - 2 == current_cnv_version.minor:
-        return UpgradeStreams.EUS
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/conftest.py` around lines 1788 - 1793, The EUS branch (checking
target_cnv_version.minor % 2 == 0 and target_cnv_version.minor - 2 ==
current_cnv_version.minor which returns UpgradeStreams.EUS) is unreachable
because the earlier condition "elif current_cnv_version.minor <
target_cnv_version.minor: return UpgradeStreams.Y_STREAM" catches any
target.minor > current.minor first; fix by evaluating the specific EUS case
before the generic minor-increase check (i.e., check the EUS condition involving
current_cnv_version and target_cnv_version first, then fall back to the generic
current_cnv_version.minor < target_cnv_version.minor ->
UpgradeStreams.Y_STREAM), keeping all version symbol names exactly as used
(current_cnv_version, target_cnv_version, UpgradeStreams.Y_STREAM,
UpgradeStreams.EUS).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@tests/install_upgrade_operators/product_upgrade/conftest.py`:
- Around line 136-142: The change reversed the intended logic so
updated_konflux_idms no longer runs for disconnected clusters: ensure the
function runs only when is_disconnected_cluster is True and
iib_build_info.get("pipeline") == KONFLUX_PIPELINE; i.e., remove or invert the
early return that currently exits when is_disconnected_cluster is True and
instead only return when NOT disconnected OR when the pipeline is not
KONFLUX_PIPELINE so updated_konflux_idms is invoked for disconnected Konflux
installs.

In `@tests/install_upgrade_operators/product_upgrade/test_upgrade.py`:
- Around line 25-49: The test test_cnv_upgrade_install_plan_creation now
declares shared setup fixtures (disabled_default_sources_in_operatorhub,
updated_konflux_idms, updated_custom_hco_catalog_source_image,
updated_cnv_subscription_source) and is marked `@pytest.mark.order`("first"),
which makes downstream tests (test_cnv_upgrade_process,
test_production_source_cnv_upgrade_process) dependent on its side-effects; to
fix, restore independence by removing those shared fixtures from
test_cnv_upgrade_install_plan_creation and re-attaching them to the actual
upgrade tests (test_cnv_upgrade_process and
test_production_source_cnv_upgrade_process), or explicitly declare a
pytest-dependency on those downstream tests using
`@pytest.mark.dependency`(depends=["test_cnv_upgrade_install_plan_creation"]) on
each dependent test and add a one-line comment explaining WHY the dependency
exists (that these tests require the catalog/operatorhub changes as
side-effects); ensure you keep the `@pytest.mark.order` only if ordering is still
needed.

In `@tests/install_upgrade_operators/utils.py`:
- Around line 99-101: The code dereferences
cnv_subscription.instance.status.installplan before getattr runs causing
AttributeError when status or installplan is None; update the assignment for
install_plan_name_in_subscription inside the install_plan_sampler loop to safely
traverse the nested attributes (e.g., check for None or use nested getattr
calls) so you only access .name when installplan exists on
cnv_subscription.instance.status; target the install_plan_sampler loop and the
variable install_plan_name_in_subscription to implement the guarded lookup.
- Around line 314-321: The code currently treats any mirror that startswith a
base URL as satisfying per-image mirrors; change the presence check to look for
the exact per-image mirror (construct expected = f"{url}/{image_name}") rather
than using startswith. In the block handling entry["source"]/image_name and
mirrors, replace the any(m.startswith(url) for m in mirrors) test with a strict
equality check against the constructed per-image URL (normalizing trailing
slashes if needed) so missing becomes only those exact per-image URLs and then
append those exact URLs to entry["mirrors"] and set has_changes accordingly.

---

Outside diff comments:
In `@tests/conftest.py`:
- Around line 1788-1793: The EUS branch (checking target_cnv_version.minor % 2
== 0 and target_cnv_version.minor - 2 == current_cnv_version.minor which returns
UpgradeStreams.EUS) is unreachable because the earlier condition "elif
current_cnv_version.minor < target_cnv_version.minor: return
UpgradeStreams.Y_STREAM" catches any target.minor > current.minor first; fix by
evaluating the specific EUS case before the generic minor-increase check (i.e.,
check the EUS condition involving current_cnv_version and target_cnv_version
first, then fall back to the generic current_cnv_version.minor <
target_cnv_version.minor -> UpgradeStreams.Y_STREAM), keeping all version symbol
names exactly as used (current_cnv_version, target_cnv_version,
UpgradeStreams.Y_STREAM, UpgradeStreams.EUS).
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: e52462b6-b2ba-47eb-a4db-55659b48c568

📥 Commits

Reviewing files that changed from the base of the PR and between 45d1fc4 and c2b697a.

📒 Files selected for processing (11)
  • tests/conftest.py
  • tests/install_upgrade_operators/conftest.py
  • tests/install_upgrade_operators/constants.py
  • tests/install_upgrade_operators/product_install/conftest.py
  • tests/install_upgrade_operators/product_upgrade/conftest.py
  • tests/install_upgrade_operators/product_upgrade/test_upgrade.py
  • tests/install_upgrade_operators/product_upgrade/utils.py
  • tests/install_upgrade_operators/utils.py
  • tests/virt/upgrade/test_upgrade_virt.py
  • utilities/constants.py
  • utilities/pytest_utils.py

Comment on lines 136 to 142
if is_disconnected_cluster:
LOGGER.warning("Skip applying IDMS in a disconnected setup.")
return

if cnv_source == HOTFIX_STR:
LOGGER.info("IDMS updates skipped as upgrading using production source/upgrade to hotfix")
if iib_build_info.get("pipeline") != KONFLUX_PIPELINE:
LOGGER.warning(f"Pipeline is '{iib_build_info.get('pipeline')}', not Konflux. Skipping IDMS.")
return
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.

⚠️ Potential issue | 🔴 Critical

CRITICAL: This reverses the IDMS setup condition.

updated_konflux_idms used to apply mirrors only for disconnected clusters, which is where the IDMS is needed. The new early return on is_disconnected_cluster skips the patch in exactly that environment, so the install-plan precheck and later upgrade flow run without the required mirror configuration.

Proposed fix
-    if is_disconnected_cluster:
-        LOGGER.warning("Skip applying IDMS in a disconnected setup.")
+    if not is_disconnected_cluster:
+        LOGGER.info("Connected setup; skipping Konflux IDMS update.")
         return
🧰 Tools
🪛 Ruff (0.15.9)

[warning] 141-141: Logging statement uses f-string

(G004)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/install_upgrade_operators/product_upgrade/conftest.py` around lines 136
- 142, The change reversed the intended logic so updated_konflux_idms no longer
runs for disconnected clusters: ensure the function runs only when
is_disconnected_cluster is True and iib_build_info.get("pipeline") ==
KONFLUX_PIPELINE; i.e., remove or invert the early return that currently exits
when is_disconnected_cluster is True and instead only return when NOT
disconnected OR when the pipeline is not KONFLUX_PIPELINE so
updated_konflux_idms is invoked for disconnected Konflux installs.

Comment on lines +25 to +49
@pytest.mark.gating
@pytest.mark.cnv_upgrade
@pytest.mark.order("first")
@pytest.mark.polarion("CNV-12451")
@pytest.mark.usefixtures(
"cnv_upgrade_stream",
"disabled_default_sources_in_operatorhub",
"updated_konflux_idms",
"updated_custom_hco_catalog_source_image",
"updated_cnv_subscription_source",
)
def test_cnv_upgrade_install_plan_creation(
admin_client,
hco_namespace,
hco_target_csv_name,
is_production_source,
cnv_subscription_scope_session,
):
wait_for_install_plan(
client=admin_client,
hco_namespace=hco_namespace.name,
hco_target_csv_name=hco_target_csv_name,
is_production_source=is_production_source,
cnv_subscription=cnv_subscription_scope_session,
)
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.

⚠️ Potential issue | 🟠 Major

HIGH: This precheck is ordered first, but the downstream CNV tests now depend on its side effects.

After moving disabled_default_sources_in_operatorhub, updated_konflux_idms, updated_custom_hco_catalog_source_image, and updated_cnv_subscription_source onto this test, test_cnv_upgrade_process() and test_production_source_cnv_upgrade_process() are no longer independently runnable. @pytest.mark.order("first") only changes order; it does not stop later tests from running without this setup when the precheck is deselected, rerun selectively, or fails. Keep the shared setup fixtures on the upgrade tests too, or add an explicit dependency contract for the test-to-test gating.

As per coding guidelines "Tests MUST be independent; use pytest-dependency ONLY when test B requires side effects from test A; when using @pytest.mark.dependency, a comment explaining WHY the dependency exists is REQUIRED".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/install_upgrade_operators/product_upgrade/test_upgrade.py` around lines
25 - 49, The test test_cnv_upgrade_install_plan_creation now declares shared
setup fixtures (disabled_default_sources_in_operatorhub, updated_konflux_idms,
updated_custom_hco_catalog_source_image, updated_cnv_subscription_source) and is
marked `@pytest.mark.order`("first"), which makes downstream tests
(test_cnv_upgrade_process, test_production_source_cnv_upgrade_process) dependent
on its side-effects; to fix, restore independence by removing those shared
fixtures from test_cnv_upgrade_install_plan_creation and re-attaching them to
the actual upgrade tests (test_cnv_upgrade_process and
test_production_source_cnv_upgrade_process), or explicitly declare a
pytest-dependency on those downstream tests using
`@pytest.mark.dependency`(depends=["test_cnv_upgrade_install_plan_creation"]) on
each dependent test and add a one-line comment explaining WHY the dependency
exists (that these tests require the catalog/operatorhub changes as
side-effects); ensure you keep the `@pytest.mark.order` only if ordering is still
needed.

Comment on lines 99 to +101
for install_plan_samples in install_plan_sampler:
# wait for the install plan to be created and updated in the subscription.
install_plan_name_in_subscription = getattr(subscription.instance.status.installplan, "name", None)
install_plan_name_in_subscription = getattr(cnv_subscription.instance.status.installplan, "name", None)
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.

⚠️ Potential issue | 🔴 Critical

CRITICAL: Guard the subscription InstallPlan lookup while it is still unset.

Line 101 still dereferences .status.installplan before getattr() runs. On the first sampler iterations the Subscription often has no InstallPlan yet, so this raises AttributeError instead of continuing to wait.

Proposed fix
-            install_plan_name_in_subscription = getattr(cnv_subscription.instance.status.installplan, "name", None)
+            subscription_status = getattr(cnv_subscription.instance, "status", None)
+            install_plan_ref = getattr(subscription_status, "installplan", None)
+            install_plan_name_in_subscription = getattr(install_plan_ref, "name", None)
📝 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
for install_plan_samples in install_plan_sampler:
# wait for the install plan to be created and updated in the subscription.
install_plan_name_in_subscription = getattr(subscription.instance.status.installplan, "name", None)
install_plan_name_in_subscription = getattr(cnv_subscription.instance.status.installplan, "name", None)
for install_plan_samples in install_plan_sampler:
# wait for the install plan to be created and updated in the subscription.
subscription_status = getattr(cnv_subscription.instance, "status", None)
install_plan_ref = getattr(subscription_status, "installplan", None)
install_plan_name_in_subscription = getattr(install_plan_ref, "name", None)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/install_upgrade_operators/utils.py` around lines 99 - 101, The code
dereferences cnv_subscription.instance.status.installplan before getattr runs
causing AttributeError when status or installplan is None; update the assignment
for install_plan_name_in_subscription inside the install_plan_sampler loop to
safely traverse the nested attributes (e.g., check for None or use nested
getattr calls) so you only access .name when installplan exists on
cnv_subscription.instance.status; target the install_plan_sampler loop and the
variable install_plan_name_in_subscription to implement the guarded lookup.

Comment on lines +314 to +321
if entry["source"].startswith(RH_IDMS_SOURCE):
image_name = entry["source"].removeprefix(f"{RH_IDMS_SOURCE}/")
mirrors = entry.get("mirrors", [])
missing = [f"{url}/{image_name}" for url in required_mirrors if not any(m.startswith(url) for m in mirrors)]
if missing:
entry["mirrors"] = mirrors + missing
has_changes = True
return mirror_entries if has_changes else []
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.

⚠️ Potential issue | 🟠 Major

HIGH: Base-URL matches hide missing per-image mirrors.

Line 317 treats any mirror that merely starts with the version base URL as “already present”. An existing mirror like .../v4-22 will therefore suppress adding the required per-image mirror .../v4-22/virt-api-rhel9, so older coarse-grained entries never get upgraded to the per-image layout. This is especially easy to hit because the create path at Lines 355-360 seeds those base URLs.

Proposed fix
-            missing = [f"{url}/{image_name}" for url in required_mirrors if not any(m.startswith(url) for m in mirrors)]
+            missing = [
+                f"{url}/{image_name}"
+                for url in required_mirrors
+                if f"{url}/{image_name}" not in mirrors
+            ]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@tests/install_upgrade_operators/utils.py` around lines 314 - 321, The code
currently treats any mirror that startswith a base URL as satisfying per-image
mirrors; change the presence check to look for the exact per-image mirror
(construct expected = f"{url}/{image_name}") rather than using startswith. In
the block handling entry["source"]/image_name and mirrors, replace the
any(m.startswith(url) for m in mirrors) test with a strict equality check
against the constructed per-image URL (normalizing trailing slashes if needed)
so missing becomes only those exact per-image URLs and then append those exact
URLs to entry["mirrors"] and set has_changes accordingly.

@openshift-virtualization-qe-bot-3
Copy link
Copy Markdown
Contributor

/retest all

Auto-triggered: Files in this PR were modified by merged PR #4365.

Overlapping files

tests/conftest.py

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants