-
Notifications
You must be signed in to change notification settings - Fork 35
IFC-1886: Paginated branch graphql query #7418
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: develop
Are you sure you want to change the base?
Changes from 10 commits
1102ae7
4e16ec7
c0b3b31
9a07e23
41b1849
c8fbca1
dd242d9
9f1dc4a
3a7ff90
e659340
2ad4b2d
32c72ad
a38cec2
84fac0a
f7d4828
491ad04
86dbefa
9eba0b8
9fe2763
8e4dca9
f0aa561
089b015
fb7d0a6
1157cc4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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 | ||
|
|
@@ -28,3 +28,29 @@ async def branch_resolver( | |
| resolver=branch_resolver, | ||
| required=True, | ||
| ) | ||
|
|
||
|
|
||
| async def infrahub_branch_resolver( | ||
| root: dict, # noqa: ARG001 | ||
| info: GraphQLResolveInfo, | ||
| limit: int | None = None, | ||
| offset: int | None = None, | ||
| ) -> dict[str, Any]: | ||
|
Comment on lines
+33
to
+38
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Add validation for pagination parameters. The Apply this diff to add validation: async def infrahub_branch_resolver(
root: dict, # noqa: ARG001
info: GraphQLResolveInfo,
limit: int | None = None,
offset: int | None = None,
) -> dict[str, Any]:
+ """...""" # Add docstring as per previous comment
+
+ # Validate and set defaults for pagination parameters
+ if limit is None:
+ limit = 100
+ if offset is None:
+ offset = 0
+
+ if limit < 1:
+ raise ValueError("limit must be at least 1")
+ if offset < 0:
+ raise ValueError("offset must be non-negative")
+
fields = extract_graphql_fields(info)🤖 Prompt for AI Agents |
||
| fields = extract_graphql_fields(info) | ||
| branches = await BranchType.get_list( | ||
| graphql_context=info.context, fields=fields.get("edges", {}).get("node", {}), limit=limit, offset=offset | ||
| ) | ||
| count = await InfrahubBranchType.get_list_count(graphql_context=info.context) | ||
| return {"count": count, "edges": {"node": branches}} | ||
|
||
|
|
||
|
|
||
| InfrahubBranchQueryList = Field( | ||
| InfrahubBranchType, | ||
| ids=List(of_type=NonNull(ID)), | ||
| name=String(), | ||
|
||
| offset=Int(), | ||
| limit=Int(), | ||
| description="Retrieve paginated information about active branches.", | ||
| resolver=infrahub_branch_resolver, | ||
| required=True, | ||
| ) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -31,7 +31,6 @@ async def test_branch_query( | |
|
|
||
| gql_params = await prepare_graphql_params( | ||
| db=db, | ||
| include_subscription=False, | ||
| branch=default_branch, | ||
| account_session=session_admin, | ||
| service=service, | ||
|
|
@@ -61,9 +60,7 @@ async def test_branch_query( | |
| } | ||
| } | ||
| """ | ||
| gql_params = await prepare_graphql_params( | ||
| db=db, include_subscription=False, branch=default_branch, service=service | ||
| ) | ||
| gql_params = await prepare_graphql_params(db=db, branch=default_branch, service=service) | ||
| all_branches = await graphql( | ||
| schema=gql_params.schema, | ||
| source=query, | ||
|
|
@@ -108,9 +105,7 @@ async def test_branch_query( | |
| } | ||
| } | ||
| """ % branch3["name"] | ||
| gql_params = await prepare_graphql_params( | ||
| db=db, include_subscription=False, branch=default_branch, service=service | ||
| ) | ||
| gql_params = await prepare_graphql_params(db=db, branch=default_branch, service=service) | ||
| name_response = await graphql( | ||
| schema=gql_params.schema, | ||
| source=name_query, | ||
|
|
@@ -134,9 +129,7 @@ async def test_branch_query( | |
| """ % [branch3["id"]] | ||
| id_query = id_query.replace("'", '"') | ||
|
|
||
| gql_params = await prepare_graphql_params( | ||
| db=db, include_subscription=False, branch=default_branch, service=service | ||
| ) | ||
| gql_params = await prepare_graphql_params(db=db, branch=default_branch, service=service) | ||
| id_response = await graphql( | ||
| schema=gql_params.schema, | ||
| source=id_query, | ||
|
|
@@ -148,3 +141,90 @@ 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, | ||
| 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(offset: 2, limit: 5) { | ||
| count | ||
| edges { | ||
| node { | ||
| name | ||
| description | ||
| } | ||
| } | ||
| } | ||
| } | ||
| """ | ||
| gql_params = await prepare_graphql_params(db=db, 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 all_branches.data["InfrahubBranch"]["count"] == 13 | ||
|
||
|
|
||
| expected_branches = [ | ||
| { | ||
| "description": "Default Branch", | ||
| "name": "main", | ||
| }, | ||
| { | ||
| "description": "my description", | ||
| "name": "branch3", | ||
| }, | ||
| *[ | ||
| { | ||
| "description": f"sample description {i}", | ||
| "name": f"sample-branch-{i}", | ||
| } | ||
| for i in range(10) | ||
| ], | ||
| ] | ||
| assert all_branches.data["InfrahubBranch"]["edges"]["node"].sort( | ||
|
||
| key=operator.itemgetter("name") | ||
| ) == expected_branches.sort(key=operator.itemgetter("name")) | ||
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6880,6 +6880,16 @@ input InfrahubAccountUpdateSelfInput { | |
| password: String | ||
| } | ||
|
|
||
| type InfrahubBranchEdge { | ||
| node: [Branch!]! | ||
| } | ||
|
|
||
| type InfrahubBranchType { | ||
| """Total number of items""" | ||
| count: Int! | ||
| edges: InfrahubBranchEdge! | ||
| } | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| input InfrahubComputedAttributeRecomputeInput { | ||
| """Name of the computed attribute that must be recomputed""" | ||
| attribute: String! | ||
|
|
@@ -10397,6 +10407,8 @@ type Query { | |
| """Retrieve fields mapping for converting object type""" | ||
| FieldsMappingTypeConversion(source_kind: String, target_kind: String): FieldsMapping! | ||
| InfrahubAccountToken(limit: Int, offset: Int): AccountTokenEdges! | ||
| """Retrieve paginated information about active branches.""" | ||
| InfrahubBranch(ids: [ID!], limit: Int, name: String, offset: Int): InfrahubBranchType! | ||
|
||
| InfrahubEvent( | ||
| """Filter the query to specific accounts""" | ||
| account__ids: [String!] | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion | 🟠 Major
Add docstring and type annotation.
The class is missing a docstring and type annotation, which are required by the coding guidelines.
Apply this diff to add the missing docstring and type annotation:
As per coding guidelines.
📝 Committable suggestion
🤖 Prompt for AI Agents