Skip to content

Conversation

@BaptisteGi
Copy link
Contributor

@BaptisteGi BaptisteGi commented Dec 27, 2025

GraphQL Query Analyzer - Migration & Implementation

Overview

The InfrahubQueryAnalyzer enables static analysis of GraphQL queries to determine if they target single or multiple objects. This is exposed via infrahubctl graphql check [query-path].

Architecture

Components

File Purpose
infrahub_sdk/query_analyzer.py Core analyzer with InfrahubQueryAnalyzer class and data models
infrahub_sdk/schema/main.py BranchSchema with node_names, generic_names, profile_names properties and getter methods
infrahub_sdk/ctl/graphql.py CLI check command implementation

Type Adaptations from Backend

Backend SDK
infrahub.core.constants.RelationshipCardinality infrahub_sdk.schema.RelationshipCardinality
infrahub.core.schema.GenericSchema infrahub_sdk.schema.GenericSchemaAPI
infrahub.core.schema.MainSchemaTypes NodeSchemaAPI | GenericSchemaAPI | ProfileSchemaAPI | TemplateSchemaAPI
SchemaBranch SchemaBranchProtocol (satisfied by BranchSchema)
SchemaNotFoundError KeyError

Implementation Details

Schema Data Flow

client.schema.all() returns MutableMapping[str, MainSchemaTypesAPI] — a flat dict with kind names as keys and schema objects as values. This is not the raw API response format.

# Correct usage:
schema_data = await client.schema.all(branch=branch)
branch_schema = BranchSchema(hash="", nodes=schema_data)

# Wrong - from_api_response expects {"nodes": [...], "generics": [...], ...}
# branch_schema = BranchSchema.from_api_response(schema_data)

Single-Target Detection Logic

A query is considered "single-target" when:

  1. All operations have infrahub_model with uniqueness_constraints
  2. Each operation has an argument matching the uniqueness constraint format
  3. The argument is either:
    • A required variable ($name: String!)
    • A static value (name__value: "my-tag")
    • The ids argument with a required variable

Critical: The uniqueness constraint must match the GraphQL argument name format (e.g., name__value, not name).

Edge Cases Handled

Scenario Behavior
Empty queries list only_has_unique_targets returns False
Unknown model in query Model skipped, top_level_kinds empty
No models found Warning displayed, exit code 1
Optional variable filter Returns False (multi-target)
No .gql files in path Error displayed, exit code 1
Multiple files with errors All files checked, exit code 1 if any errors

Usage

The check command accepts a file or directory path. If a directory is provided, it recursively finds all .gql files. If no path is provided, it defaults to the current directory.

# Check a single file
$ infrahubctl graphql check query1.gql
Checking 1 GraphQL file...

────────────────────────────────────────────────────────────
[1/1] query1.gql
  Top-level kinds: BuiltinTag
  Result: Single-target query (good)
    This query targets unique nodes, enabling selective artifact regeneration.
────────────────────────────────────────────────────────────

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->
## Summary by CodeRabbit

* **New Features**
  * New CLI command to validate GraphQL query files with per-file analysis, error reporting, and a final summary (non‑zero exit on errors).
  * Comprehensive GraphQL query analyzer that builds query reports, computes impacted models, and reasons about fragments, variables, arguments, and access.

* **Enhancements**
  * Schema accessors added for easier retrieval of node, generic, and profile types.

* **Tests**
  * Unit tests for the query analyzer and report behavior.

* **Documentation**
  * Added docs describing the new CLI command and usage.

<sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub>
<!-- end of auto-generated comment: release notes by coderabbit.ai -->:
  1 single-target

# Check all .gql files in a directory
$ infrahubctl graphql check queries/
Checking 3 GraphQL files...

────────────────────────────────────────────────────────────
[1/3] queries/query1.gql
  Top-level kinds: BuiltinTag
  Result: Single-target query (good)
    This query targets unique nodes, enabling selective artifact regeneration.
────────────────────────────────────────────────────────────
[2/3] queries/query3.gql
  Validation failed:
    - Cannot query field 'BuiltinUnknown' on type 'Query'. Did you mean 'BuiltinTag'?
────────────────────────────────────────────────────────────
[3/3] queries/query2.gql
  Top-level kinds: BuiltinTag
  Result: Multi-target query
    May cause excessive artifact regeneration. Fix: filter by ID or unique attribute.
────────────────────────────────────────────────────────────

Summary:
  1 single-target
  1 multi-target
    See: https://docs.infrahub.app/topics/graphql
  1 errors

Tests

Unit tests in tests/unit/sdk/test_infrahub_query_analyzer.py cover:

  • Empty queries handling
  • Multi-target detection (no filter)
  • Single-target detection (required unique filter, static filter, ids filter)
  • Optional filter handling
  • Top-level kinds extraction

Known Limitations & Future Improvements

1. BranchSchema Construction Workaround

Issue: Direct instantiation bypasses proper factory method.

# Current workaround
branch_schema = BranchSchema(hash="", nodes=schema_data)

Improvement: Add a factory method to BranchSchema that accepts the client.schema.all() output format:

@classmethod
def from_schema_dict(cls, nodes: MutableMapping[str, MainSchemaTypesAPI], hash: str = "") -> Self:
    return cls(hash=hash, nodes=nodes)

Or modify from_api_response to detect the input format.

2. Uniqueness Constraint Format Mismatch

Issue: The analyzer compares argument.name (e.g., name__value) against uniqueness_constraints (e.g., [["name"]]). These use different formats.

Current behavior: Only works if uniqueness_constraints are defined with the GraphQL argument format (name__value).

Improvement: Normalize the comparison — either strip __value suffix from arguments or expand constraint names to include the suffix.

3. Template Schema Handling

Issue: _get_operations() checks node_names, generic_names, profile_names but not templates.

if model_name in self.schema_branch.node_names:
    ...
elif model_name in self.schema_branch.generic_names:
    ...
elif model_name in self.schema_branch.profile_names:
    ...
else:
    continue  # Templates silently skipped

Improvement: Add template_names property and corresponding handling.

4. Schema Hash Not Populated

Issue: BranchSchema is constructed with empty hash.

branch_schema = BranchSchema(hash="", nodes=schema_data)

Improvement: Fetch and pass the actual schema hash for cache validation purposes.

5. GraphQL Schema Fetched Separately

Issue: Two API calls required — one for Infrahub schema, one for GraphQL schema.

Improvement: Consider caching or combining these calls if performance becomes an issue.

@coderabbitai
Copy link

coderabbitai bot commented Dec 27, 2025

Walkthrough

Adds a new Infrahub GraphQL query analysis subsystem: a new infrahub_sdk/query_analyzer.py module that parses GraphQL operations, handles fragments and dependencies, constructs query node trees mapped to BranchSchema models, and reports variables, affected models, and mutation actions. Extends BranchSchema in infrahub_sdk/schema/main.py with node_names, generic_names, profile_names, and typed get/get_node/get_generic/get_profile accessors. Introduces a CLI infrahubctl graphql check command to analyze .gql files using a branch schema and exits non‑zero on errors. Adds unit tests and documentation for the new check command.

Pre-merge checks

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The title 'Graphql graph CTL command' is vague and contains a typo ('graph' appears redundant). It does not clearly convey the primary change: adding a GraphQL query analysis feature and a CLI check command. Replace with a more descriptive title such as 'Add GraphQL query analyzer and check command' to clearly communicate the main functionality being added.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cloudflare-workers-and-pages
Copy link

cloudflare-workers-and-pages bot commented Dec 27, 2025

Deploying infrahub-sdk-python with  Cloudflare Pages  Cloudflare Pages

Latest commit: 68ad676
Status: ✅  Deploy successful!
Preview URL: https://fd310e62.infrahub-sdk-python.pages.dev
Branch Preview URL: https://bgi-grahql-check-command.infrahub-sdk-python.pages.dev

View logs

@BaptisteGi BaptisteGi marked this pull request as ready for review December 27, 2025 11:30
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
infrahub_sdk/query_analyzer.py (1)

417-424: Consider simplifying the schema_branch type annotation.

The schema_branch parameter is typed as SchemaBranchProtocol | BranchSchema, but since BranchSchema implements SchemaBranchProtocol, the union type is redundant. You could simplify to just SchemaBranchProtocol.

🔎 Proposed refactor
     def __init__(
         self,
         query: str,
-        schema_branch: SchemaBranchProtocol | BranchSchema,
+        schema_branch: SchemaBranchProtocol,
         schema: GraphQLSchema | None = None,
         query_variables: dict[str, Any] | None = None,
         operation_name: str | None = None,
     ) -> None:

This maintains flexibility while being more precise about the interface requirement.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1f1cb0c and e40b48b.

📒 Files selected for processing (4)
  • infrahub_sdk/ctl/graphql.py
  • infrahub_sdk/query_analyzer.py
  • infrahub_sdk/schema/main.py
  • tests/unit/sdk/test_infrahub_query_analyzer.py
🧰 Additional context used
📓 Path-based instructions (5)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use type hints on all function signatures
Never mix async/sync inappropriately
Never bypass type checking without justification

Files:

  • infrahub_sdk/schema/main.py
  • infrahub_sdk/query_analyzer.py
  • infrahub_sdk/ctl/graphql.py
  • tests/unit/sdk/test_infrahub_query_analyzer.py
infrahub_sdk/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Follow async/sync dual pattern for new features in the Python SDK

Files:

  • infrahub_sdk/schema/main.py
  • infrahub_sdk/query_analyzer.py
  • infrahub_sdk/ctl/graphql.py
infrahub_sdk/ctl/**/*.py

📄 CodeRabbit inference engine (infrahub_sdk/ctl/AGENTS.md)

infrahub_sdk/ctl/**/*.py: Use @catch_exception(console=console) decorator on all async CLI commands
Include CONFIG_PARAM in all CLI command function parameters, even if unused
Use initialize_client() or initialize_client_sync() from ctl.client for client creation in CLI commands
Use Rich library for output formatting in CLI commands (tables, panels, console.print) instead of plain print() statements
Do not instantiate InfrahubClient directly; always use initialize_client() or initialize_client_sync() helper functions
Do not use plain print() statements in CLI commands; use Rich console.print() instead

Files:

  • infrahub_sdk/ctl/graphql.py
tests/**/*.py

📄 CodeRabbit inference engine (tests/AGENTS.md)

tests/**/*.py: Use httpx_mock fixture for HTTP mocking in tests instead of making real HTTP requests
Do not add @pytest.mark.asyncio decorator to async test functions (async auto-mode is globally enabled)

Files:

  • tests/unit/sdk/test_infrahub_query_analyzer.py
tests/unit/**/*.py

📄 CodeRabbit inference engine (tests/AGENTS.md)

Unit tests must be fast, mocked, and have no external dependencies

Files:

  • tests/unit/sdk/test_infrahub_query_analyzer.py
🧬 Code graph analysis (3)
infrahub_sdk/query_analyzer.py (2)
infrahub_sdk/analyzer.py (2)
  • GraphQLQueryAnalyzer (32-121)
  • operations (55-65)
infrahub_sdk/schema/main.py (15)
  • GenericSchemaAPI (288-292)
  • NodeSchemaAPI (312-314)
  • ProfileSchemaAPI (317-318)
  • TemplateSchemaAPI (321-322)
  • BranchSchema (361-460)
  • node_names (368-370)
  • generic_names (373-375)
  • profile_names (378-380)
  • get (382-395)
  • get_node (397-407)
  • get_generic (409-419)
  • get_profile (421-431)
  • kind (279-280)
  • attribute_names (223-224)
  • get_relationship_or_none (193-197)
infrahub_sdk/ctl/graphql.py (5)
infrahub_sdk/ctl/client.py (1)
  • initialize_client (10-25)
infrahub_sdk/ctl/utils.py (1)
  • catch_exception (78-106)
infrahub_sdk/graphql/utils.py (2)
  • insert_fragments_inline (13-31)
  • remove_fragment_import (34-40)
infrahub_sdk/query_analyzer.py (3)
  • InfrahubQueryAnalyzer (407-760)
  • only_has_unique_targets (386-404)
  • query_report (460-464)
infrahub_sdk/schema/main.py (1)
  • BranchSchema (361-460)
tests/unit/sdk/test_infrahub_query_analyzer.py (1)
infrahub_sdk/query_analyzer.py (4)
  • GraphQLQueryReport (289-404)
  • only_has_unique_targets (386-404)
  • query_report (460-464)
  • top_level_kinds (354-355)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: integration-tests-latest-infrahub
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (3)
infrahub_sdk/schema/main.py (1)

367-431: LGTM! Well-structured schema accessors.

The new properties and getter methods provide clean, type-safe access to different schema types. The error handling with KeyError and TypeError is appropriate, and the docstrings clearly document the API compatibility with backend SchemaBranch.

tests/unit/sdk/test_infrahub_query_analyzer.py (1)

1-170: LGTM! Comprehensive test coverage.

The test suite effectively validates the query analyzer's behavior across various scenarios:

  • Empty queries
  • Single/multi-target detection with required, optional, and static filters
  • Top-level kinds extraction
  • Unknown model handling

The fixtures provide isolated, fast test execution without external dependencies.

infrahub_sdk/query_analyzer.py (1)

1-760: LGTM! Solid architecture for GraphQL query analysis.

The implementation provides comprehensive query parsing with:

  • Fragment handling with circular dependency detection
  • Hierarchical query node tree construction
  • Model and permission reasoning
  • Clean separation of concerns with dataclasses and protocols

The code is well-structured with proper type hints throughout.

Comment on lines +645 to +665
def _populate_inline_fragment_node(
self, node: InlineFragmentNode, query_node: GraphQLQueryNode
) -> GraphQLQueryNode:
infrahub_model = self.schema_branch.get(name=node.type_condition.name.value, duplicate=False)
context_type = ContextType.DIRECT
current_node = GraphQLQueryNode(
parent=query_node,
path=node.type_condition.name.value,
context_type=context_type,
infrahub_model=infrahub_model,
)
if node.selection_set:
selections = self._get_selections(selection_set=node.selection_set)
for field_node in selections.field_nodes:
current_node.children.append(self._populate_field_node(node=field_node, query_node=current_node))
for inline_fragment_node in selections.inline_fragment_nodes:
current_node.children.append(
self._populate_inline_fragment_node(node=inline_fragment_node, query_node=current_node)
)

return current_node
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Add error handling for unknown inline fragment types.

In _populate_inline_fragment_node (line 648), the call to self.schema_branch.get() can raise KeyError if the type is not found in the schema. Unlike _populate_named_fragments (lines 582-584) which handles this with try-except, this code will propagate the exception.

🔎 Proposed fix
     def _populate_inline_fragment_node(
         self, node: InlineFragmentNode, query_node: GraphQLQueryNode
     ) -> GraphQLQueryNode:
-        infrahub_model = self.schema_branch.get(name=node.type_condition.name.value, duplicate=False)
+        try:
+            infrahub_model = self.schema_branch.get(name=node.type_condition.name.value, duplicate=False)
+        except KeyError:
+            infrahub_model = None
         context_type = ContextType.DIRECT
         current_node = GraphQLQueryNode(
             parent=query_node,
             path=node.type_condition.name.value,
             context_type=context_type,
             infrahub_model=infrahub_model,
         )

This ensures consistent behavior when encountering unknown types in inline fragments, similar to how named fragments handle missing types.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
def _populate_inline_fragment_node(
self, node: InlineFragmentNode, query_node: GraphQLQueryNode
) -> GraphQLQueryNode:
infrahub_model = self.schema_branch.get(name=node.type_condition.name.value, duplicate=False)
context_type = ContextType.DIRECT
current_node = GraphQLQueryNode(
parent=query_node,
path=node.type_condition.name.value,
context_type=context_type,
infrahub_model=infrahub_model,
)
if node.selection_set:
selections = self._get_selections(selection_set=node.selection_set)
for field_node in selections.field_nodes:
current_node.children.append(self._populate_field_node(node=field_node, query_node=current_node))
for inline_fragment_node in selections.inline_fragment_nodes:
current_node.children.append(
self._populate_inline_fragment_node(node=inline_fragment_node, query_node=current_node)
)
return current_node
def _populate_inline_fragment_node(
self, node: InlineFragmentNode, query_node: GraphQLQueryNode
) -> GraphQLQueryNode:
try:
infrahub_model = self.schema_branch.get(name=node.type_condition.name.value, duplicate=False)
except KeyError:
infrahub_model = None
context_type = ContextType.DIRECT
current_node = GraphQLQueryNode(
parent=query_node,
path=node.type_condition.name.value,
context_type=context_type,
infrahub_model=infrahub_model,
)
if node.selection_set:
selections = self._get_selections(selection_set=node.selection_set)
for field_node in selections.field_nodes:
current_node.children.append(self._populate_field_node(node=field_node, query_node=current_node))
for inline_fragment_node in selections.inline_fragment_nodes:
current_node.children.append(
self._populate_inline_fragment_node(node=inline_fragment_node, query_node=current_node)
)
return current_node
🤖 Prompt for AI Agents
In infrahub_sdk/query_analyzer.py around lines 645 to 665, wrap the call to
self.schema_branch.get(...) in a try/except KeyError to match the named-fragment
handling: if the type is missing catch KeyError, log a warning (using the same
logger used elsewhere in this class) including the missing type name, and return
the parent query_node (i.e., skip creating/populating this inline fragment)
instead of allowing the exception to propagate.

@codecov
Copy link

codecov bot commented Dec 27, 2025

Codecov Report

❌ Patch coverage is 27.85714% with 404 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
infrahub_sdk/query_analyzer.py 31.59% 307 Missing and 7 partials ⚠️
infrahub_sdk/ctl/graphql.py 15.06% 62 Missing ⚠️
infrahub_sdk/schema/main.py 0.00% 28 Missing ⚠️

❗ There is a different number of reports uploaded between BASE (1f1cb0c) and HEAD (68ad676). Click for more details.

HEAD has 13 uploads less than BASE
Flag BASE (1f1cb0c) HEAD (68ad676)
python-3.11 2 0
python-3.12 2 0
python-3.10 2 0
python-filler-3.12 2 0
python-3.14 2 0
python-3.13 2 0
integration-tests 2 1
@@             Coverage Diff             @@
##           stable     #711       +/-   ##
===========================================
- Coverage   76.03%   34.27%   -41.77%     
===========================================
  Files         113      114        +1     
  Lines        9744    10303      +559     
  Branches     1491     1621      +130     
===========================================
- Hits         7409     3531     -3878     
- Misses       1840     6459     +4619     
+ Partials      495      313      -182     
Flag Coverage Δ
integration-tests 34.27% <27.85%> (-0.38%) ⬇️
python-3.10 ?
python-3.11 ?
python-3.12 ?
python-3.13 ?
python-3.14 ?
python-filler-3.12 ?

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
infrahub_sdk/schema/main.py 9.86% <0.00%> (-79.63%) ⬇️
infrahub_sdk/ctl/graphql.py 25.90% <15.06%> (-9.21%) ⬇️
infrahub_sdk/query_analyzer.py 31.59% <31.59%> (ø)

... and 83 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@github-actions github-actions bot added the type/documentation Improvements or additions to documentation label Dec 29, 2025
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
infrahub_sdk/ctl/graphql.py (1)

34-41: Consider adding type annotations to class attributes.

While the instance variables are initialized in __init__, adding explicit class-level type annotations would improve type safety and readability.

🔎 Proposed enhancement
 class CheckResults:
     """Container for check command results."""
+    single_target_count: int
+    multi_target_count: int
+    error_count: int
 
     def __init__(self) -> None:
         self.single_target_count = 0
         self.multi_target_count = 0
         self.error_count = 0
📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e40b48b and 68ad676.

📒 Files selected for processing (2)
  • docs/docs/infrahubctl/infrahubctl-graphql.mdx
  • infrahub_sdk/ctl/graphql.py
✅ Files skipped from review due to trivial changes (1)
  • docs/docs/infrahubctl/infrahubctl-graphql.mdx
🧰 Additional context used
📓 Path-based instructions (3)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Use type hints on all function signatures
Never mix async/sync inappropriately
Never bypass type checking without justification

Files:

  • infrahub_sdk/ctl/graphql.py
infrahub_sdk/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Follow async/sync dual pattern for new features in the Python SDK

Files:

  • infrahub_sdk/ctl/graphql.py
infrahub_sdk/ctl/**/*.py

📄 CodeRabbit inference engine (infrahub_sdk/ctl/AGENTS.md)

infrahub_sdk/ctl/**/*.py: Use @catch_exception(console=console) decorator on all async CLI commands
Include CONFIG_PARAM in all CLI command function parameters, even if unused
Use initialize_client() or initialize_client_sync() from ctl.client for client creation in CLI commands
Use Rich library for output formatting in CLI commands (tables, panels, console.print) instead of plain print() statements
Do not instantiate InfrahubClient directly; always use initialize_client() or initialize_client_sync() helper functions
Do not use plain print() statements in CLI commands; use Rich console.print() instead

Files:

  • infrahub_sdk/ctl/graphql.py
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: integration-tests-latest-infrahub
  • GitHub Check: documentation
  • GitHub Check: Cloudflare Pages
🔇 Additional comments (1)
infrahub_sdk/ctl/graphql.py (1)

298-299: No issue detected. The code is safe from KeyError.

When client.schema.all(branch=None) is called, the all() method normalizes the branch parameter at line 301 of infrahub_sdk/schema/__init__.py with branch = branch or self.client.default_branch before populating the cache at line 306. This ensures the cache is always keyed by client.default_branch (not None), which matches the access on line 299: client.schema.cache[branch or client.default_branch].

Likely an incorrect or invalid review comment.

query: Path | None = typer.Argument(
None, help="Path to the GraphQL query file or directory. Defaults to current directory if not specified."
),
branch: str = typer.Option(None, help="Branch to use for schema."),
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix the type hint to allow None.

The branch parameter has a type hint of str but accepts None as the default value. This will cause type checker errors.

🔎 Proposed fix
-    branch: str = typer.Option(None, help="Branch to use for schema."),
+    branch: str | None = typer.Option(None, help="Branch to use for schema."),

As per coding guidelines, type hints are required on all function signatures.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
branch: str = typer.Option(None, help="Branch to use for schema."),
branch: str | None = typer.Option(None, help="Branch to use for schema."),
🤖 Prompt for AI Agents
In infrahub_sdk/ctl/graphql.py around line 274, the branch parameter is
annotated as str but has a default of None; update the annotation to allow None
(e.g., Optional[str] or str | None depending on project typing target) and
ensure you import Optional from typing if used or rely on PEP 604 union syntax;
keep the help text and default unchanged.

@BaptisteGi
Copy link
Contributor Author

StrEnum was added in Python 3.11, but this project supports Python 3.10+.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type/documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants