Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
a7fd3ee
IFC-1983: Add config parameter for selective git sync
solababs Oct 27, 2025
bc48883
update docs
solababs Oct 27, 2025
ca0d234
update doc text
solababs Oct 27, 2025
30351e3
IFC-1984: Update git sync to consider new configuration
solababs Oct 27, 2025
41bfa41
add configuration check on creating a branch
solababs Oct 27, 2025
cd7db02
update branch creation validation condition
solababs Oct 27, 2025
88883ef
update validation condition
solababs Oct 28, 2025
5dd0ac1
move validation function outside model
solababs Oct 28, 2025
261196e
sync branch names compiles to regex, remove compiled branch names
solababs Oct 29, 2025
33f48bf
Merge branch 'sb-20251027-config-for-selective-git-sync-ifc-1983' int…
solababs Oct 29, 2025
28eaab7
remove compiled branch names
solababs Oct 29, 2025
080b64b
Merge branch 'develop' into sb-20251027-config-for-selective-git-sync…
solababs Oct 31, 2025
ec55022
Merge branch 'sb-20251027-config-for-selective-git-sync-ifc-1983' int…
solababs Oct 31, 2025
e2f4b5c
update git setting name
solababs Nov 4, 2025
6fb5a83
remove main in description
solababs Nov 4, 2025
c258da4
Merge branch 'sb-20251027-config-for-selective-git-sync-ifc-1983' int…
solababs Nov 4, 2025
adb8fa0
update git setting name
solababs Nov 4, 2025
bb37b94
Merge branch 'sb-20251027-update-git-sync-ifc-1984' of https://github…
solababs Nov 4, 2025
7a34854
refactor remote branches filter
solababs Nov 4, 2025
b6081da
Merge branch 'develop' into sb-20251027-update-git-sync-ifc-1984
solababs Nov 4, 2025
6a123f6
fix mypy
solababs Nov 4, 2025
d8e7e52
rename function
solababs Nov 4, 2025
80f60f6
use sdk instead of client
solababs Nov 4, 2025
fb7694b
Merge branch 'develop' into sb-20251027-update-git-sync-ifc-1984
solababs Nov 4, 2025
43d6bb0
update sdk
solababs Nov 4, 2025
0f4559d
refactor get_filtered_remote_branches
solababs Nov 5, 2025
003482c
Merge branch 'develop' into sb-20251027-update-git-sync-ifc-1984
solababs Nov 6, 2025
0f28898
add changelog
solababs Nov 6, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 43 additions & 1 deletion backend/infrahub/git/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,12 @@
from pydantic import BaseModel, ConfigDict, Field
from pydantic import ValidationError as PydanticValidationError

from infrahub import config
from infrahub.core.branch import Branch
from infrahub.core.constants import InfrahubKind, RepositoryOperationalStatus, RepositorySyncStatus
from infrahub.core.registry import registry
from infrahub.exceptions import (
BranchNotFoundError,
CommitNotFoundError,
FileOutOfRepositoryError,
RepositoryConnectionError,
Expand All @@ -31,6 +33,7 @@
)
from infrahub.git.constants import BRANCHES_DIRECTORY_NAME, COMMITS_DIRECTORY_NAME, TEMPORARY_DIRECTORY_NAME
from infrahub.git.directory import get_repositories_directory, initialize_repositories_directory
from infrahub.git.utils import branch_name_in_import_sync_branches
from infrahub.git.worktree import Worktree
from infrahub.log import get_logger
from infrahub.workers.dependencies import get_client
Expand Down Expand Up @@ -733,6 +736,45 @@ async def fetch(self) -> bool:

return True

async def get_filtered_remote_branches(self) -> dict[str, BranchInRemote]:
branches = self.get_branches_from_remote()

if not config.SETTINGS.git.import_sync_branch_names:
return branches

filtered_branches = {}
skipped_branch_names = []

for short_name, branch_data in branches.items():
branch = None

try:
branch = registry.get_branch_from_registry(branch=short_name)
except BranchNotFoundError:
...

branch_exists_import_sync_condition = branch and (
branch.name not in {registry.default_branch, self.default_branch}
and not branch.sync_with_git
and not branch_name_in_import_sync_branches(branch_short_name=short_name)
)
branch_does_not_exist_import_sync_condition = not branch and not branch_name_in_import_sync_branches(
branch_short_name=short_name
)

if branch_exists_import_sync_condition or branch_does_not_exist_import_sync_condition:
skipped_branch_names.append(short_name)
continue

filtered_branches[short_name] = branch_data

if skipped_branch_names:
log.debug(
f"Skipped the following branches {skipped_branch_names} "
f"because no match was found in import_sync_branch_names {config.SETTINGS.git.import_sync_branch_names}"
)
return filtered_branches

async def compare_local_remote(self) -> tuple[list[str], list[str]]:
"""
Returns:
Expand All @@ -745,7 +787,7 @@ async def compare_local_remote(self) -> tuple[list[str], list[str]]:
# TODO move this section into a dedicated function to compare and bring in sync the remote repo with the local one.
# It can be useful just after a clone etc ...
local_branches = self.get_branches_from_local()
remote_branches = self.get_branches_from_remote()
remote_branches = await self.get_filtered_remote_branches()

new_branches = set(remote_branches.keys()) - set(local_branches.keys())
existing_branches = set(local_branches.keys()) - new_branches
Expand Down
9 changes: 9 additions & 0 deletions backend/infrahub/git/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
from collections import defaultdict
from typing import TYPE_CHECKING, Any

Expand All @@ -12,6 +13,7 @@
from infrahub.database import InfrahubDatabase
from infrahub.generators.models import ProposedChangeGeneratorDefinition

from .. import config
from .models import RepositoryBranchInfo, RepositoryData

if TYPE_CHECKING:
Expand Down Expand Up @@ -168,3 +170,10 @@ async def fetch_proposed_change_generator_definition_targets(
return await _fetch_definition_targets(
client=client, branch=branch, group_id=definition.group_id, parameters=definition.parameters
)


def branch_name_in_import_sync_branches(branch_short_name: str) -> bool:
for branch_filter in config.SETTINGS.git.import_sync_branch_names:
if re.fullmatch(branch_filter, branch_short_name) or branch_filter == branch_short_name:
return True
return False
25 changes: 25 additions & 0 deletions backend/tests/unit/git/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import shutil
import tarfile
from pathlib import Path
from typing import Generator

import anyio
import pytest
Expand All @@ -14,8 +15,12 @@
from infrahub_sdk.uuidt import UUIDT
from pytest_httpx import HTTPXMock

from infrahub import config
from infrahub.core.branch import Branch
from infrahub.core.constants import InfrahubKind
from infrahub.core.initialization import create_branch
from infrahub.core.schema import SchemaRoot, core_models
from infrahub.database import InfrahubDatabase
from infrahub.git import InfrahubRepository
from infrahub.git.repository import InfrahubReadOnlyRepository
from infrahub.utils import find_first_file_in_directory, get_fixtures_dir
Expand Down Expand Up @@ -1346,3 +1351,23 @@ async def mock_update_artifact(httpx_mock: HTTPXMock) -> HTTPXMock:
method="POST", json=response, match_headers={"X-Infrahub-Tracker": "mutation-coreartifact-update"}
)
return httpx_mock


@pytest.fixture
def import_sync_branch_names() -> Generator[None, None, None]:
initial_import_sync_branch_names = config.SETTINGS.git.import_sync_branch_names
config.SETTINGS.git.import_sync_branch_names = ["branch.*"]
yield
config.SETTINGS.git.import_sync_branch_names = initial_import_sync_branch_names


@pytest.fixture
async def mock_create_branch_git_repo_01(db: InfrahubDatabase, default_branch: Branch) -> None:
await create_branch(branch_name="branch01", db=db)
await create_branch(branch_name="branch02", db=db)
await create_branch(branch_name="clean-branch", db=db)


@pytest.fixture
async def mock_create_branch_git_repo_03(db: InfrahubDatabase, default_branch: Branch) -> None:
await create_branch(branch_name="branch01", db=db)
22 changes: 22 additions & 0 deletions backend/tests/unit/git/test_git_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -1082,3 +1082,25 @@ async def test_compare_python_check(
)

assert await repo.compare_python_check_definition(check=check03, existing_check=existing_check) is False


async def test_get_filtered_remote_branches__all_branches_exists(
git_repo_01: InfrahubRepository, mock_create_branch_git_repo_01, import_sync_branch_names
) -> None:
repo = git_repo_01
filtered_remote_branches = await repo.get_filtered_remote_branches()
assert sorted(filtered_remote_branches.keys()) == ["branch01", "branch02", "main"]


async def test_get_filtered_remote_branches__some_branches_exists(
git_repo_01: InfrahubRepository, mock_create_branch_git_repo_03, import_sync_branch_names
) -> None:
repo = git_repo_01
filtered_remote_branches = await repo.get_filtered_remote_branches()
assert sorted(filtered_remote_branches.keys()) == ["branch01", "branch02", "main"]


async def test_get_filtered_remote_branches__no_import_sync_branch_names(git_repo_01: InfrahubRepository) -> None:
repo = git_repo_01
filtered_remote_branches = await repo.get_filtered_remote_branches()
assert sorted(filtered_remote_branches.keys()) == ["branch01", "branch02", "clean-branch", "main"]
1 change: 1 addition & 0 deletions changelog/+66125521.added.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added branch filtering capability to selectively synchronize remote branches based on configurable import sync patterns.