Skip to content

Conversation

@wvandeun
Copy link
Contributor

@wvandeun wvandeun commented Dec 1, 2025

Summary by CodeRabbit

  • New Features

    • Added infrahubctl branch report command for detailed branch cleanup status reporting
    • Added get_diff_tree() methods to SDK clients for retrieving complete diff trees with metadata
  • Changed

    • Migrated package management from Poetry to UV across all development workflows and CI/CD
    • Dropped Python 3.9 support; now supports Python 3.10–3.13
    • Removed is_visible property from node attributes
  • Documentation

    • Updated setup guides and CLI documentation with UV-based instructions

✏️ Tip: You can customize this high-level summary in your review settings.

petercrocker and others added 30 commits November 9, 2025 08:27
Configure RichHandler to only show file paths (e.g., object.py:568)
when the --debug flag is used. This provides cleaner output for
normal usage while preserving detailed logging for troubleshooting.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
fix(cli): hide file paths in log output unless debug mode enabled
Merge develop into infrahub-develop
Merge stable into develop
Merge develop into infrahub-develop
* Convert project to UV
Merge stable into develop
Merge develop into infrahub-develop
Merge 'stable' into 'develop' with resolved conflicts
Merge develop into infrahub-develop
Signed-off-by: Fatih Acar <fatih@opsmill.com>
Allow recursive convertion to InfrahubNode objects
@wvandeun wvandeun self-assigned this Dec 1, 2025
@wvandeun wvandeun requested a review from ogenstad December 1, 2025 16:18
@coderabbitai
Copy link

coderabbitai bot commented Dec 1, 2025

Walkthrough

This pull request performs a comprehensive modernization of the Python SDK and CLI tooling. Major changes include: (1) replacing Poetry with UV as the package manager across CI/CD workflows, configuration files, and documentation; (2) converting pyproject.toml from Poetry format to PEP 621 standard with Hatch as the build backend; (3) modernizing Python type hints to use PEP 604 union syntax (X | None instead of Optional[X]), requiring Python 3.10+ and removing Python 3.9 support; (4) adding new get_diff_tree query and retrieval methods to the client API along with branch report functionality in infrahubctl; (5) removing the is_visible property from attributes and updating related constants; (6) refactoring membership checks to use set literals instead of lists, and adding explicit UTF-8 encoding to file operations. Documentation and development guidance are updated to reflect the UV tooling shift.

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 51.69% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Prep release v1.16.0' directly and clearly summarizes the main change—preparing a new release version. It is concise, specific, and accurately reflects the comprehensive nature of the changeset.

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.

@github-actions github-actions bot added group/ci Issue related to the CI pipeline type/documentation Improvements or additions to documentation labels Dec 1, 2025
@cloudflare-workers-and-pages
Copy link

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

Deploying infrahub-sdk-python with  Cloudflare Pages  Cloudflare Pages

Latest commit: 4952028
Status: ✅  Deploy successful!
Preview URL: https://1c52bb3e.infrahub-sdk-python.pages.dev
Branch Preview URL: https://wvd-20251201-release-1-16.infrahub-sdk-python.pages.dev

View logs

@codecov
Copy link

codecov bot commented Dec 1, 2025

Codecov Report

❌ Patch coverage is 82.55319% with 41 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
infrahub_sdk/ctl/branch.py 84.44% 11 Missing and 3 partials ⚠️
infrahub_sdk/client.py 86.27% 3 Missing and 4 partials ⚠️
infrahub_sdk/node/node.py 66.66% 3 Missing and 1 partial ⚠️
infrahub_sdk/object_store.py 0.00% 4 Missing ⚠️
infrahub_sdk/transfer/importer/json.py 0.00% 3 Missing ⚠️
infrahub_sdk/ctl/graphql.py 0.00% 2 Missing ⚠️
infrahub_sdk/query_groups.py 0.00% 2 Missing ⚠️
infrahub_sdk/ctl/importer.py 0.00% 1 Missing ⚠️
infrahub_sdk/operation.py 0.00% 0 Missing and 1 partial ⚠️
...frahub_sdk/pytest_plugin/items/jinja2_transform.py 0.00% 1 Missing ⚠️
... and 2 more
@@            Coverage Diff             @@
##           stable     #671      +/-   ##
==========================================
+ Coverage   75.48%   75.80%   +0.32%     
==========================================
  Files         113      113              
  Lines        9512     9660     +148     
  Branches     1893     1473     -420     
==========================================
+ Hits         7180     7323     +143     
- Misses       1832     1841       +9     
+ Partials      500      496       -4     
Flag Coverage Δ
integration-tests 34.53% <18.29%> (-0.37%) ⬇️
python-3.10 49.56% <64.68%> (+0.79%) ⬆️
python-3.11 49.54% <64.68%> (+0.77%) ⬆️
python-3.12 49.54% <64.68%> (+0.77%) ⬆️
python-3.13 49.54% <64.68%> (+0.77%) ⬆️
python-3.9 ?
python-filler-3.12 24.10% <18.29%> (-0.19%) ⬇️

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

Files with missing lines Coverage Δ
infrahub_sdk/async_typer.py 100.00% <100.00%> (ø)
infrahub_sdk/batch.py 94.52% <100.00%> (ø)
infrahub_sdk/config.py 90.15% <100.00%> (ø)
infrahub_sdk/ctl/check.py 26.44% <100.00%> (ø)
infrahub_sdk/ctl/cli.py 66.66% <ø> (ø)
infrahub_sdk/ctl/cli_commands.py 71.08% <100.00%> (+0.11%) ⬆️
infrahub_sdk/ctl/generator.py 50.90% <100.00%> (ø)
infrahub_sdk/ctl/repository.py 69.82% <ø> (-0.26%) ⬇️
infrahub_sdk/ctl/task.py 100.00% <ø> (ø)
infrahub_sdk/ctl/utils.py 68.53% <100.00%> (ø)
... and 30 more

... and 5 files with indirect coverage changes

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

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
infrahub_sdk/batch.py (1)

4-19: Align BatchTask.task type signature with BatchTaskSync and actual usage

BatchTask.task is typed as Callable[[Any], Awaitable[Any]], but it's invoked as task.task(*task.args, **task.kwargs) where args is tuple[Any, ...]. The sync counterpart BatchTaskSync correctly uses Callable[..., Any]. With mypy's disallow_untyped_defs = true enabled for this module, the current annotation will fail type checking.

Update BatchTask.task to:

 @dataclass
 class BatchTask:
-    task: Callable[[Any], Awaitable[Any]]
+    task: Callable[..., Awaitable[Any]]
     args: tuple[Any, ...]
     kwargs: dict[str, Any]
     node: Any | None = None

This aligns the async variant with its sync counterpart and correctly reflects how the callable is invoked.

infrahub_sdk/async_typer.py (1)

5-28: Parameterize Callable in maybe_run_async for mypy strict compatibility

With disallow_untyped_defs = true enabled, unparameterized Callable on line 14 will trigger mypy errors.

Update to:

-    def maybe_run_async(decorator: Callable, func: Callable) -> Any:
+    def maybe_run_async(decorator: Callable[..., Any], func: Callable[..., Any]) -> Any:

This preserves runtime behavior and satisfies mypy's type parameter requirements.

infrahub_sdk/ctl/check.py (1)

218-223: Malformed JSON string when format_json=True and no checks are found

The line:

print('{"level": "WARNING", "message": "message", ""No check found"}')

produces invalid JSON (there’s an extra ""No check found" fragment without a key/value pair), which will break consumers expecting parseable output.

Consider correcting it to a single well‑formed message, e.g.:

-        else:
-            print('{"level": "WARNING", "message": "message", ""No check found"}')
+        else:
+            print('{"level": "WARNING", "message": "No check found"}')

This isn’t introduced by this PR but is worth fixing before relying on --format-json in automation.

.github/workflows/ci.yml (1)

45-305: UV-based CI wiring is coherent; standardize checkout versions

The dependency-groups (lint, tests, dev) and extras (all, ctl) in pyproject.toml align with the uv commands in the workflow:

  • python-lint uses uv sync --group lint (ruff, mypy, yamllint)
  • documentation, validate-generated-documentation, unit-tests, and integration-tests-latest-infrahub use uv sync --all-groups --all-extras (broader scope)

Minor inconsistency: python-lint uses actions/checkout@v5 (line 79) while all other jobs use @v6. Standardize on v6 for consistency.

🧹 Nitpick comments (16)
infrahub_sdk/transfer/importer/json.py (1)

65-65: Consider using strict=True for data integrity.

Since both columns come from the same PyArrow table, they should have identical lengths. Using strict=True would catch data corruption issues early rather than silently truncating to the shorter sequence.

Apply this diff:

-            for graphql_data, kind in zip(table.column("graphql_json"), table.column("kind"), strict=False):
+            for graphql_data, kind in zip(table.column("graphql_json"), table.column("kind"), strict=True):
infrahub_sdk/spec/range_expansion.py (1)

59-59: Improve type hint specificity for mypy strict mode.

The re.Pattern type parameter should be specified as re.Pattern[str] for strict type checking compatibility.

-def _extract_constants(pattern: str, re_compiled: re.Pattern) -> tuple[list[int], list[list[str]]]:
+def _extract_constants(pattern: str, re_compiled: re.Pattern[str]) -> tuple[list[int], list[list[str]]]:
tests/fixtures/integration/test_infrahubctl/tags_transform/tags_transform.py (1)

8-8: Good addition of return type annotation.

The dict[str, str] return type correctly reflects the function's output. For complete type coverage, consider also annotating the data parameter.

Apply this diff to add the parameter annotation:

-    async def transform(self, data) -> dict[str, str]:
+    async def transform(self, data: dict) -> dict[str, str]:

Note: The exact type of data depends on the base class contract. If a more specific type is available from InfrahubTransform, use that instead of the generic dict.

infrahub_sdk/ctl/task.py (1)

70-83: Limit/offset union hints look good; consider aligning state annotation with its default

The switch to int | None for limit and offset is correct and matches Typer’s None default and the client.task.filter signature, so no behavioral change here.

One small consistency tweak you might want to do while you’re here: state is annotated as list[str] but has a None default and is passed into _parse_states(states: list[str] | None). With strict mypy this can be noisy; aligning the annotation would be cleaner:

-    state: list[str] = typer.Option(
+    state: list[str] | None = typer.Option(
         None, "--state", "-s", help="Filter by task state. Can be provided multiple times."
     ),
infrahub_sdk/config.py (1)

161-204: Config typing tweaks look good; config guidelines appear satisfied

  • Narrowing the type ignore on logger to # type: ignore[return-value] is a nice improvement: it keeps the documented intent (“we let self.log be treated as InfrahubLoggers despite structlog quirks”) while not masking other potential issues on that property.
  • Changing for field in Config.model_fields: to iterate the mapping directly is equivalent to iterating .keys() and keeps the clone() behavior intact.

Also, for this module specifically:

  • ConfigBase.model_config uses env_prefix="INFRAHUB_", and
  • validate_proxy_config() enforces that proxy and proxy_mounts (backed by INFRAHUB_PROXY_MOUNTS_HTTP/HTTPS) are mutually exclusive,

which aligns with the provided configuration guidelines.

If you ever want to guarantee that logger is never None at runtime, you might consider either:

  • making log non-optional and defaulting it to a concrete logger, or
  • having logger raise if self.log is unset, rather than returning None.

For now, the current behavior is consistent with the existing comments and use case.

infrahub_sdk/template/__init__.py (1)

4-34: Callable import switch is fine; consider parameterizing filter callables

Switching Callable to come from collections.abc is consistent with modern typing style and doesn’t affect runtime behavior.

If you’re running mypy in strict mode, you may want to be explicit about the callable shape for filters:

-from collections.abc import Callable
+from collections.abc import Callable
@@
-        filters: dict[str, Callable] | None = None,
+        filters: dict[str, Callable[..., Any]] | None = None,

This keeps the current flexibility (any callable is allowed) while avoiding potential “missing type parameters for generic type Callable” warnings.

If you adopt this, please re-run mypy to ensure there are no remaining unsubscripted-Callable instances that strict mode complains about.

infrahub_sdk/spec/object.py (1)

233-233: Avoid creating an unnecessary list in any().

The any([...]) call creates a list unnecessarily. Use a generator expression or direct boolean operators instead.

Apply this diff:

-            if not any([element in data, element in context]):
+            if element not in data and element not in context:

Alternatively, if you prefer the any() approach, use a generator:

-            if not any([element in data, element in context]):
+            if not any((element in data, element in context)):
infrahub_sdk/query_groups.py (1)

171-171: Consider using a set for unused_member_ids for better performance.

The code converts a set difference to a list, but unused_member_ids is only used for membership checks (if member.id in self.unused_member_ids on lines 111 and 205). Sets are more efficient for membership tests.

Consider updating the type hint on line 22 and removing the list() conversion:

-        self.unused_member_ids: list[str] | None = None
+        self.unused_member_ids: set[str] | None = None

And on lines 171 and 265:

-        self.unused_member_ids = list(set(existing_group.members.peer_ids) - set(members))
+        self.unused_member_ids = set(existing_group.members.peer_ids) - set(members)

Also applies to: 265-265

CLAUDE.md (1)

167-177: Update pyproject.toml description to remove Poetry reference

The code quality and CI bullets correctly reflect Ruff 0.14.5 and Python 3.10–3.13, but the pyproject.toml entry still refers to “Poetry dependencies,” which is now misleading with the uv/Hatch setup.

Consider neutral wording like:

-- **pyproject.toml**: Poetry dependencies, tool configurations (ruff, mypy, pytest)
+- **pyproject.toml**: Project dependencies and tool configurations (ruff, mypy, pytest)

Also applies to: 183-187

infrahub_sdk/ctl/cli_commands.py (1)

9-12: PEP 604 type hints and Callable import are consistent with CLI utilities

Switching branch/variables/concurrent to str | None / list[str] | None and importing Callable from collections.abc aligns these commands with parse_cli_vars and the project-wide typing style; no functional changes and this should play well with strict mypy.

If you want to finish the cleanup while you’re here, you could also make run’s branch annotation str | None to match the other commands and its default None.

Also applies to: 77-102, 107-126, 131-146, 250-262, 300-312

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

2-3: temp_dir fixture typing clarified; optionally tighten Generator type

Annotating temp_dir as returning a Generator[str] makes its intent clearer and is sufficient for most tooling.

If you want to be maximally explicit for strict type checkers, you could refine it to:

-from collections.abc import Generator
+from collections.abc import Generator
...
-@pytest.fixture
-def temp_dir() -> Generator[str]:
+@pytest.fixture
+def temp_dir() -> Generator[str, None, None]:

Also applies to: 13-17

infrahub_sdk/diff.py (1)

144-204: LGTM - Query builder for GetDiffTree.

The get_diff_tree_query() function properly constructs the GraphQL query using the Query class. The node structure mirrors the existing raw string in get_diff_summary_query() but is now programmatically built, enabling better maintainability and type-safe variable handling.

Consider consolidating get_diff_summary_query() (lines 52-88) to also use the Query class pattern for consistency, since both queries share the same node_structure. This would reduce duplication and improve maintainability.

# Example: Extract shared node structure
_NODE_STRUCTURE = {
    "uuid": None,
    "kind": None,
    # ... rest of structure
}

def get_diff_summary_query() -> Query:
    return Query(
        name="GetDiffSummary",
        query={"DiffTree": {"@filters": {...}, "nodes": _NODE_STRUCTURE}},
        variables={"branch_name": str, "name": str | None, ...},
    )
infrahub_sdk/ctl/graphql.py (1)

77-182: UTF‑8 write for schema looks good; consider aligning result‑type writes

  • Explicit encoding="utf-8" in export_schema is a solid improvement, and the query: Path | None defaulting to Path.cwd() is clean and matches the help text.
  • Iterating for file_name in package_generator._result_types_files is equivalent to .keys() and fine.

You might also want to make generate_result_types consistent by writing the generated modules with an explicit encoding as well:

-        file_path.write_text(code)
+        file_path.write_text(code, encoding="utf-8")
tests/conftest.py (1)

3-42: Fixture Generator annotations are fine; you can tighten generics if desired

The new Generator annotations improve typing without changing behavior. If you want fully precise types (and to help static checkers), you could spell out all three generic parameters:

-from collections.abc import Generator
+from collections.abc import Generator

-@pytest.fixture(scope="session")
-def event_loop() -> Generator[asyncio.AbstractEventLoop]:
+@pytest.fixture(scope="session")
+def event_loop() -> Generator[asyncio.AbstractEventLoop, None, None]:
@@
-@pytest.fixture(scope="session", autouse=True)
-def clean_env_vars() -> Generator:
+@pytest.fixture(scope="session", autouse=True)
+def clean_env_vars() -> Generator[None, None, None]:

This is optional and not required for correctness.

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

2416-2625: Deep-nesting _process_relationships test exercises both async and sync paths well

The new test_process_relationships_recursive_deep_nesting correctly:

  • Sets up a 3-level graph (Device → Interfaces → IP Addresses) and a matching schema cache for both clients.
  • Verifies that recursive=False only yields the two interfaces, while recursive=True yields the interfaces plus all three IP address nodes, for both InfrahubNode and InfrahubNodeSync.

If you ever find this pattern useful elsewhere, you could factor the nested data/schema construction into a fixture to reduce duplication, but as-is the test is clear and targeted.

infrahub_sdk/ctl/branch.py (1)

163-163: Consider handling the case where no default branch exists.

Using next() is more Pythonic than list indexing, but if no default branch is found, it will raise StopIteration which may be confusing. Consider providing a sentinel or explicit error:

-    default_branch = next(branch for branch in branches.values() if branch.is_default)
+    default_branch = next((branch for branch in branches.values() if branch.is_default), None)
+    if default_branch is None:
+        console.print("[red]No default branch found!")
+        return

Alternatively, if a default branch is always guaranteed to exist, this is acceptable as-is.

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 085e87b and 4952028.

⛔ Files ignored due to path filters (2)
  • poetry.lock is excluded by !**/*.lock
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (76)
  • .github/file-filters.yml (2 hunks)
  • .github/workflows/ci.yml (8 hunks)
  • .github/workflows/define-versions.yml (1 hunks)
  • .github/workflows/publish-pypi.yml (1 hunks)
  • .github/workflows/release.yml (2 hunks)
  • .gitignore (1 hunks)
  • CHANGELOG.md (1 hunks)
  • CLAUDE.md (4 hunks)
  • README.md (1 hunks)
  • docs/docs/infrahubctl/infrahubctl-branch.mdx (2 hunks)
  • docs/docs/python-sdk/guides/client.mdx (1 hunks)
  • infrahub_sdk/async_typer.py (1 hunks)
  • infrahub_sdk/batch.py (1 hunks)
  • infrahub_sdk/client.py (11 hunks)
  • infrahub_sdk/config.py (2 hunks)
  • infrahub_sdk/ctl/branch.py (4 hunks)
  • infrahub_sdk/ctl/check.py (2 hunks)
  • infrahub_sdk/ctl/cli.py (1 hunks)
  • infrahub_sdk/ctl/cli_commands.py (6 hunks)
  • infrahub_sdk/ctl/generator.py (2 hunks)
  • infrahub_sdk/ctl/graphql.py (2 hunks)
  • infrahub_sdk/ctl/importer.py (2 hunks)
  • infrahub_sdk/ctl/repository.py (3 hunks)
  • infrahub_sdk/ctl/task.py (1 hunks)
  • infrahub_sdk/ctl/utils.py (3 hunks)
  • infrahub_sdk/ctl/validate.py (1 hunks)
  • infrahub_sdk/diff.py (3 hunks)
  • infrahub_sdk/graphql/constants.py (1 hunks)
  • infrahub_sdk/graphql/renderers.py (2 hunks)
  • infrahub_sdk/node/attribute.py (4 hunks)
  • infrahub_sdk/node/constants.py (1 hunks)
  • infrahub_sdk/node/node.py (8 hunks)
  • infrahub_sdk/node/related_node.py (1 hunks)
  • infrahub_sdk/node/relationship.py (1 hunks)
  • infrahub_sdk/object_store.py (4 hunks)
  • infrahub_sdk/operation.py (1 hunks)
  • infrahub_sdk/protocols_base.py (0 hunks)
  • infrahub_sdk/protocols_generator/generator.py (1 hunks)
  • infrahub_sdk/pytest_plugin/items/jinja2_transform.py (1 hunks)
  • infrahub_sdk/pytest_plugin/models.py (1 hunks)
  • infrahub_sdk/pytest_plugin/plugin.py (1 hunks)
  • infrahub_sdk/query_groups.py (2 hunks)
  • infrahub_sdk/schema/__init__.py (5 hunks)
  • infrahub_sdk/schema/main.py (1 hunks)
  • infrahub_sdk/schema/repository.py (2 hunks)
  • infrahub_sdk/spec/object.py (2 hunks)
  • infrahub_sdk/spec/range_expansion.py (1 hunks)
  • infrahub_sdk/template/__init__.py (1 hunks)
  • infrahub_sdk/transfer/importer/json.py (3 hunks)
  • infrahub_sdk/types.py (2 hunks)
  • infrahub_sdk/utils.py (2 hunks)
  • pyproject.toml (4 hunks)
  • tasks.py (1 hunks)
  • tests/__init__.py (1 hunks)
  • tests/conftest.py (3 hunks)
  • tests/fixtures/integration/test_infrahubctl/tags_transform/tags_transform.py (1 hunks)
  • tests/helpers/fixtures.py (1 hunks)
  • tests/integration/conftest.py (1 hunks)
  • tests/integration/test_infrahub_client.py (4 hunks)
  • tests/unit/__init__.py (1 hunks)
  • tests/unit/ctl/conftest.py (2 hunks)
  • tests/unit/ctl/test_branch_report.py (1 hunks)
  • tests/unit/ctl/test_render_app.py (1 hunks)
  • tests/unit/ctl/test_repository_app.py (1 hunks)
  • tests/unit/ctl/test_transform_app.py (2 hunks)
  • tests/unit/sdk/checks/test_checks.py (3 hunks)
  • tests/unit/sdk/conftest.py (48 hunks)
  • tests/unit/sdk/graphql/conftest.py (6 hunks)
  • tests/unit/sdk/graphql/test_plugin.py (2 hunks)
  • tests/unit/sdk/test_batch.py (1 hunks)
  • tests/unit/sdk/test_diff_summary.py (2 hunks)
  • tests/unit/sdk/test_node.py (36 hunks)
  • tests/unit/sdk/test_repository.py (2 hunks)
  • tests/unit/sdk/test_schema.py (1 hunks)
  • tests/unit/sdk/test_template.py (1 hunks)
  • tests/unit/sdk/test_yaml.py (1 hunks)
💤 Files with no reviewable changes (1)
  • infrahub_sdk/protocols_base.py
🧰 Additional context used
📓 Path-based instructions (11)
**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.py: All async operations must have corresponding sync implementations following the dual implementation pattern
Use mypy with strict configuration for type checking in Python files

Files:

  • tests/helpers/fixtures.py
  • tests/unit/ctl/test_transform_app.py
  • tests/integration/conftest.py
  • infrahub_sdk/node/relationship.py
  • infrahub_sdk/pytest_plugin/models.py
  • infrahub_sdk/ctl/cli.py
  • infrahub_sdk/query_groups.py
  • tests/unit/ctl/test_render_app.py
  • infrahub_sdk/object_store.py
  • infrahub_sdk/utils.py
  • tasks.py
  • infrahub_sdk/ctl/check.py
  • infrahub_sdk/schema/repository.py
  • tests/unit/sdk/test_schema.py
  • infrahub_sdk/node/constants.py
  • tests/unit/ctl/test_branch_report.py
  • tests/unit/__init__.py
  • tests/unit/ctl/test_repository_app.py
  • infrahub_sdk/batch.py
  • tests/unit/sdk/checks/test_checks.py
  • tests/__init__.py
  • infrahub_sdk/ctl/utils.py
  • tests/unit/sdk/test_diff_summary.py
  • tests/unit/sdk/test_yaml.py
  • tests/unit/sdk/test_template.py
  • infrahub_sdk/ctl/generator.py
  • infrahub_sdk/node/attribute.py
  • infrahub_sdk/ctl/importer.py
  • infrahub_sdk/template/__init__.py
  • infrahub_sdk/spec/range_expansion.py
  • infrahub_sdk/diff.py
  • tests/unit/sdk/test_node.py
  • tests/unit/sdk/test_batch.py
  • infrahub_sdk/node/node.py
  • infrahub_sdk/ctl/graphql.py
  • infrahub_sdk/async_typer.py
  • infrahub_sdk/operation.py
  • tests/integration/test_infrahub_client.py
  • infrahub_sdk/ctl/cli_commands.py
  • tests/conftest.py
  • infrahub_sdk/ctl/branch.py
  • infrahub_sdk/protocols_generator/generator.py
  • infrahub_sdk/client.py
  • tests/unit/sdk/test_repository.py
  • infrahub_sdk/ctl/task.py
  • infrahub_sdk/graphql/constants.py
  • tests/unit/ctl/conftest.py
  • tests/fixtures/integration/test_infrahubctl/tags_transform/tags_transform.py
  • infrahub_sdk/types.py
  • infrahub_sdk/graphql/renderers.py
  • infrahub_sdk/schema/main.py
  • infrahub_sdk/node/related_node.py
  • infrahub_sdk/pytest_plugin/items/jinja2_transform.py
  • infrahub_sdk/config.py
  • infrahub_sdk/schema/__init__.py
  • infrahub_sdk/spec/object.py
  • tests/unit/sdk/graphql/test_plugin.py
  • infrahub_sdk/ctl/validate.py
  • infrahub_sdk/pytest_plugin/plugin.py
  • infrahub_sdk/transfer/importer/json.py
  • tests/unit/sdk/conftest.py
  • infrahub_sdk/ctl/repository.py
  • tests/unit/sdk/graphql/conftest.py
tests/unit/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Place unit tests in tests/unit/ directory for testing individual components in isolation

Files:

  • tests/unit/ctl/test_transform_app.py
  • tests/unit/ctl/test_render_app.py
  • tests/unit/sdk/test_schema.py
  • tests/unit/ctl/test_branch_report.py
  • tests/unit/__init__.py
  • tests/unit/ctl/test_repository_app.py
  • tests/unit/sdk/checks/test_checks.py
  • tests/unit/sdk/test_diff_summary.py
  • tests/unit/sdk/test_yaml.py
  • tests/unit/sdk/test_template.py
  • tests/unit/sdk/test_node.py
  • tests/unit/sdk/test_batch.py
  • tests/unit/sdk/test_repository.py
  • tests/unit/ctl/conftest.py
  • tests/unit/sdk/graphql/test_plugin.py
  • tests/unit/sdk/conftest.py
  • tests/unit/sdk/graphql/conftest.py
**/ctl/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use Typer framework for building CLI commands in the infrahubctl CLI

Files:

  • tests/unit/ctl/test_transform_app.py
  • infrahub_sdk/ctl/cli.py
  • tests/unit/ctl/test_render_app.py
  • infrahub_sdk/ctl/check.py
  • tests/unit/ctl/test_branch_report.py
  • tests/unit/ctl/test_repository_app.py
  • infrahub_sdk/ctl/utils.py
  • infrahub_sdk/ctl/generator.py
  • infrahub_sdk/ctl/importer.py
  • infrahub_sdk/ctl/graphql.py
  • infrahub_sdk/ctl/cli_commands.py
  • infrahub_sdk/ctl/branch.py
  • infrahub_sdk/ctl/task.py
  • tests/unit/ctl/conftest.py
  • infrahub_sdk/ctl/validate.py
  • infrahub_sdk/ctl/repository.py
**/*.md

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.md: Use markdownlint for documentation consistency
Use Vale for documentation style checking
Follow markdown style as defined in .markdownlint.yaml configuration

Files:

  • README.md
  • CHANGELOG.md
  • CLAUDE.md
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CLAUDE.md)

docs/**/*.{md,mdx}: Follow Diataxis framework for documentation structure: Tutorials (learning-oriented), How-to guides (task-oriented), Explanation (understanding-oriented), and Reference (information-oriented)
Use professional but approachable tone with plain language and technical precision in documentation
Use concise and direct documentation with short, active sentences and minimal fluff
Maintain informative documentation focused on explaining how and why rather than marketing
Follow consistent documentation structure patterns across documents
Define new terms when first introduced in documentation
Use domain-relevant terminology from the user perspective (playbooks, branches, schemas, commits) in documentation
Maintain consistency with Infrahub's data model and UI naming conventions in documentation
Use proper language tags for all code blocks in documentation
Include both async and sync code examples using Tabs component where applicable
Provide realistic code examples that reflect real-world complexity in documentation
Use callouts for warnings, tips, and important notes in documentation

Files:

  • docs/docs/infrahubctl/infrahubctl-branch.mdx
  • docs/docs/python-sdk/guides/client.mdx
tests/integration/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Place integration tests in tests/integration/ directory for testing against real Infrahub instances

Files:

  • tests/integration/conftest.py
  • tests/integration/test_infrahub_client.py
**/node/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/node/*.py: Implement lazy loading for node attributes and relationships to load on demand
Support batch operations for bulk create/update/delete operations on nodes
Include built-in data validation with GraphQL query generation for nodes

Files:

  • infrahub_sdk/node/relationship.py
  • infrahub_sdk/node/constants.py
  • infrahub_sdk/node/attribute.py
  • infrahub_sdk/node/node.py
  • infrahub_sdk/node/related_node.py
**/node/relationship.py

📄 CodeRabbit inference engine (CLAUDE.md)

Implement automatic handling of node relationships with add/remove/replace operations

Files:

  • infrahub_sdk/node/relationship.py
**/check*.py

📄 CodeRabbit inference engine (CLAUDE.md)

In Checks implementation, use the validate() method, NOT check() when implementing InfrahubCheck

Files:

  • infrahub_sdk/ctl/check.py
**/client.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/client.py: Use InfrahubClient (async) and InfrahubClientSync (sync) with identical interfaces following the Dual Client Pattern
Use HTTPX-based transport with proxy support (single proxy or HTTP/HTTPS mounts) and API token/JWT authentication with automatic refresh

Files:

  • infrahub_sdk/client.py
**/config.py

📄 CodeRabbit inference engine (CLAUDE.md)

**/config.py: Use Pydantic-based Config class with environment variable support for configuration management
Use environment variables prefixed with INFRAHUB_ for configuration
Ensure mutual exclusivity validation between proxy configuration methods (INFRAHUB_PROXY vs INFRAHUB_PROXY_MOUNTS_HTTP/INFRAHUB_PROXY_MOUNTS_HTTPS)

Files:

  • infrahub_sdk/config.py
🧠 Learnings (20)
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Use `poetry install --with dev --all-extras` to install dependencies in development environment

Applied to files:

  • README.md
  • CLAUDE.md
📚 Learning: 2025-11-25T13:29:23.062Z
Learnt from: wvandeun
Repo: opsmill/infrahub-sdk-python PR: 637
File: infrahub_sdk/ctl/branch.py:290-290
Timestamp: 2025-11-25T13:29:23.062Z
Learning: In infrahub_sdk/ctl/branch.py, the report command uses pc.created_by.updated_at to display "Created at" for proposed changes as a workaround because the SDK doesn't have easy access to the creation time of the proposed change. This will be replaced with proper object-level metadata implementation in version 1.7 of Infrahub.

Applied to files:

  • docs/docs/infrahubctl/infrahubctl-branch.mdx
  • CHANGELOG.md
  • tests/unit/ctl/test_branch_report.py
  • infrahub_sdk/ctl/branch.py
  • infrahub_sdk/node/related_node.py
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Applies to **/node/relationship.py : Implement automatic handling of node relationships with add/remove/replace operations

Applied to files:

  • infrahub_sdk/node/relationship.py
  • tests/unit/sdk/test_node.py
  • infrahub_sdk/node/node.py
  • infrahub_sdk/operation.py
  • infrahub_sdk/node/related_node.py
  • infrahub_sdk/transfer/importer/json.py
📚 Learning: 2025-11-25T13:23:15.190Z
Learnt from: wvandeun
Repo: opsmill/infrahub-sdk-python PR: 637
File: infrahub_sdk/operation.py:74-76
Timestamp: 2025-11-25T13:23:15.190Z
Learning: In infrahub_sdk/operation.py, the recursive=True parameter in _process_relationships is a temporary workaround to access Proposed Changes data. This will be replaced with proper object-level metadata implementation in version 1.7.

Applied to files:

  • infrahub_sdk/node/relationship.py
  • tests/unit/sdk/test_node.py
  • infrahub_sdk/node/node.py
  • infrahub_sdk/operation.py
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Applies to **/ctl/**/*.py : Use Typer framework for building CLI commands in the infrahubctl CLI

Applied to files:

  • infrahub_sdk/ctl/cli.py
  • tasks.py
  • infrahub_sdk/ctl/cli_commands.py
  • infrahub_sdk/ctl/branch.py
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Validate documentation accuracy against the latest Infrahub version

Applied to files:

  • CHANGELOG.md
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Applies to **/client.py : Use `InfrahubClient` (async) and `InfrahubClientSync` (sync) with identical interfaces following the Dual Client Pattern

Applied to files:

  • docs/docs/python-sdk/guides/client.mdx
  • infrahub_sdk/schema/repository.py
  • tests/unit/ctl/test_repository_app.py
  • tests/unit/sdk/checks/test_checks.py
  • tests/unit/sdk/test_diff_summary.py
  • infrahub_sdk/ctl/branch.py
  • infrahub_sdk/client.py
  • infrahub_sdk/schema/__init__.py
  • tests/unit/sdk/conftest.py
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Applies to **/config.py : Use environment variables prefixed with `INFRAHUB_` for configuration

Applied to files:

  • docs/docs/python-sdk/guides/client.mdx
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Generate documentation with `poetry run invoke docs`

Applied to files:

  • tasks.py
  • .github/workflows/ci.yml
  • CLAUDE.md
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Run linting with `poetry run invoke lint` (ruff + mypy + yamllint + markdownlint) to ensure code quality

Applied to files:

  • .github/workflows/ci.yml
  • CLAUDE.md
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Use Ruff (0.11.0) for comprehensive linting and formatting

Applied to files:

  • .github/workflows/ci.yml
  • pyproject.toml
  • CLAUDE.md
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Validate documentation with `poetry run invoke docs-validate`

Applied to files:

  • .github/workflows/ci.yml
  • CLAUDE.md
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Run `poetry run invoke format` to format code before committing

Applied to files:

  • .github/workflows/ci.yml
  • CLAUDE.md
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Run unit tests with `poetry run pytest --cov infrahub_sdk tests/unit/` to ensure code coverage

Applied to files:

  • .github/workflows/ci.yml
  • pyproject.toml
  • tests/unit/sdk/checks/test_checks.py
  • CLAUDE.md
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Maintain code coverage through codecov integration in testing

Applied to files:

  • .github/workflows/ci.yml
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Applies to tests/integration/**/*.py : Place integration tests in `tests/integration/` directory for testing against real Infrahub instances

Applied to files:

  • tests/unit/sdk/checks/test_checks.py
  • CLAUDE.md
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Applies to **/node/*.py : Include built-in data validation with GraphQL query generation for nodes

Applied to files:

  • infrahub_sdk/diff.py
  • infrahub_sdk/ctl/graphql.py
  • infrahub_sdk/ctl/validate.py
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Run integration tests with `poetry run pytest tests/integration/`

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Use Docusaurus-based documentation system with auto-generation for CLI docs and config reference

Applied to files:

  • CLAUDE.md
📚 Learning: 2025-11-25T07:18:58.155Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T07:18:58.155Z
Learning: Applies to **/*.md : Use markdownlint for documentation consistency

Applied to files:

  • CLAUDE.md
🧬 Code graph analysis (16)
infrahub_sdk/query_groups.py (1)
infrahub_sdk/node/relationship.py (1)
  • peer_ids (44-45)
tasks.py (1)
infrahub_sdk/ctl/cli_commands.py (1)
  • run (131-181)
tests/unit/ctl/test_repository_app.py (1)
infrahub_sdk/client.py (1)
  • InfrahubClient (318-1744)
tests/unit/sdk/checks/test_checks.py (1)
infrahub_sdk/ctl/cli_commands.py (1)
  • check (79-102)
tests/unit/sdk/test_diff_summary.py (3)
infrahub_sdk/client.py (3)
  • InfrahubClient (318-1744)
  • get_diff_tree (1285-1339)
  • get_diff_tree (2579-2633)
infrahub_sdk/diff.py (1)
  • get_diff_tree_query (144-204)
tests/unit/sdk/conftest.py (2)
  • clients (42-46)
  • BothClients (25-28)
tests/unit/sdk/test_yaml.py (1)
infrahub_sdk/yaml.py (1)
  • load_content (43-58)
infrahub_sdk/diff.py (1)
infrahub_sdk/graphql/query.py (1)
  • Query (31-43)
tests/unit/sdk/test_node.py (3)
tests/unit/sdk/conftest.py (3)
  • BothClients (25-28)
  • client (32-33)
  • clients (42-46)
infrahub_sdk/node/node.py (5)
  • InfrahubNode (458-1108)
  • from_graphql (486-500)
  • from_graphql (1139-1153)
  • _process_relationships (892-945)
  • _process_relationships (1539-1592)
infrahub_sdk/node/related_node.py (1)
  • id (83-86)
infrahub_sdk/operation.py (1)
infrahub_sdk/node/node.py (4)
  • from_graphql (486-500)
  • from_graphql (1139-1153)
  • _process_relationships (892-945)
  • _process_relationships (1539-1592)
tests/integration/test_infrahub_client.py (1)
tests/unit/sdk/conftest.py (1)
  • client (32-33)
infrahub_sdk/ctl/cli_commands.py (3)
infrahub_sdk/testing/repository.py (1)
  • path (57-58)
infrahub_sdk/types.py (1)
  • debug (49-50)
infrahub_sdk/analyzer.py (1)
  • variables (72-99)
infrahub_sdk/ctl/branch.py (4)
infrahub_sdk/branch.py (3)
  • BranchData (25-35)
  • get (205-215)
  • get (245-255)
infrahub_sdk/diff.py (1)
  • DiffTreeData (39-49)
infrahub_sdk/protocols.py (1)
  • CoreProposedChange (491-505)
infrahub_sdk/utils.py (1)
  • decode_json (94-98)
infrahub_sdk/client.py (1)
infrahub_sdk/diff.py (5)
  • DiffTreeData (39-49)
  • NodeDiff (11-17)
  • diff_tree_node_to_node_diff (91-141)
  • get_diff_summary_query (52-88)
  • get_diff_tree_query (144-204)
tests/fixtures/integration/test_infrahubctl/tags_transform/tags_transform.py (2)
infrahub_sdk/ctl/cli_commands.py (1)
  • transform (302-360)
infrahub_sdk/yaml.py (1)
  • data (147-150)
infrahub_sdk/ctl/validate.py (1)
infrahub_sdk/analyzer.py (1)
  • variables (72-99)
infrahub_sdk/transfer/importer/json.py (3)
infrahub_sdk/node/related_node.py (1)
  • kind (123-126)
infrahub_sdk/schema/main.py (1)
  • kind (279-280)
infrahub_sdk/yaml.py (1)
  • kind (157-158)
⏰ 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). (4)
  • GitHub Check: unit-tests (3.12)
  • GitHub Check: unit-tests (3.13)
  • GitHub Check: unit-tests (3.10)
  • GitHub Check: unit-tests (3.11)


## Prerequisites

- Python 3.9 or higher
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Update Python version requirement to reflect PR changes.

Line 19 states "Python 3.9 or higher," but according to the PR objectives, Python 3.9 support is being removed and the SDK now requires Python 3.10+. This prerequisite needs to be updated to match the modernization goals of this release.

- Python 3.9 or higher
+ Python 3.10 or higher
📝 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
- Python 3.9 or higher
- Python 3.10 or higher
🤖 Prompt for AI Agents
In docs/docs/python-sdk/guides/client.mdx around line 19, the prerequisite
currently reads "Python 3.9 or higher" but the PR removes 3.9 support; update
this line to require "Python 3.10 or higher" (or equivalent phrasing used across
the docs) and run a quick grep to ensure all other occurrences of "3.9" are
updated to "3.10" for consistency.

Comment on lines +30 to +42
def format_timestamp(timestamp: str) -> str:
"""Format ISO timestamp to 'YYYY-MM-DD HH:MM:SS'.
Args:
timestamp (str): ISO fromatted timestamp
Returns:
(str): the datetime as string formatted as 'YYYY-MM-DD HH:MM:SS'
Raises:
Any execptions returned from formatting the timestamp are propogated to the caller
"""
dt = datetime.fromisoformat(timestamp.replace("Z", "+00:00"))
return dt.strftime("%Y-%m-%d %H:%M:%S")
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

Minor typos in docstring.

The docstring contains a few typos:

  • Line 33: "fromatted" → "formatted"
  • Line 39: "execptions" → "exceptions", "propogated" → "propagated"
 def format_timestamp(timestamp: str) -> str:
-    """Format ISO timestamp to 'YYYY-MM-DD HH:MM:SS'.
+    """Format ISO timestamp to 'YYYY-MM-DD HH:MM:SS'.
     Args:
-        timestamp (str): ISO fromatted timestamp
+        timestamp (str): ISO formatted timestamp
 
     Returns:
         (str): the datetime as string formatted as 'YYYY-MM-DD HH:MM:SS'
 
     Raises:
-        Any execptions returned from formatting the timestamp are propogated to the caller
+        Any exceptions returned from formatting the timestamp are propagated to the caller
     """
🤖 Prompt for AI Agents
In infrahub_sdk/ctl/branch.py around lines 30 to 42, the function docstring has
a few typos: change "fromatted" to "formatted" in the Args description, change
"execptions" to "exceptions" and "propogated" to "propagated" in the Raises
section; update the wording if needed to keep grammar consistent (e.g., "ISO
formatted timestamp" and "Any exceptions returned from formatting the timestamp
are propagated to the caller").

Comment on lines +78 to +90
async def test_check_git_files_changed_empty_response(httpx_mock: HTTPXMock) -> None:
response = {}

httpx_mock.add_response(
method="GET",
url="http://mock/api/diff/files?branch=test-branch",
json=response,
)

"""Test check_git_files_changed returns False when branch not in response."""
client = InfrahubClient(config=Config(address="http://mock"))
result = await check_git_files_changed(client, branch="test-branch")
assert result is False
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

Move docstring to the beginning of the function.

The docstring on line 87 is incorrectly placed after code execution has started. Docstrings should be the first statement in a function.

Apply this diff to fix the docstring placement:

 async def test_check_git_files_changed_empty_response(httpx_mock: HTTPXMock) -> None:
+    """Test check_git_files_changed returns False when branch not in response."""
     response = {}
 
     httpx_mock.add_response(
         method="GET",
         url="http://mock/api/diff/files?branch=test-branch",
         json=response,
     )
 
-    """Test check_git_files_changed returns False when branch not in response."""
     client = InfrahubClient(config=Config(address="http://mock"))
📝 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
async def test_check_git_files_changed_empty_response(httpx_mock: HTTPXMock) -> None:
response = {}
httpx_mock.add_response(
method="GET",
url="http://mock/api/diff/files?branch=test-branch",
json=response,
)
"""Test check_git_files_changed returns False when branch not in response."""
client = InfrahubClient(config=Config(address="http://mock"))
result = await check_git_files_changed(client, branch="test-branch")
assert result is False
async def test_check_git_files_changed_empty_response(httpx_mock: HTTPXMock) -> None:
"""Test check_git_files_changed returns False when branch not in response."""
response = {}
httpx_mock.add_response(
method="GET",
url="http://mock/api/diff/files?branch=test-branch",
json=response,
)
client = InfrahubClient(config=Config(address="http://mock"))
result = await check_git_files_changed(client, branch="test-branch")
assert result is False
🤖 Prompt for AI Agents
tests/unit/ctl/test_branch_report.py around lines 78 to 90: the function has a
docstring placed after test setup and execution; move the docstring to be the
first statement inside the async test function (i.e., immediately after the def
line) so it documents the test properly and does not execute after code,
ensuring the test setup (httpx_mock, response, client creation, call and
assertion) follows the docstring.

@wvandeun wvandeun merged commit d51e287 into stable Dec 1, 2025
19 checks passed
@wvandeun wvandeun deleted the wvd-20251201-release-1.16 branch December 1, 2025 19:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

group/ci Issue related to the CI pipeline type/documentation Improvements or additions to documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants