Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
1102ae7
WIP
solababs Oct 13, 2025
4e16ec7
Merge branch 'develop' into sb-20251013-infrahub-branch-query-ifc-1886
solababs Oct 15, 2025
c0b3b31
IFC-1886: Paginated branch graphql query
solababs Oct 16, 2025
9a07e23
update repsonse format
solababs Oct 20, 2025
41b1849
fix mypy
solababs Oct 20, 2025
c8fbca1
Merge branch 'develop' into sb-20251013-infrahub-branch-query-ifc-1886
solababs Oct 20, 2025
dd242d9
Merge branch 'develop' into sb-20251013-infrahub-branch-query-ifc-1886
solababs Oct 21, 2025
9f1dc4a
refactor branch list and count logic
solababs Oct 21, 2025
3a7ff90
fix mypy
solababs Oct 21, 2025
e659340
remove unused limit and offset on get list count
solababs Oct 21, 2025
2ad4b2d
conditionally resolve fields
solababs Oct 28, 2025
32c72ad
fix mypy, update schema
solababs Oct 29, 2025
a38cec2
Merge branch 'develop' into sb-20251013-infrahub-branch-query-ifc-1886
solababs Oct 29, 2025
84fac0a
change response format
solababs Oct 29, 2025
f7d4828
Merge branch 'develop' into sb-20251013-infrahub-branch-query-ifc-1886
solababs Oct 29, 2025
491ad04
update status, add schema
solababs Oct 29, 2025
86dbefa
update schema
solababs Oct 29, 2025
9eba0b8
fix mypy
solababs Oct 29, 2025
9fe2763
Merge branch 'develop' into sb-20251013-infrahub-branch-query-ifc-1886
solababs Oct 30, 2025
8e4dca9
use uuid for id
solababs Oct 30, 2025
f0aa561
Merge branch 'sb-20251013-infrahub-branch-query-ifc-1886' of https://…
solababs Oct 30, 2025
089b015
remove name and ids filter
solababs Oct 31, 2025
fb7d0a6
Merge branch 'develop' into sb-20251013-infrahub-branch-query-ifc-1886
solababs Oct 31, 2025
1157cc4
update graphql schema
solababs Oct 31, 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
3 changes: 2 additions & 1 deletion backend/infrahub/graphql/queries/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from .account import AccountPermissions, AccountToken
from .branch import BranchQueryList
from .branch import BranchQueryList, InfrahubBranchQueryList
from .internal import InfrahubInfo
from .ipam import (
DeprecatedIPAddressGetNextAvailable,
Expand All @@ -20,6 +20,7 @@
"BranchQueryList",
"DeprecatedIPAddressGetNextAvailable",
"DeprecatedIPPrefixGetNextAvailable",
"InfrahubBranchQueryList",
"InfrahubIPAddressGetNextAvailable",
"InfrahubIPPrefixGetNextAvailable",
"InfrahubInfo",
Expand Down
37 changes: 35 additions & 2 deletions backend/infrahub/graphql/queries/branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@

from typing import TYPE_CHECKING, Any

from graphene import ID, Field, List, NonNull, String
from graphene import ID, Field, Int, List, NonNull, String

from infrahub.graphql.field_extractor import extract_graphql_fields
from infrahub.graphql.types import BranchType
from infrahub.graphql.types import BranchType, InfrahubBranchType

if TYPE_CHECKING:
from graphql import GraphQLResolveInfo
Expand All @@ -28,3 +28,36 @@ async def branch_resolver(
resolver=branch_resolver,
required=True,
)


async def infrahub_branch_resolver(
root: dict, # noqa: ARG001
info: GraphQLResolveInfo,
**kwargs: Any,
) -> dict[str, Any]:
page = kwargs.pop("page", 1)
limit = kwargs.pop("limit", 100)
offset = (page - 1) * limit
fields = {name: str(field.type) for name, field in BranchType._meta.fields.items()}

branches = await BranchType.get_list(
fields=fields, graphql_context=info.context, limit=limit, offset=offset, **kwargs
)

return {
"current_page": page,
"count_per_page": limit,
"branches": branches,
}


InfrahubBranchQueryList = Field(
InfrahubBranchType,
ids=List(ID),
name=String(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These parameters doesn't seem to work now.

query MyQuery {
  InfrahubBranch(name: "branch2") {
    count
    edges {
      node {
        id
        name {
          value
        }
      }
    }
  }
}

I.e infrahub_branch_resolver() doesn't accept the parameters ids or name so the above query would fail. I think perhaps we can just remove both of them in this first iteration and then consider which filter options we want and need. We will want to add some of them for sure. But it could potentially be quite verbose if we start to add all of the variations that we dynamically generate for other node types, so I think that we can have a discussion around that after this PR is merge.

I.e. if we were to follow the current approach we'd have:

  • name__value
  • name__values
  • description__value
  • description__values
  • etc for all attributes.

page=Int(default_value=1),
limit=Int(default_value=100),
description="Retrieve paginated information about active branches.",
resolver=infrahub_branch_resolver,
required=True,
)
2 changes: 2 additions & 0 deletions backend/infrahub/graphql/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
BranchQueryList,
DeprecatedIPAddressGetNextAvailable,
DeprecatedIPPrefixGetNextAvailable,
InfrahubBranchQueryList,
InfrahubInfo,
InfrahubIPAddressGetNextAvailable,
InfrahubIPPrefixGetNextAvailable,
Expand All @@ -65,6 +66,7 @@ class InfrahubBaseQuery(ObjectType):

Relationship = Relationship

InfrahubBranch = InfrahubBranchQueryList
InfrahubInfo = InfrahubInfo
InfrahubStatus = InfrahubStatus

Expand Down
3 changes: 2 additions & 1 deletion backend/infrahub/graphql/types/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
StrAttributeType,
TextAttributeType,
)
from .branch import BranchType
from .branch import BranchType, InfrahubBranchType
from .interface import InfrahubInterface
from .node import InfrahubObject
from .permission import PaginatedObjectPermission
Expand All @@ -41,6 +41,7 @@
"DropdownType",
"IPHostType",
"IPNetworkType",
"InfrahubBranchType",
"InfrahubInterface",
"InfrahubObject",
"InfrahubObjectType",
Expand Down
8 changes: 7 additions & 1 deletion backend/infrahub/graphql/types/branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from typing import TYPE_CHECKING, Any

from graphene import Boolean, Field, String
from graphene import Boolean, Field, Int, List, NonNull, String

from infrahub.core.branch import Branch
from infrahub.core.constants import GLOBAL_BRANCH_NAME
Expand Down Expand Up @@ -44,3 +44,9 @@ async def get_list(
return []

return [await obj.to_graphql(fields=fields) for obj in objs if obj.name != GLOBAL_BRANCH_NAME]


class InfrahubBranchType(InfrahubObjectType):
current_page = Int()
count_per_page = Int()
branches = List(of_type=NonNull(BranchType))
78 changes: 78 additions & 0 deletions backend/tests/unit/graphql/queries/test_branch.py
Original file line number Diff line number Diff line change
Expand Up @@ -148,3 +148,81 @@ async def test_branch_query(
assert id_response.data
assert id_response.data["Branch"][0]["name"] == "branch3"
assert len(id_response.data["Branch"]) == 1

async def test_paginated_branch_query(
self,
db: InfrahubDatabase,
default_branch: Branch,
register_core_models_schema,
session_admin,
client,
service,
):
for i in range(10):
create_branch_query = """
mutation {
BranchCreate(data: { name: "%s", description: "%s" }) {
ok
object {
id
name
}
}
}
""" % (
f"sample-branch-{i}",
f"sample description {i}",
)

gql_params = await prepare_graphql_params(
db=db,
include_subscription=False,
branch=default_branch,
account_session=session_admin,
service=service,
)
branch_result = await graphql(
schema=gql_params.schema,
source=create_branch_query,
context_value=gql_params.context,
root_value=None,
variable_values={},
)
assert branch_result.errors is None
assert branch_result.data

query = """
query {
InfrahubBranch(page: 2, limit: 5) {
branches {
id
name
description
origin_branch
branched_from
created_at
is_default
is_isolated
has_schema_changes
sync_with_git
}
current_page
count_per_page
}
}
"""
gql_params = await prepare_graphql_params(
db=db, include_subscription=False, branch=default_branch, service=service
)
all_branches = await graphql(
schema=gql_params.schema,
source=query,
context_value=gql_params.context,
root_value=None,
variable_values={},
)
assert all_branches.errors is None
assert all_branches.data
assert len(all_branches.data["InfrahubBranch"]["branches"]) == 5
assert all_branches.data["InfrahubBranch"]["current_page"] == 2
assert all_branches.data["InfrahubBranch"]["count_per_page"] == 5
Loading