diff --git a/src/mas/devops/data/__init__.py b/src/mas/devops/data/__init__.py index 3101b32c..750ad4a3 100644 --- a/src/mas/devops/data/__init__.py +++ b/src/mas/devops/data/__init__.py @@ -29,16 +29,18 @@ def getCatalog(name: str) -> dict: Load a specific IBM Operator Catalog definition by name. This function reads a catalog YAML file from the catalogs directory and returns - its contents as a dictionary. + its contents as a dictionary. Dev/master catalogs that don't exist will automatically + resolve to the newest catalog for that architecture. Args: - name (str): The catalog name/tag (e.g., "v9-241205-amd64", "v8-240528-amd64"). + name (str): The catalog name/tag (e.g., "v9-241205-amd64", "v8-240528-amd64", "v9-master-amd64"). Returns: dict: The catalog definition dictionary containing operator versions and metadata. + For dev catalogs, returns the newest catalog data for that architecture. Raises: - NoSuchCatalogError: If the specified catalog does not exist. + NoSuchCatalogError: If the specified catalog does not exist and is not a dev catalog pattern. """ moduleFile = path.abspath(__file__) modulePath = path.dirname(moduleFile) @@ -46,9 +48,31 @@ def getCatalog(name: str) -> dict: pathToCatalog = path.join(modulePath, "catalogs", catalogFileName) if not path.exists(pathToCatalog): - raise NoSuchCatalogError( - f"Catalog {name} is unknown: {pathToCatalog} does not exist" - ) + # Check if this looks like a dev catalog (master or branch name pattern) + parts = name.split("-") + if len(parts) >= 3: + middle_part = parts[1] # e.g., "master", "branchname", or "241205" + arch = parts[-1] # e.g., "amd64" + + # Validate catalog format + is_dev_catalog = not (middle_part.isdigit() and len(middle_part) == 6) + + if is_dev_catalog: + # This is a dev catalog, resolve to newest catalog for this architecture + try: + newestCatalog = getNewestCatalogTag(arch) + catalogFileName = f"{newestCatalog}.yaml" + pathToCatalog = path.join(modulePath, "catalogs", catalogFileName) + except NoSuchCatalogError: + raise NoSuchCatalogError( + f"Catalog {name} appears to be a dev catalog, but no catalogs found for architecture {arch}" + ) + + # Final check if the resolved path exists + if not path.exists(pathToCatalog): + raise NoSuchCatalogError( + f"Catalog {name} is unknown: {pathToCatalog} does not exist" + ) with open(pathToCatalog) as stream: return yaml.safe_load(stream) @@ -180,9 +204,7 @@ def getCatalogEditorial(catalogTag: str) -> dict | None: Returns: dict: Dictionary with 'whats_new' and 'known_issues' keys containing - structured lists. Returns None if catalog doesn't exist - or has no editorial content. + structured lists. Returns None if catalog has no editorial content. """ catalog = getCatalog(catalogTag) - return catalog.get("editorial") diff --git a/test/src/test_data.py b/test/src/test_data.py index cbf0f152..7ce42ab9 100644 --- a/test/src/test_data.py +++ b/test/src/test_data.py @@ -43,3 +43,27 @@ def test_get_newest_catalog_tag_fail(): def test_get_catalog_fail(): with pytest.raises(NoSuchCatalogError, match="Catalog nonexistent-catalog is unknown"): getCatalog("nonexistent-catalog") + + +def test_get_dev_catalog_master(): + """Test that master dev catalogs automatically resolve to newest catalog""" + catalogData = getCatalog("v9-master-amd64") + # Should resolve to newest catalog + newestCatalog = getCatalog(getNewestCatalogTag("amd64")) + assert catalogData == newestCatalog + + +def test_get_dev_catalog_branch(): + """Test that branch dev catalogs automatically resolve to newest catalog""" + catalogData = getCatalog("v9-feature-branch-amd64") + # Should resolve to newest catalog + newestCatalog = getCatalog(getNewestCatalogTag("amd64")) + assert catalogData == newestCatalog + + +def test_get_dev_catalog_s390x(): + """Test that dev catalogs work for different architectures""" + catalogData = getCatalog("v9-master-s390x") + # Should resolve to newest s390x catalog + newestCatalog = getCatalog(getNewestCatalogTag("s390x")) + assert catalogData == newestCatalog