Skip to content

bug: periodic git sync ignores non-main default_branch, never imports default-branch updates #9600

Description

@lancamat1

Component

Git Integration

Infrahub version

1.9.6

Current Behavior

A read-write CoreRepository whose default_branch is not main (e.g. default_branch=staging) never imports new commits on its default branch via the periodic sync. The instance stays pinned to its last-imported commit while reporting sync_status: in-sync; new commits on the git default branch are silently never applied.

The periodic git_repositories_sync flow fails on every cycle with:

RepositoryError: Unable to get worktree : staging
ValueError: Unable to identify the worktree for the branch : staging
→ Flow run Finished in state Failed(...)

Expected Behavior

The periodic sync should use the repository's configured default_branch and import new commits on it into the instance's main (advancing CoreRepository.commit). It must never silently report in-sync while pinned to a stale commit.

Steps to Reproduce

  1. Deploy Infrahub 1.9.6.
  2. Add a read-write CoreRepository and set default_branch to a non-main branch (e.g. staging) via CoreRepositoryCreate.
  3. Let it import (commit = C0).
  4. Push a new commit to the git staging branch.
  5. Observe: git_repositories_sync fails with Unable to identify the worktree for the branch : staging; CoreRepository.commit stays at C0; sync_status stays in-sync. The new commit is never imported.

Additional Information

Root cause

get_repositories_commit_per_branch (backend/infrahub/git/utils.py, ~line 40) does not request the default_branch attribute when it loads repositories for the sync flow:

repos = await NodeManager.query(
    db=db, branch=branch, schema=kind, order=OrderModel(disable=True),
    fields={"id": None, "name": None, "commit": None,
            "internal_status": None, "location": None, "ref": None},
    #                                                   ^^^ "default_branch" is missing
)

Because the attribute is not fetched, repository.default_branch.value in sync_remote_repositories (backend/infrahub/git/tasks.py, ~line 262/301) returns the schema default "main" (backend/infrahub/core/schema/definitions/core/repository.py, default_value="main") instead of the configured value. The repository is initialised with default_branch_name="main", so self.default_branch == "main" for the whole sync.

That breaks the default-branch → worktree mapping in pull() (backend/infrahub/git/base.py):

identifier = branch_name                                   # "staging"
if branch_name == self.default_branch and branch_name != registry.default_branch:
    identifier = "main"                                    # ← skipped: self.default_branch is "main"
repo = self.get_git_repo_worktree(identifier="staging")    # ← no worktree keyed "staging" → RepositoryError

The default branch's worktree is keyed main; with the wrong default_branch the code looks up a worktree named after the git branch (staging), which does not exist, and the flow raises.

Corroborating evidence (all consistent with self.default_branch == "main"):

  • validate_remote_branch logs Merging staging into main has no conflicts — it calls has_conflicting_changes(target_branch=self.default_branch, source="staging"), and the target is logged as main.
  • git_repositories_sync flow runs are all FAILED with the worktree : staging ValueError.
  • A manual git pull origin staging inside the worker's worktree fast-forwards cleanly — git, refspec, and credentials are all healthy; only the in-process default_branch is wrong.
  • An instance with default_branch=main is unaffected (the accidental default is correct).

Fix (verified)

Add default_branch to the fetched fields in get_repositories_commit_per_branch:

fields={"id": None, "name": None, "commit": None, "internal_status": None,
        "location": None, "ref": None, "default_branch": None},

Verified live on 1.9.6: with this single change, the previously-stuck instance imported a fresh commit on its non-main default branch within ~30 s, the git_repositories_sync flow returned Completed, and the worktree : staging error disappeared. Without it, the instance stayed stuck across many cycles with FAILED sync flows.

Scope & relation to other issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    type/bugSomething isn't working as expected

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions