Skip to content

Remove RHEC tests and add multiple source tests#597

Merged
dbasunag merged 2 commits intoopendatahub-io:mainfrom
dbasunag:multiple_sources
Sep 9, 2025
Merged

Remove RHEC tests and add multiple source tests#597
dbasunag merged 2 commits intoopendatahub-io:mainfrom
dbasunag:multiple_sources

Conversation

@dbasunag
Copy link
Copy Markdown
Collaborator

@dbasunag dbasunag commented Sep 9, 2025

Description

How Has This Been Tested?

Merge criteria:

  • The commits are squashed in a cohesive manner and have meaningful messages.
  • Testing instructions have been added in the PR body (for PRs involving changes that are not immediately obvious).
  • The developer has manually tested the changes and verified that the changes work

Summary by CodeRabbit

  • New Features

    • Support for multiple custom catalogs in listing sources, models, and artifacts.
    • Ability to add and remove models in a custom catalog, with readiness/API checks around updates.
    • Clearer "not found" error handling when models are missing.
  • Tests

    • Expanded coverage for single- and multi-catalog scenarios.
    • New tests for add/remove model flows and updated assertions for multiple entries.
    • Improved test data generation and logging.
  • Chores

    • Streamlined handling of multiple sample YAML entries in configuration.

@dbasunag dbasunag requested review from fege and lugi0 as code owners September 9, 2025 01:05
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Sep 9, 2025

📝 Walkthrough

Walkthrough

Switches model-catalog tests from single static catalog data to multi-catalog, dynamic YAML generation. Adds YAML helper utilities, a fixture to append a model to a custom catalog, local ResourceNotFoundError handling, and test refactors that add/rename tests for listing sources, retrieving models/artifacts, and add/remove flows.

Changes

Cohort / File(s) Summary
Fixtures & patching / YAML appender
tests/model_registry/model_catalog/conftest.py
Extend configmap patching to apply multiple sample_yaml keys; add update_configmap_data_add_model fixture that appends a model YAML (using get_model_str) to a custom catalog entry, waits for readiness/API, yields the ConfigMap, and re-checks readiness after tests.
Test utilities
tests/model_registry/model_catalog/utils.py
Add local ResourceNotFoundError, make _execute_get_call raise it on non-200/201, adapt retry usage; add YAML builders get_catalog_str(ids), get_sample_yaml_str(models), and get_model_str(model) for dynamic catalog/sample YAML generation.
Constants (test data)
tests/model_registry/model_catalog/constants.py
Replace single-catalog constants with multi-catalog model: add CUSTOM_CATALOG_ID1/2, SAMPLE_MODEL_NAME1/2/3, EXPECTED_CUSTOM_CATALOG_VALUES (list) and MULTIPLE_CUSTOM_CATALOG_VALUES, plus default catalog metadata; remove legacy echo/single-catalog constants.
Tests: refactor, rename, additions
tests/model_registry/model_catalog/test_custom_model_catalog.py
Replace static fixtures with dynamic YAML via helpers; rename tests (test_model_custom_catalog_list_sources, test_model_custom_catalog_get_models_by_source, test_model_custom_catalog_get_model_artifact), parameterize for single/multi-catalog scenarios, add test_model_custom_catalog_add_model and test_model_custom_catalog_remove_model, and adjust validations to iterate expected entries and expect ResourceNotFoundError for removed models.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks (1 passed, 2 warnings)

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description Check ⚠️ Warning The description remains a generic template with placeholder headings and unchecked checklist items, failing to convey any details about the actual changes made in the pull request. Please update the pull request description to include a concise summary of the implemented changes, details on how they were tested, and confirmation that merge criteria have been met.
Docstring Coverage ⚠️ Warning Docstring coverage is 42.86% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (1 passed)
Check name Status Explanation
Title Check ✅ Passed The title succinctly and accurately summarizes the main changes by indicating the removal of RHEC tests and the addition of multiple source tests, which aligns with the core modifications introduced in the pull request.

Tip

👮 Agentic pre-merge checks are now available in preview!

Pro plan users can now enable pre-merge checks in their settings to enforce checklists before merging PRs.

  • Built-in checks – Quickly apply ready-made checks to enforce title conventions, require pull request descriptions that follow templates, validate linked issues for compliance, and more.
  • Custom agentic checks – Define your own rules using CodeRabbit’s advanced agentic capabilities to enforce organization-specific policies and workflows. For example, you can instruct CodeRabbit’s agent to verify that API documentation is updated whenever API schema files are modified in a PR. Note: Upto 5 custom checks are currently allowed during the preview period. Pricing for this feature will be announced in a few weeks.

Example:

reviews:
  pre_merge_checks:
    custom_checks:
      - name: "Undocumented Breaking Changes"
        mode: "warning"
        instructions: |
          Pass/fail criteria: All breaking changes to public APIs, CLI flags, environment variables, configuration keys, database schemas, or HTTP/GraphQL endpoints must be documented in the "Breaking Change" section of the PR description and in CHANGELOG.md. Exclude purely internal or private changes (e.g., code not exported from package entry points or explicitly marked as internal).

Please share your feedback with us on this Discord post.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Sep 9, 2025

The following are automatically added/executed:

  • PR size label.
  • Run pre-commit
  • Run tox
  • Add PR author as the PR assignee
  • Build image based on the PR

Available user actions:

  • To mark a PR as WIP, add /wip in a comment. To remove it from the PR comment /wip cancel to the PR.
  • To block merging of a PR, add /hold in a comment. To un-block merging of PR comment /hold cancel.
  • To mark a PR as approved, add /lgtm in a comment. To remove, add /lgtm cancel.
    lgtm label removed on each new commit push.
  • To mark PR as verified comment /verified to the PR, to un-verify comment /verified cancel to the PR.
    verified label removed on each new commit push.
  • To Cherry-pick a merged PR /cherry-pick <target_branch_name> to the PR. If <target_branch_name> is valid,
    and the current PR is merged, a cherry-picked PR would be created and linked to the current PR.
  • To build and push image to quay, add /build-push-pr-image in a comment. This would create an image with tag
    pr-<pr_number> to quay repository. This image tag, however would be deleted on PR merge or close action.
Supported labels

{'/lgtm', '/verified', '/wip', '/cherry-pick', '/build-push-pr-image', '/hold'}

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: 1

Caution

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

⚠️ Outside diff range comments (2)
tests/model_registry/model_catalog/utils.py (2)

22-30: Differentiate 404 from other HTTP failures; broaden retry coverage

Conflating all non-2xx as “not found” can mask real server/auth errors and cause false-green tests. Raise a specific NotFound only on 404 and a generic API error otherwise; retry on both.

-class ResourceNotFoundError(Exception):
-    pass
+class APIRequestError(Exception):
+    pass
+
+class ResourceNotFoundError(APIRequestError):
+    pass
@@
 def _execute_get_call(url: str, headers: dict[str, str], verify: bool | str = False) -> requests.Response:
     resp = requests.get(url=url, headers=headers, verify=verify, timeout=60)
-    if resp.status_code not in [200, 201]:
-        raise ResourceNotFoundError(f"Get call failed for resource: {url}, {resp.status_code}: {resp.text}")
+    if resp.status_code == 404:
+        raise ResourceNotFoundError(f"Resource not found: {url} (404)")
+    if resp.status_code not in (200, 201):
+        raise APIRequestError(f"GET {url} failed: {resp.status_code}: {resp.text}")
     return resp
@@
-@retry(wait_timeout=60, sleep=5, exceptions_dict={ResourceNotFoundError: []})
+@retry(wait_timeout=60, sleep=5, exceptions_dict={ResourceNotFoundError: [], APIRequestError: []})
 def wait_for_model_catalog_api(url: str, headers: dict[str, str], verify: bool | str = False) -> requests.Response:
     return _execute_get_call(url=f"{url}sources", headers=headers, verify=verify)

Also applies to: 33-35


47-53: Guard against missing env list to avoid NPE

container.env can be None. Iterate safely.

 def validate_model_catalog_enabled(pod: Pod) -> bool:
-    for container in pod.instance.spec.containers:
-        for env in container.env:
+    for container in pod.instance.spec.containers:
+        for env in (getattr(container, "env", None) or []):
             if env.name == "ENABLE_MODEL_CATALOG":
                 return True
     return False
🧹 Nitpick comments (10)
tests/model_registry/model_catalog/utils.py (3)

38-45: Prefer Response.json() with tighter exception handling

Slightly simpler and avoids an intermediate string parse.

 def execute_get_command(url: str, headers: dict[str, str], verify: bool | str = False) -> dict[Any, Any]:
     resp = _execute_get_call(url=url, headers=headers, verify=verify)
-    try:
-        return json.loads(resp.text)
-    except json.JSONDecodeError:
+    try:
+        return resp.json()
+    except (ValueError, json.JSONDecodeError):
         LOGGER.error(f"Unable to parse {resp.text}")
         raise

95-109: YAML builder: avoid shadowing built-in and trailing whitespace

Minor cleanup: don’t shadow id(), and drop the trailing spaces-only line.

-def get_catalog_str(ids: list[str]) -> str:
-    catalog_str: str = ""
-    for id in ids:
-        catalog_str += f"""
+def get_catalog_str(ids: list[str]) -> str:
+    catalog_str: str = ""
+    for catalog_id in ids:
+        catalog_str += f"""
 - name: Sample Catalog
-  id: {id}
+  id: {catalog_id}
   type: yaml
   enabled: true
   properties:
-    yamlCatalogPath: {id.replace("_", "-")}.yaml
+    yamlCatalogPath: {catalog_id.replace("_", "-")}.yaml
 """
-    return f"""catalogs:
-{catalog_str}
-    """
+    return f"""catalogs:
+{catalog_str}
+"""

123-136: Optional: make provider/license configurable

Hard-coding “Mistral AI” and license is fine for fixtures, but consider parameters if you need to add non-Mistral models later.

tests/model_registry/model_catalog/constants.py (1)

1-10: Centralize catalog-id → filename mapping to avoid drift

You derive filenames via id.replace('_','-') elsewhere while hardcoding here (e.g., “sample-custom-catalog1.yaml”). Export a helper (e.g., catalog_yaml_filename) to keep this consistent.

Example (in utils.py):

def catalog_yaml_filename(catalog_id: str) -> str:
    return f"{catalog_id.replace('_', '-')}.yaml"
tests/model_registry/model_catalog/conftest.py (2)

51-52: Simplify patch population

Use dict.update to copy all sample YAML entries.

-    if "sample_yaml" in request.param:
-        for key in request.param["sample_yaml"]:
-            patches["data"][key] = request.param["sample_yaml"][key]
+    if "sample_yaml" in request.param:
+        patches["data"].update(request.param["sample_yaml"])

66-66: Remove unused parameter per Ruff ARG001

request isn’t used in updated_catalog_config_map_add_model.

tests/model_registry/model_catalog/test_custom_model_catalog.py (4)

37-46: Give distinct parametrize ids and avoid hardcoded filenames

Unique ids improve test reports; prefer deriving filenames from catalog ids to prevent drift.

-            id="file_test_catalog",
+            id="single_source",
@@
-            id="file_test_catalog",
+            id="multi_source",

Optionally:

from tests.model_registry.model_catalog.utils import catalog_yaml_filename
...
"sample_yaml": {catalog_yaml_filename(CUSTOM_CATALOG_ID1): ...}

55-61: Fixture type annotation mismatch

updated_catalog_config_map yields a ConfigMap; drop the tuple[...] annotation (or omit typing) to avoid confusion.

-        updated_catalog_config_map: tuple[ConfigMap, str, str],
+        updated_catalog_config_map,

143-161: Remove unused arg; fix fixture typing

expected_catalog_values isn’t used; also the fixture type hint is inaccurate.

-    def test_model_custom_catalog_add_model(
+    def test_model_custom_catalog_add_model(
         self: Self,
         model_catalog_rest_url: list[str],
         model_registry_rest_headers: dict[str, str],
-        expected_catalog_values: dict[str, str],
-        updated_catalog_config_map_add_model: dict[str, str],
+        updated_catalog_config_map_add_model,
     ):

169-179: Docstring and exception semantics

Update docstring to “remove” to reflect behavior. With the utils change, this will now fail only on true 404, not any non-2xx.

-        Add a model to a source and ensure it is added to the catalog
+        Ensure previously added model is no longer present (after fixture cleanup)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9aa4fb4 and 3fa8c36.

📒 Files selected for processing (4)
  • tests/model_registry/model_catalog/conftest.py (3 hunks)
  • tests/model_registry/model_catalog/constants.py (1 hunks)
  • tests/model_registry/model_catalog/test_custom_model_catalog.py (6 hunks)
  • tests/model_registry/model_catalog/utils.py (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-21T19:08:14.982Z
Learnt from: dbasunag
PR: opendatahub-io/opendatahub-tests#527
File: tests/model_registry/rbac/conftest.py:358-359
Timestamp: 2025-08-21T19:08:14.982Z
Learning: In tests/model_registry/rbac/conftest.py, the model catalog configmap only exists in one specific namespace (py_config["model_registry_namespace"]) regardless of where model registry instances are deployed, making it a shared resource that serves all model registry instances across namespaces.

Applied to files:

  • tests/model_registry/model_catalog/conftest.py
  • tests/model_registry/model_catalog/test_custom_model_catalog.py
📚 Learning: 2025-08-08T15:58:03.524Z
Learnt from: lugi0
PR: opendatahub-io/opendatahub-tests#487
File: tests/model_registry/async_job/constants.py:23-31
Timestamp: 2025-08-08T15:58:03.524Z
Learning: In opendatahub-io/opendatahub-tests, for tests under tests/model_registry/async_job (e.g., constants.py and related fixtures), runs start from a clean, known Model Registry state. Therefore, using static MODEL_ID, MODEL_VERSION_ID, and MODEL_ARTIFACT_ID values in MODEL_SYNC_CONFIG is intentional and acceptable; dynamic ID injection is not required for these async job tests (per guidance from user lugi0).

Applied to files:

  • tests/model_registry/model_catalog/conftest.py
📚 Learning: 2025-07-17T15:42:23.880Z
Learnt from: lugi0
PR: opendatahub-io/opendatahub-tests#446
File: tests/model_registry/conftest.py:733-770
Timestamp: 2025-07-17T15:42:23.880Z
Learning: In tests/model_registry/conftest.py, the model_registry_instance_1 and model_registry_instance_2 fixtures do not need explicit database dependency fixtures (like db_deployment_1, db_secret_1, etc.) in their function signatures. Pytest's dependency injection automatically handles the fixture dependencies when they reference db_name_1 and db_name_2 parameters. This is the correct pattern for these Model Registry instance fixtures.

Applied to files:

  • tests/model_registry/model_catalog/conftest.py
📚 Learning: 2025-07-17T15:42:26.275Z
Learnt from: lugi0
PR: opendatahub-io/opendatahub-tests#446
File: tests/model_registry/conftest.py:0-0
Timestamp: 2025-07-17T15:42:26.275Z
Learning: In tests/model_registry/conftest.py, the model_registry_instance_1 fixture (and similar duplicated Model Registry instance fixtures) do not require admin_client, db_deployment_1, or db_secret_1 parameters as explicit dependencies, even though these dependencies exist implicitly through the fixture dependency chain.

Applied to files:

  • tests/model_registry/model_catalog/conftest.py
🧬 Code graph analysis (2)
tests/model_registry/model_catalog/conftest.py (3)
tests/model_registry/model_catalog/utils.py (3)
  • is_model_catalog_ready (55-65)
  • wait_for_model_catalog_api (34-35)
  • get_model_str (123-136)
tests/model_registry/conftest.py (2)
  • model_registry_namespace (62-63)
  • model_registry_rest_headers (290-295)
tests/conftest.py (1)
  • admin_client (68-69)
tests/model_registry/model_catalog/test_custom_model_catalog.py (3)
tests/model_registry/model_catalog/utils.py (4)
  • execute_get_command (38-44)
  • get_catalog_str (95-108)
  • get_sample_yaml_str (111-120)
  • ResourceNotFoundError (22-23)
tests/model_registry/model_catalog/conftest.py (3)
  • model_catalog_rest_url (28-37)
  • expected_catalog_values (62-63)
  • updated_catalog_config_map_add_model (67-81)
tests/model_registry/conftest.py (1)
  • model_registry_rest_headers (290-295)
🪛 Ruff (0.12.2)
tests/model_registry/model_catalog/conftest.py

68-68: Unused function argument: request

(ARG001)

tests/model_registry/model_catalog/test_custom_model_catalog.py

72-72: Use of assert detected

(S101)


75-75: Use of assert detected

(S101)


95-95: Use of assert detected

(S101)


116-116: Use of assert detected

(S101)


140-140: Use of assert detected

(S101)


141-141: Use of assert detected

(S101)


148-148: Unused method argument: expected_catalog_values

(ARG002)


149-149: Unused method argument: updated_catalog_config_map_add_model

(ARG002)


160-160: Use of assert detected

(S101)


167-167: Unused method argument: expected_catalog_values

(ARG002)

🔇 Additional comments (9)
tests/model_registry/model_catalog/utils.py (1)

111-121: LGTM: simple model list YAML generation

The structure aligns with get_model_str output and current test needs.

tests/model_registry/model_catalog/constants.py (1)

15-15: LGTM: added SAMPLE_MODEL_NAME3

Expands coverage for add/remove flow.

tests/model_registry/model_catalog/conftest.py (1)

11-13: LGTM: imports for multi-source and YAML snippet generation

Imports are consistent with new helpers.

tests/model_registry/model_catalog/test_custom_model_catalog.py (6)

3-9: LGTM: expanded constants for multi-source scenarios

Imports align with new constants.


15-20: LGTM: utils usage

Switch to local helpers keeps tests cohesive.


65-76: LGTM: sources list assertions

Covers count and ids, good signal.


87-96: LGTM: per-source model listing

Simple and effective presence check.


107-116: LGTM: get-by-name validation

Direct name equality is sufficient here.


128-142: LGTM: artifact presence check

Asserts existence and non-empty uri.

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: 5

♻️ Duplicate comments (1)
tests/model_registry/model_catalog/conftest.py (1)

66-81: Limit patch scope; remove unused arg; assert file exists (same as prior feedback)

Reiterating earlier feedback: patching the full to_dict risks clobbering metadata; request is unused; and you should assert the YAML key exists before appending.

 @pytest.fixture(scope="function")
-def update_configmap_data_add_model(
-    request: pytest.FixtureRequest,
+def update_configmap_data_add_model(
     catalog_config_map: ConfigMap,
     model_registry_namespace: str,
     admin_client: DynamicClient,
     model_catalog_rest_url: list[str],
     model_registry_rest_headers: dict[str, str],
 ) -> Generator[ConfigMap, None, None]:
-    patches = catalog_config_map.instance.to_dict()
-    patches["data"][f"{CUSTOM_CATALOG_ID1.replace('_', '-')}.yaml"] += get_model_str(model=SAMPLE_MODEL_NAME3)
-    with ResourceEditor(patches={catalog_config_map: patches}):
+    file_name = f"{CUSTOM_CATALOG_ID1.replace('_', '-')}.yaml"
+    base_yaml = catalog_config_map.instance.data.get(file_name)
+    assert base_yaml is not None, f"Catalog YAML {file_name} not found in ConfigMap"
+    new_yaml = f"{base_yaml}{get_model_str(model=SAMPLE_MODEL_NAME3)}"
+    with ResourceEditor(patches={catalog_config_map: {"data": {file_name: new_yaml}}}):
         is_model_catalog_ready(client=admin_client, model_registry_namespace=model_registry_namespace)
         wait_for_model_catalog_api(url=model_catalog_rest_url[0], headers=model_registry_rest_headers)
         yield catalog_config_map
     is_model_catalog_ready(client=admin_client, model_registry_namespace=model_registry_namespace)
🧹 Nitpick comments (6)
tests/model_registry/model_catalog/utils.py (2)

97-105: Avoid shadowing built-in name 'id'

Use catalog_id to avoid shadowing the built-in id().

-    for id in ids:
+    for catalog_id in ids:
-        catalog_str += f"""
- - name: Sample Catalog
-  id: {id}
+        catalog_str += f"""
+ - name: Sample Catalog
+  id: {catalog_id}
-    yamlCatalogPath: {id.replace("_", "-")}.yaml
+    yamlCatalogPath: {catalog_id.replace("_", "-")}.yaml

95-136: Prefer generating YAML via a dumper over string concatenation

To prevent indentation/format drift, consider using PyYAML (or ruamel.yaml) to build these structures.

import yaml

def get_catalog_str(ids: list[str]) -> str:
    data = {"catalogs": [
        {
            "name": "Sample Catalog",
            "id": cid,
            "type": "yaml",
            "enabled": True,
            "properties": {"yamlCatalogPath": cid.replace("_","-") + ".yaml"},
        } for cid in ids
    ]}
    return yaml.safe_dump(data, sort_keys=False)

def get_sample_yaml_str(models: list[str]) -> str:
    data = {
        "source": "Hugging Face",
        "models": [get_model_dict(m) for m in models],
    }
    return yaml.safe_dump(data, sort_keys=False)

def get_model_dict(model: str) -> dict:
    return {
        "name": model,
        "description": "test description.",
        "readme": f"# test read me information {model}",
        "provider": "Mistral AI",
        "logo": "temp placeholder logo",
        "license": "apache-2.0",
        "licenseLink": "https://www.apache.org/licenses/LICENSE-2.0.txt",
        "libraryName": "transformers",
        "artifacts": [{"uri": f"https://huggingface.co/{model}/resolve/main/consolidated.safetensors"}],
    }
tests/model_registry/model_catalog/test_custom_model_catalog.py (4)

36-47: Give each parametrize case a unique id

Two cases both use id="file_test_catalog". Use distinct ids for clarity in reports.

-            id="file_test_catalog",
+            id="file_test_catalog_single",
@@
-            id="file_test_catalog",
+            id="file_test_catalog_multi",

143-161: Silence unused params and encode model in add flow

Rename unused fixture param to underscore to satisfy linters, and encode SAMPLE_MODEL_NAME3 in the URL.

-    def test_model_custom_catalog_add_model(
+    def test_model_custom_catalog_add_model(
         self: Self,
         model_catalog_rest_url: list[str],
         model_registry_rest_headers: dict[str, str],
-        expected_catalog_values: dict[str, str],
-        update_configmap_data_add_model: dict[str, str],
+        _expected_catalog_values: list[dict[str, str]],
+        _update_configmap_data_add_model: dict[str, str],
     ):
@@
-        url = f"{model_catalog_rest_url[0]}sources/{CUSTOM_CATALOG_ID1}/models/{SAMPLE_MODEL_NAME3}"
+        from urllib.parse import quote
+        url = f"{model_catalog_rest_url[0]}sources/{CUSTOM_CATALOG_ID1}/models/{quote(SAMPLE_MODEL_NAME3, safe='')}"

162-179: Fix docstring; silence unused param; encode model; keep negative assertion

Adjust docstring, rename unused param to underscore, and encode the model name.

-    def test_model_custom_catalog_remove_model(
+    def test_model_custom_catalog_remove_model(
         self: Self,
         model_catalog_rest_url: list[str],
         model_registry_rest_headers: dict[str, str],
-        expected_catalog_values: dict[str, str],
+        _expected_catalog_values: list[dict[str, str]],
     ):
-        """
-        Add a model to a source and ensure it is added to the catalog
-        """
-        url = f"{model_catalog_rest_url[0]}sources/{CUSTOM_CATALOG_ID1}/models/{SAMPLE_MODEL_NAME3}"
+        """
+        Ensure the previously added model is no longer present after fixture teardown.
+        """
+        from urllib.parse import quote
+        url = f"{model_catalog_rest_url[0]}sources/{CUSTOM_CATALOG_ID1}/models/{quote(SAMPLE_MODEL_NAME3, safe='')}"

60-61: Type hints for expected_catalog_values should be a sequence of mappings

These tests treat expected_catalog_values as an iterable of dict entries. Update hints accordingly.

-        expected_catalog_values: dict[str, str],
+        expected_catalog_values: list[dict[str, str]],

Also applies to: 82-83, 102-103, 123-124, 148-149, 167-168

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3fa8c36 and eaf686e.

📒 Files selected for processing (4)
  • tests/model_registry/model_catalog/conftest.py (3 hunks)
  • tests/model_registry/model_catalog/constants.py (1 hunks)
  • tests/model_registry/model_catalog/test_custom_model_catalog.py (6 hunks)
  • tests/model_registry/model_catalog/utils.py (2 hunks)
🧰 Additional context used
🧠 Learnings (4)
📚 Learning: 2025-08-21T19:08:14.982Z
Learnt from: dbasunag
PR: opendatahub-io/opendatahub-tests#527
File: tests/model_registry/rbac/conftest.py:358-359
Timestamp: 2025-08-21T19:08:14.982Z
Learning: In tests/model_registry/rbac/conftest.py, the model catalog configmap only exists in one specific namespace (py_config["model_registry_namespace"]) regardless of where model registry instances are deployed, making it a shared resource that serves all model registry instances across namespaces.

Applied to files:

  • tests/model_registry/model_catalog/conftest.py
  • tests/model_registry/model_catalog/test_custom_model_catalog.py
📚 Learning: 2025-08-08T15:58:03.524Z
Learnt from: lugi0
PR: opendatahub-io/opendatahub-tests#487
File: tests/model_registry/async_job/constants.py:23-31
Timestamp: 2025-08-08T15:58:03.524Z
Learning: In opendatahub-io/opendatahub-tests, for tests under tests/model_registry/async_job (e.g., constants.py and related fixtures), runs start from a clean, known Model Registry state. Therefore, using static MODEL_ID, MODEL_VERSION_ID, and MODEL_ARTIFACT_ID values in MODEL_SYNC_CONFIG is intentional and acceptable; dynamic ID injection is not required for these async job tests (per guidance from user lugi0).

Applied to files:

  • tests/model_registry/model_catalog/conftest.py
📚 Learning: 2025-08-11T12:14:34.102Z
Learnt from: dbasunag
PR: opendatahub-io/opendatahub-tests#504
File: tests/model_registry/upgrade/conftest.py:20-30
Timestamp: 2025-08-11T12:14:34.102Z
Learning: In tests/model_registry/upgrade/conftest.py, when using ResourceEditor to patch DataScienceCluster resources with a partial components dictionary like `{DscComponents.MODELREGISTRY: {"managementState": ...}}`, the patch is applied correctly without overwriting other components in spec.components. ResourceEditor performs the appropriate merge operation for this resource type.

Applied to files:

  • tests/model_registry/model_catalog/conftest.py
📚 Learning: 2025-07-17T15:42:26.275Z
Learnt from: lugi0
PR: opendatahub-io/opendatahub-tests#446
File: tests/model_registry/conftest.py:0-0
Timestamp: 2025-07-17T15:42:26.275Z
Learning: In tests/model_registry/conftest.py, the model_registry_instance_1 fixture (and similar duplicated Model Registry instance fixtures) do not require admin_client, db_deployment_1, or db_secret_1 parameters as explicit dependencies, even though these dependencies exist implicitly through the fixture dependency chain.

Applied to files:

  • tests/model_registry/model_catalog/conftest.py
🧬 Code graph analysis (1)
tests/model_registry/model_catalog/test_custom_model_catalog.py (2)
tests/model_registry/model_catalog/utils.py (4)
  • execute_get_command (38-44)
  • get_catalog_str (95-108)
  • get_sample_yaml_str (111-120)
  • ResourceNotFoundError (22-23)
tests/model_registry/conftest.py (1)
  • model_registry_rest_headers (290-295)
🪛 Ruff (0.12.2)
tests/model_registry/model_catalog/conftest.py

68-68: Unused function argument: request

(ARG001)

tests/model_registry/model_catalog/test_custom_model_catalog.py

148-148: Unused method argument: expected_catalog_values

(ARG002)


149-149: Unused method argument: update_configmap_data_add_model

(ARG002)


167-167: Unused method argument: expected_catalog_values

(ARG002)

🔇 Additional comments (7)
tests/model_registry/model_catalog/utils.py (2)

22-24: Localize and standardize the not-found exception

Defining a local ResourceNotFoundError here is fine and aligns callers. No issues.


33-36: Retry wrapper is appropriate for transient 404s

Wrapping the readiness check with retry on ResourceNotFoundError looks correct. No changes needed.

tests/model_registry/model_catalog/constants.py (2)

1-10: Multi-catalog constants look good

Naming is clear and supports the new tests.


15-15: Additional sample model constant is fine

SAMPLE_MODEL_NAME3 adds coverage for add/remove flows.

tests/model_registry/model_catalog/conftest.py (2)

11-13: Targeted imports are appropriate

Importing SAMPLE_MODEL_NAME3, CUSTOM_CATALOG_ID1, and get_model_str here is correct for the new flows.


51-52: Merging sample_yaml keys into the ConfigMap patch is fine

This keeps the patch narrow to data entries. Looks good.

tests/model_registry/model_catalog/test_custom_model_catalog.py (1)

55-76: Sources listing assertions look correct

Good coverage validating count and IDs.

assert result[0]["id"] == expected_catalog_values["id"]

def test_model_custom_catalog_models(
LOGGER.info(f"Results: for uri {url}: {results}")
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.

is this needed?

)["items"]
assert result, f"Expected custom models to be present. Actual: {result}"
for expected_entry in expected_catalog_values:
LOGGER.info(f"Expected entry: {expected_entry}")
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.

same

url=url,
headers=model_registry_rest_headers,
)["items"]
LOGGER.info(f"URL: {url} Result: {result}")
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.

same

@dbasunag dbasunag merged commit 3bb31da into opendatahub-io:main Sep 9, 2025
15 checks passed
@dbasunag dbasunag deleted the multiple_sources branch September 9, 2025 15:17
@github-actions
Copy link
Copy Markdown

github-actions bot commented Sep 9, 2025

Status of building tag latest: success.
Status of pushing tag latest to image registry: success.

mwaykole pushed a commit to mwaykole/opendatahub-tests that referenced this pull request Jan 23, 2026
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.

4 participants