From 399bff9b01c3e3434426424e4924b82dbb99e80a Mon Sep 17 00:00:00 2001 From: Pete Crocker Date: Thu, 27 Nov 2025 17:59:50 +0000 Subject: [PATCH 1/7] fix https://github.com/opsmill/infrahub/issues/6124 --- backend/infrahub/exceptions.py | 17 ++ backend/infrahub/git/integrator.py | 92 +++++--- .../unit/git/test_git_read_only_repository.py | 6 +- backend/tests/unit/git/test_git_repository.py | 21 +- .../tests/unit/git/test_repository_config.py | 199 ++++++++++++++++++ 5 files changed, 296 insertions(+), 39 deletions(-) create mode 100644 backend/tests/unit/git/test_repository_config.py diff --git a/backend/infrahub/exceptions.py b/backend/infrahub/exceptions.py index 965a091f7e..a84d635790 100644 --- a/backend/infrahub/exceptions.py +++ b/backend/infrahub/exceptions.py @@ -116,6 +116,23 @@ def __init__( self.directory = directory +class RepositoryConfigurationError(RepositoryError): + """Raised when repository configuration file is missing or invalid. + + This exception provides clear error messages when a Git repository + lacks a .infrahub.yml/.infrahub.yaml file or when the file cannot + be parsed correctly. + """ + + def __init__(self, identifier: str, message: str | None = None) -> None: + super().__init__( + identifier=identifier, + message=message + or f"Repository '{identifier}' is missing a configuration file. " + f"Please add a '.infrahub.yml' or '.infrahub.yaml' file to the repository root.", + ) + + class CommitNotFoundError(Error): HTTP_CODE: int = 400 diff --git a/backend/infrahub/git/integrator.py b/backend/infrahub/git/integrator.py index 2f9ee5333c..f7fc956439 100644 --- a/backend/infrahub/git/integrator.py +++ b/backend/infrahub/git/integrator.py @@ -47,7 +47,12 @@ from infrahub.events.artifact_action import ArtifactCreatedEvent, ArtifactUpdatedEvent from infrahub.events.models import EventMeta from infrahub.events.repository_action import CommitUpdatedEvent -from infrahub.exceptions import CheckError, RepositoryInvalidFileSystemError, TransformError +from infrahub.exceptions import ( + CheckError, + RepositoryConfigurationError, + RepositoryInvalidFileSystemError, + TransformError, +) from infrahub.git.base import InfrahubRepositoryBase, extract_repo_file_information from infrahub.log import get_logger from infrahub.workers.dependencies import get_event_service @@ -180,31 +185,29 @@ async def import_objects_from_files( self.create_commit_worktree(commit) await self._update_sync_status(branch_name=infrahub_branch_name, status=RepositorySyncStatus.SYNCING) - config_file = await self.get_repository_config(branch_name=infrahub_branch_name, commit=commit) # type: ignore[misc] - sync_status = RepositorySyncStatus.IN_SYNC if config_file else RepositorySyncStatus.ERROR_IMPORT - + sync_status = RepositorySyncStatus.IN_SYNC error: Exception | None = None try: - if config_file: - await self.import_schema_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) # type: ignore[misc] - await self.import_all_graphql_query( - branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] - await self.import_objects( - branch_name=infrahub_branch_name, - commit=commit, - config_file=config_file, - ) # type: ignore[misc] - await self.import_all_python_files( # type: ignore[call-overload] - branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] - await self.import_jinja2_transforms( - branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] - await self.import_artifact_definitions( - branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] + config_file = await self.get_repository_config(branch_name=infrahub_branch_name, commit=commit) # type: ignore[misc] + await self.import_schema_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) # type: ignore[misc] + await self.import_all_graphql_query( + branch_name=infrahub_branch_name, commit=commit, config_file=config_file + ) # type: ignore[misc] + await self.import_objects( + branch_name=infrahub_branch_name, + commit=commit, + config_file=config_file, + ) # type: ignore[misc] + await self.import_all_python_files( # type: ignore[call-overload] + branch_name=infrahub_branch_name, commit=commit, config_file=config_file + ) # type: ignore[misc] + await self.import_jinja2_transforms( + branch_name=infrahub_branch_name, commit=commit, config_file=config_file + ) # type: ignore[misc] + await self.import_artifact_definitions( + branch_name=infrahub_branch_name, commit=commit, config_file=config_file + ) # type: ignore[misc] except Exception as exc: sync_status = RepositorySyncStatus.ERROR_IMPORT @@ -433,7 +436,20 @@ async def update_artifact_definition( await existing_artifact_definition.save() @task(name="repository-get-config", task_run_name="get repository config", cache_policy=NONE) - async def get_repository_config(self, branch_name: str, commit: str) -> InfrahubRepositoryConfig | None: + async def get_repository_config(self, branch_name: str, commit: str) -> InfrahubRepositoryConfig: + """Load and parse the repository configuration file. + + Args: + branch_name: The name of the branch to load the config from. + commit: The commit hash to load the config from. + + Returns: + The parsed repository configuration. + + Raises: + RepositoryConfigurationError: If the configuration file is missing, + cannot be parsed as YAML, or has an invalid format. + """ branch_wt = self.get_worktree(identifier=commit or branch_name) log = get_run_logger() @@ -448,15 +464,27 @@ async def get_repository_config(self, branch_name: str, commit: str) -> Infrahub config_file = config_file_yaml config_file_name = ".infrahub.yaml" else: - log.debug("Unable to find the configuration file (.infrahub.yml or .infrahub.yaml), skipping") - return None + log.error( + f"Repository '{self.name}' is missing a configuration file. " + "Expected '.infrahub.yml' or '.infrahub.yaml' in the repository root." + ) + raise RepositoryConfigurationError( + identifier=self.name, + message=f"Repository '{self.name}' is missing a configuration file. " + f"Please add a '.infrahub.yml' or '.infrahub.yaml' file to the repository root. " + f"See https://docs.infrahub.app/topics/repository for more information.", + ) config_file_content = config_file.read_text(encoding="utf-8") try: data = yaml.safe_load(config_file_content) except yaml.YAMLError as exc: - log.error(f"Unable to load the configuration file in YAML format {config_file_name} : {exc}") - return None + log.error(f"Unable to load the configuration file in YAML format {config_file_name}: {exc}") + raise RepositoryConfigurationError( + identifier=self.name, + message=f"Repository '{self.name}' has an invalid configuration file '{config_file_name}'. " + f"The file could not be parsed as valid YAML: {exc}", + ) from exc # Convert data to a dictionary to avoid it being `None` if the yaml file is just an empty document data = data or {} @@ -466,8 +494,12 @@ async def get_repository_config(self, branch_name: str, commit: str) -> Infrahub log.info(f"Successfully parsed {config_file_name}") return configuration except PydanticValidationError as exc: - log.error(f"Unable to load the configuration file {config_file_name}, the format is not valid : {exc}") - return None + log.error(f"Unable to load the configuration file {config_file_name}, the format is not valid: {exc}") + raise RepositoryConfigurationError( + identifier=self.name, + message=f"Repository '{self.name}' has an invalid configuration file '{config_file_name}'. " + f"The file format is not valid: {exc}", + ) from exc @task(name="import-schema-files", task_run_name="Import schema files", cache_policy=NONE) async def import_schema_files(self, branch_name: str, commit: str, config_file: InfrahubRepositoryConfig) -> None: diff --git a/backend/tests/unit/git/test_git_read_only_repository.py b/backend/tests/unit/git/test_git_read_only_repository.py index ba4cfaf2fd..d5718e3303 100644 --- a/backend/tests/unit/git/test_git_read_only_repository.py +++ b/backend/tests/unit/git/test_git_read_only_repository.py @@ -76,7 +76,11 @@ async def test_sync_from_remote_new_ref(git_repo_01_read_only: InfrahubReadOnlyR mock_client = AsyncMock(InfrahubClient) repo.client = mock_client - await repo.sync_from_remote() + # Mock import_objects_from_files since we're testing git sync, not import functionality + with patch( + "infrahub.git.repository.InfrahubReadOnlyRepository.import_objects_from_files", new_callable=AsyncMock + ): + await repo.sync_from_remote() worktree_commits = {wt.identifier for wt in repo.get_worktrees()} assert worktree_commits == {"main", "92700512b5b16c0144f7fd2869669273577f1bd8", branch_02_head_commit} diff --git a/backend/tests/unit/git/test_git_repository.py b/backend/tests/unit/git/test_git_repository.py index ea3f627dc7..d844897959 100644 --- a/backend/tests/unit/git/test_git_repository.py +++ b/backend/tests/unit/git/test_git_repository.py @@ -1,5 +1,5 @@ from pathlib import Path -from unittest.mock import MagicMock, patch +from unittest.mock import AsyncMock, MagicMock, patch from uuid import uuid4 import anyio @@ -498,11 +498,8 @@ async def test_sync_new_branch( method="POST", json=commit_response, match_headers={"X-Infrahub-Tracker": "mutation-repository-update-commit"} ) admin_response = {"data": {"CoreGenericRepositoryUpdate": {"ok": True}}} - httpx_mock.add_response( - method="POST", - json=admin_response, - match_headers={"X-Infrahub-Tracker": "mutation-repository-update-admin-status"}, - ) + # Note: The admin-status endpoint is only called from within import_objects_from_files, + # which we're mocking below, so we don't need to mock it here. httpx_mock.add_response( method="POST", json=admin_response, @@ -510,7 +507,11 @@ async def test_sync_new_branch( ) repo.client = client - await repo.sync() + # Mock import_objects_from_files since we're testing git sync, not import functionality + with patch( + "infrahub.git.repository.InfrahubRepository.import_objects_from_files", new_callable=AsyncMock + ): + await repo.sync() worktrees = repo.get_worktrees() assert repo.get_commit_value(branch_name=branch.name) == "92700512b5b16c0144f7fd2869669273577f1bd8" @@ -526,7 +527,11 @@ async def test_sync_updated_branch(prefect_test_fixture, git_repo_04: InfrahubRe # Mock update_commit_value query commit = repo.get_commit_value(branch_name="branch01", remote=True) - await repo.sync() + # Mock import_objects_from_files since we're testing git sync, not import functionality + with patch( + "infrahub.git.repository.InfrahubRepository.import_objects_from_files", new_callable=AsyncMock + ): + await repo.sync() assert repo.get_commit_value(branch_name="branch01") == str(commit) diff --git a/backend/tests/unit/git/test_repository_config.py b/backend/tests/unit/git/test_repository_config.py new file mode 100644 index 0000000000..6d6563a971 --- /dev/null +++ b/backend/tests/unit/git/test_repository_config.py @@ -0,0 +1,199 @@ +"""Tests for repository configuration file loading and error handling.""" + +from __future__ import annotations + +from typing import TYPE_CHECKING + +import pytest +from infrahub_sdk import Config, InfrahubClient +from infrahub_sdk.uuidt import UUIDT + +from infrahub.exceptions import RepositoryConfigurationError +from infrahub.git import InfrahubRepository +from tests.helpers.test_client import dummy_async_request + +if TYPE_CHECKING: + from pathlib import Path + + +class TestGetRepositoryConfig: + """Tests for the get_repository_config method.""" + + @pytest.fixture + async def repo_without_config( + self, git_upstream_repo_01: dict[str, str | Path], git_repos_dir: Path + ) -> InfrahubRepository: + """Create a repository without a .infrahub.yml config file. + + The test fixture repository doesn't have a config file by default. + """ + repo = await InfrahubRepository.new( + id=UUIDT.new(), + name=git_upstream_repo_01["name"], + location=str(git_upstream_repo_01["path"]), + client=InfrahubClient(config=Config(requester=dummy_async_request)), + ) + return repo + + @pytest.fixture + async def repo_with_invalid_yaml( + self, git_upstream_repo_01: dict[str, str | Path], git_repos_dir: Path + ) -> InfrahubRepository: + """Create a repository with an invalid YAML config file.""" + from git import Repo as GitRepo + + upstream_repo = GitRepo(git_upstream_repo_01["path"]) + config_file = git_upstream_repo_01["path"] / ".infrahub.yml" + + # Write invalid YAML content + invalid_yaml = """ +schemas: + - path: invalid + this is: [not valid yaml + missing: closing bracket +""" + config_file.write_text(invalid_yaml, encoding="utf-8") + upstream_repo.index.add([".infrahub.yml"]) + upstream_repo.index.commit("Add invalid YAML config file") + + repo = await InfrahubRepository.new( + id=UUIDT.new(), + name=git_upstream_repo_01["name"], + location=str(git_upstream_repo_01["path"]), + client=InfrahubClient(config=Config(requester=dummy_async_request)), + ) + return repo + + @pytest.fixture + async def repo_with_invalid_format( + self, git_upstream_repo_01: dict[str, str | Path], git_repos_dir: Path + ) -> InfrahubRepository: + """Create a repository with a YAML config file that has invalid format.""" + from git import Repo as GitRepo + + upstream_repo = GitRepo(git_upstream_repo_01["path"]) + config_file = git_upstream_repo_01["path"] / ".infrahub.yml" + + # Write valid YAML but invalid InfrahubRepositoryConfig format + invalid_format = """ +invalid_key: "this key doesn't exist in the schema" +schemas: "should be a list, not a string" +""" + config_file.write_text(invalid_format, encoding="utf-8") + upstream_repo.index.add([".infrahub.yml"]) + upstream_repo.index.commit("Add invalid format config file") + + repo = await InfrahubRepository.new( + id=UUIDT.new(), + name=git_upstream_repo_01["name"], + location=str(git_upstream_repo_01["path"]), + client=InfrahubClient(config=Config(requester=dummy_async_request)), + ) + return repo + + async def test_missing_config_file_raises_error( + self, repo_without_config: InfrahubRepository, prefect_test_fixture + ) -> None: + """Test that a missing config file raises RepositoryConfigurationError.""" + commit = repo_without_config.get_commit_value(branch_name="main") + repo_without_config.create_commit_worktree(commit) + + with pytest.raises(RepositoryConfigurationError) as exc_info: + await repo_without_config.get_repository_config(branch_name="main", commit=commit) + + assert repo_without_config.name in str(exc_info.value) + assert "missing a configuration file" in str(exc_info.value) + assert ".infrahub.yml" in str(exc_info.value) or ".infrahub.yaml" in str(exc_info.value) + + async def test_invalid_yaml_raises_error( + self, repo_with_invalid_yaml: InfrahubRepository, prefect_test_fixture + ) -> None: + """Test that an invalid YAML config file raises RepositoryConfigurationError.""" + commit = repo_with_invalid_yaml.get_commit_value(branch_name="main") + repo_with_invalid_yaml.create_commit_worktree(commit) + + with pytest.raises(RepositoryConfigurationError) as exc_info: + await repo_with_invalid_yaml.get_repository_config(branch_name="main", commit=commit) + + assert repo_with_invalid_yaml.name in str(exc_info.value) + assert "could not be parsed as valid YAML" in str(exc_info.value) + + async def test_invalid_format_raises_error( + self, repo_with_invalid_format: InfrahubRepository, prefect_test_fixture + ) -> None: + """Test that a config file with invalid format raises RepositoryConfigurationError.""" + commit = repo_with_invalid_format.get_commit_value(branch_name="main") + repo_with_invalid_format.create_commit_worktree(commit) + + with pytest.raises(RepositoryConfigurationError) as exc_info: + await repo_with_invalid_format.get_repository_config(branch_name="main", commit=commit) + + assert repo_with_invalid_format.name in str(exc_info.value) + assert "format is not valid" in str(exc_info.value) + + @pytest.fixture + async def repo_with_valid_config( + self, git_upstream_repo_01: dict[str, str | Path], git_repos_dir: Path + ) -> InfrahubRepository: + """Create a repository with a valid .infrahub.yml config file.""" + from git import Repo as GitRepo + + upstream_repo = GitRepo(git_upstream_repo_01["path"]) + config_file = git_upstream_repo_01["path"] / ".infrahub.yml" + + # Write a valid minimal config file + valid_config = """ +# Infrahub Repository Configuration +schemas: [] +""" + config_file.write_text(valid_config, encoding="utf-8") + upstream_repo.index.add([".infrahub.yml"]) + upstream_repo.index.commit("Add valid .infrahub.yml config file") + + repo = await InfrahubRepository.new( + id=UUIDT.new(), + name=git_upstream_repo_01["name"], + location=str(git_upstream_repo_01["path"]), + client=InfrahubClient(config=Config(requester=dummy_async_request)), + ) + return repo + + async def test_valid_config_file_returns_config( + self, repo_with_valid_config: InfrahubRepository, prefect_test_fixture + ) -> None: + """Test that a valid config file is successfully loaded.""" + commit = repo_with_valid_config.get_commit_value(branch_name="main") + repo_with_valid_config.create_commit_worktree(commit) + + config = await repo_with_valid_config.get_repository_config(branch_name="main", commit=commit) + + assert config is not None + + +class TestRepositoryConfigurationErrorException: + """Tests for the RepositoryConfigurationError exception class.""" + + def test_default_message(self) -> None: + """Test that the default message is correctly set.""" + error = RepositoryConfigurationError(identifier="test-repo") + + assert "test-repo" in str(error) + assert "missing a configuration file" in str(error) + assert ".infrahub.yml" in str(error) + + def test_custom_message(self) -> None: + """Test that a custom message is correctly set.""" + custom_message = "Custom error message for test-repo" + error = RepositoryConfigurationError(identifier="test-repo", message=custom_message) + + assert str(error) == custom_message + assert error.message == custom_message + assert error.identifier == "test-repo" + + def test_inherits_from_repository_error(self) -> None: + """Test that RepositoryConfigurationError inherits from RepositoryError.""" + from infrahub.exceptions import RepositoryError + + error = RepositoryConfigurationError(identifier="test-repo") + + assert isinstance(error, RepositoryError) From 65cb522935322ddadee8a7bd0de2c8dd7777bfdb Mon Sep 17 00:00:00 2001 From: Pete Crocker Date: Thu, 27 Nov 2025 18:06:00 +0000 Subject: [PATCH 2/7] Apply ruff formatting to test files --- backend/tests/unit/git/test_git_read_only_repository.py | 4 +--- backend/tests/unit/git/test_git_repository.py | 8 ++------ 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/backend/tests/unit/git/test_git_read_only_repository.py b/backend/tests/unit/git/test_git_read_only_repository.py index d5718e3303..3825ffbcd5 100644 --- a/backend/tests/unit/git/test_git_read_only_repository.py +++ b/backend/tests/unit/git/test_git_read_only_repository.py @@ -77,9 +77,7 @@ async def test_sync_from_remote_new_ref(git_repo_01_read_only: InfrahubReadOnlyR repo.client = mock_client # Mock import_objects_from_files since we're testing git sync, not import functionality - with patch( - "infrahub.git.repository.InfrahubReadOnlyRepository.import_objects_from_files", new_callable=AsyncMock - ): + with patch("infrahub.git.repository.InfrahubReadOnlyRepository.import_objects_from_files", new_callable=AsyncMock): await repo.sync_from_remote() worktree_commits = {wt.identifier for wt in repo.get_worktrees()} diff --git a/backend/tests/unit/git/test_git_repository.py b/backend/tests/unit/git/test_git_repository.py index d844897959..d876e583f9 100644 --- a/backend/tests/unit/git/test_git_repository.py +++ b/backend/tests/unit/git/test_git_repository.py @@ -508,9 +508,7 @@ async def test_sync_new_branch( repo.client = client # Mock import_objects_from_files since we're testing git sync, not import functionality - with patch( - "infrahub.git.repository.InfrahubRepository.import_objects_from_files", new_callable=AsyncMock - ): + with patch("infrahub.git.repository.InfrahubRepository.import_objects_from_files", new_callable=AsyncMock): await repo.sync() worktrees = repo.get_worktrees() @@ -528,9 +526,7 @@ async def test_sync_updated_branch(prefect_test_fixture, git_repo_04: InfrahubRe commit = repo.get_commit_value(branch_name="branch01", remote=True) # Mock import_objects_from_files since we're testing git sync, not import functionality - with patch( - "infrahub.git.repository.InfrahubRepository.import_objects_from_files", new_callable=AsyncMock - ): + with patch("infrahub.git.repository.InfrahubRepository.import_objects_from_files", new_callable=AsyncMock): await repo.sync() assert repo.get_commit_value(branch_name="branch01") == str(commit) From c5e2d07d15a1155dccdf826b8da25468cc7f5e73 Mon Sep 17 00:00:00 2001 From: Pete Crocker Date: Thu, 27 Nov 2025 18:13:27 +0000 Subject: [PATCH 3/7] Remove unnecessary type ignore comments from integrator.py Since get_repository_config() no longer returns None, the type ignore comments are no longer needed. --- backend/infrahub/git/integrator.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/backend/infrahub/git/integrator.py b/backend/infrahub/git/integrator.py index f7fc956439..f43cf26149 100644 --- a/backend/infrahub/git/integrator.py +++ b/backend/infrahub/git/integrator.py @@ -189,25 +189,25 @@ async def import_objects_from_files( error: Exception | None = None try: - config_file = await self.get_repository_config(branch_name=infrahub_branch_name, commit=commit) # type: ignore[misc] - await self.import_schema_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) # type: ignore[misc] + config_file = await self.get_repository_config(branch_name=infrahub_branch_name, commit=commit) + await self.import_schema_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) await self.import_all_graphql_query( branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] + ) await self.import_objects( branch_name=infrahub_branch_name, commit=commit, config_file=config_file, - ) # type: ignore[misc] - await self.import_all_python_files( # type: ignore[call-overload] + ) + await self.import_all_python_files( branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] + ) await self.import_jinja2_transforms( branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] + ) await self.import_artifact_definitions( branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] + ) except Exception as exc: sync_status = RepositorySyncStatus.ERROR_IMPORT From 233c01f5013c2e97502fe384b26ed301a6ea453e Mon Sep 17 00:00:00 2001 From: Pete Crocker Date: Thu, 27 Nov 2025 18:13:27 +0000 Subject: [PATCH 4/7] Remove unnecessary type ignore comments from integrator.py Since get_repository_config() no longer returns None, the type ignore comments are no longer needed. --- backend/infrahub/git/integrator.py | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/backend/infrahub/git/integrator.py b/backend/infrahub/git/integrator.py index f7fc956439..05cb4136b2 100644 --- a/backend/infrahub/git/integrator.py +++ b/backend/infrahub/git/integrator.py @@ -189,25 +189,23 @@ async def import_objects_from_files( error: Exception | None = None try: - config_file = await self.get_repository_config(branch_name=infrahub_branch_name, commit=commit) # type: ignore[misc] - await self.import_schema_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) # type: ignore[misc] + config_file = await self.get_repository_config(branch_name=infrahub_branch_name, commit=commit) + await self.import_schema_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) await self.import_all_graphql_query( branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] + ) await self.import_objects( branch_name=infrahub_branch_name, commit=commit, config_file=config_file, - ) # type: ignore[misc] - await self.import_all_python_files( # type: ignore[call-overload] - branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] + ) + await self.import_all_python_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) await self.import_jinja2_transforms( branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] + ) await self.import_artifact_definitions( branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) # type: ignore[misc] + ) except Exception as exc: sync_status = RepositorySyncStatus.ERROR_IMPORT From ca57fc66d358a997fa6ee8f185089202b0c1800c Mon Sep 17 00:00:00 2001 From: Pete Crocker Date: Thu, 27 Nov 2025 18:30:06 +0000 Subject: [PATCH 5/7] Apply ruff formatting to import_all_python_files call --- backend/infrahub/git/integrator.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/backend/infrahub/git/integrator.py b/backend/infrahub/git/integrator.py index f43cf26149..05cb4136b2 100644 --- a/backend/infrahub/git/integrator.py +++ b/backend/infrahub/git/integrator.py @@ -199,9 +199,7 @@ async def import_objects_from_files( commit=commit, config_file=config_file, ) - await self.import_all_python_files( - branch_name=infrahub_branch_name, commit=commit, config_file=config_file - ) + await self.import_all_python_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) await self.import_jinja2_transforms( branch_name=infrahub_branch_name, commit=commit, config_file=config_file ) From 24eaca2536db586cc54229ed5c8f28c863f0a260 Mon Sep 17 00:00:00 2001 From: Pete Crocker Date: Thu, 27 Nov 2025 20:06:47 +0000 Subject: [PATCH 6/7] Restore type ignore comments required by mypy for Prefect tasks The type ignore comments are needed because mypy doesn't understand Prefect's @task decorator return type correctly. --- backend/infrahub/git/integrator.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/backend/infrahub/git/integrator.py b/backend/infrahub/git/integrator.py index 05cb4136b2..af0639a1eb 100644 --- a/backend/infrahub/git/integrator.py +++ b/backend/infrahub/git/integrator.py @@ -189,21 +189,21 @@ async def import_objects_from_files( error: Exception | None = None try: - config_file = await self.get_repository_config(branch_name=infrahub_branch_name, commit=commit) - await self.import_schema_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) - await self.import_all_graphql_query( + config_file = await self.get_repository_config(branch_name=infrahub_branch_name, commit=commit) # type: ignore[misc] + await self.import_schema_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) # type: ignore[misc] + await self.import_all_graphql_query( # type: ignore[misc] branch_name=infrahub_branch_name, commit=commit, config_file=config_file ) - await self.import_objects( + await self.import_objects( # type: ignore[misc] branch_name=infrahub_branch_name, commit=commit, config_file=config_file, ) - await self.import_all_python_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) - await self.import_jinja2_transforms( + await self.import_all_python_files(branch_name=infrahub_branch_name, commit=commit, config_file=config_file) # type: ignore[misc, call-overload] + await self.import_jinja2_transforms( # type: ignore[misc] branch_name=infrahub_branch_name, commit=commit, config_file=config_file ) - await self.import_artifact_definitions( + await self.import_artifact_definitions( # type: ignore[misc] branch_name=infrahub_branch_name, commit=commit, config_file=config_file ) From 286bbd38e152a0df5d9e5c8f4dd194973429f863 Mon Sep 17 00:00:00 2001 From: Pete Crocker Date: Thu, 27 Nov 2025 21:20:27 +0000 Subject: [PATCH 7/7] Add .infrahub.yml config file to conflict-01 test fixture The conflict-01 test fixture was missing a .infrahub.yml configuration file. With the new RepositoryConfigurationError exception that is now raised when a repository lacks this config file, the integration tests using this fixture were failing. This adds a minimal .infrahub.yml to fix the integration tests: - test_run_pipeline_validate_requested_jobs - test_run_generators_validate_requested_jobs --- .../fixtures/repos/conflict-01/initial__main/.infrahub.yml | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 backend/tests/fixtures/repos/conflict-01/initial__main/.infrahub.yml diff --git a/backend/tests/fixtures/repos/conflict-01/initial__main/.infrahub.yml b/backend/tests/fixtures/repos/conflict-01/initial__main/.infrahub.yml new file mode 100644 index 0000000000..9e9b14c746 --- /dev/null +++ b/backend/tests/fixtures/repos/conflict-01/initial__main/.infrahub.yml @@ -0,0 +1,3 @@ +# yaml-language-server: $schema=https://schema.infrahub.app/python-sdk/repository-config/develop.json +--- +# Minimal configuration for test repository