fix: use configured default_branch in generators, transforms, checks

Merged
PT
17d ago
+138-25

Why

Running infrahubctl generator, transform or check without --branch targeted the
local Git checkout's active branch instead of the configured default_branch, failing with
BranchNotFoundError whenever that Git branch did not exist in Infrahub. The fallback the
default_branch_from_git flag exists to gate was applied unconditionally, overriding an
explicitly configured INFRAHUB_DEFAULT_BRANCH.

Goal: with default_branch_from_git unset or false, an operation with no explicit branch
targets the configured default_branch — the same branch the rest of the command already uses.

Non-goals: Config.clone drops an explicit branch argument when default_branch_from_git
is enabled. Pre-existing, out of scope here, will be filed separately.

Closes #1290

What changed

Behavioral changes:

  • Generators, transforms and checks run without an explicit branch now target the configured
    default_branch.
  • The local Git branch is used only when default_branch_from_git is enabled.
  • infrahubctl generator is no longer internally inconsistent: the GraphQL query and the
    schema fetch resolve to the same branch.

Implementation notes:

  • InfrahubOperation.__init__ resolves the branch once as branch or client.default_branch.
    client.default_branch is already the output of ConfigBase.default_infrahub_branch, which
    makes the default_branch_from_git decision — so the flag stays honoured in exactly one place
    rather than being reimplemented. Same pattern already used in ctl/cli_commands.py:386.
  • branch_name becomes a plain accessor; the GitRepoManager lookup and the self.git
    attribute are removed from operation.py.
  • InfrahubCheck.branch_name gets the same treatment. Its client is optional, so with no client
    (no config to consult) it falls back to the existing get_branch() helper.
  • Fixed at the base class, not the call sites — InfrahubGenerator and InfrahubTransform both
    inherit from InfrahubOperation, as does every library consumer.

What stayed the same:

  • No public API or signature changes. branch_name and root_directory are unchanged.
  • default_branch_from_git=true behaviour is unchanged.
  • No generated-doc drift; the config reference already documented the intended behaviour.

How to review

Start with infrahub_sdk/operation.py — the whole fix is self.branch = branch or client.default_branch. infrahub_sdk/checks.py is the same change with an extra no-client arm.

How to test

uv run pytest tests/unit/sdk/test_operation.py tests/unit/sdk/checks/
uv run invoke format lint-code

Regression coverage: explicit branch wins / no branch + flag off → configured default_branch /
no branch + flag on → local Git branch. Both new default_branch assertions fail on the
pre-fix code.

Impact & rollout

  • Backward compatibility: behaviour change. Anyone relying on the implicit Git fallback
    without setting default_branch_from_git=true now gets the configured default_branch
    (default main) instead of their checkout branch. That is the documented contract; noted in
    the changelog entry.
  • Config/env changes: none. INFRAHUB_DEFAULT_BRANCH and INFRAHUB_DEFAULT_BRANCH_FROM_GIT
    now behave as documented.
  • Deployment notes: safe to deploy.

Checklist

  • Tests added/updated
  • Changelog entry added (changelog/1290.fixed.md)
  • External docs updated — not needed, generated config reference already correct
  • Internal .md docs updated — not needed

Summary by cubic

Fixes generators, transforms, and checks to target the configured default_branch when no explicit branch is passed, eliminating the BranchNotFoundError that occurred when the local Git branch didn't exist in Infrahub.

  • The local Git branch is used only when default_branch_from_git is enabled, and is resolved from the operation's root_directory instead of the process working directory.
  • infrahubctl generator now resolves the same branch for its GraphQL query and schema fetch.
  • Behavior change: operations without an explicit branch or default_branch_from_git now target the configured default_branch (default main) instead of the checkout branch. No config or env changes required. Closes #1290.