Skip to content

Conversation

@ogenstad
Copy link
Contributor

@ogenstad ogenstad commented Dec 2, 2025

Summary by CodeRabbit

  • New Features

    • Added branch report command to infrahubctl for cleanup status reports with diff summaries.
    • Added get_diff_tree method to retrieve complete diff trees with metadata.
  • Changed

    • Improved recursive lookups in nested relationship conversions.
    • Dropped Python 3.9 support; now requires Python 3.10+.
    • Switched from Poetry to uv for package/dependency management.
  • Removed

    • Removed is_visible property from Infrahub.

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

petercrocker and others added 30 commits November 10, 2025 22:33
Merge develop into infrahub-develop
Merge develop into infrahub-develop
Merge develop into infrahub-develop
Merge develop into infrahub-develop
Allow recursive convertion to InfrahubNode objects
Upgrade uv action version and pin Python version for test matrix
…1118

Prefer `next(iter())` over single element slice
Clear out test restrictions for Python 3.9
…-develop-20251118

Update ruleset for shadowing builtins
Use specific rule codes when using noqa
…51118

Use a `set` literal when testing for membership
…ub-develop-20251118

Fix return annotations and changes for early returns
@coderabbitai
Copy link

coderabbitai bot commented Dec 2, 2025

Walkthrough

This pull request performs a comprehensive modernization of the Infrahub SDK project. It upgrades GitHub Actions workflows to newer versions (checkout@v6, setup-python@v6, setup-uv@v7), standardizes Python type annotations to use PEP 604 union syntax (X | None instead of Optional[X]), and updates the project to require Python 3.10+ while dropping 3.9 support. The release introduces new features including a get_diff_tree client method and a branch report CLI command, along with associated diff tree query structures. Dependencies are updated, including a migration to UV for package management and Ruff version upgrades. Throughout the codebase, minor consistency improvements are applied, such as replacing list membership checks with set literals and using explicit UTF-8 encoding for file operations.

Pre-merge checks

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 52.33% 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 PR title accurately describes the main purpose of merging the stable branch into develop with conflict resolution.

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 2, 2025
@cloudflare-workers-and-pages
Copy link

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

Deploying infrahub-sdk-python with  Cloudflare Pages  Cloudflare Pages

Latest commit: 17cf122
Status: ✅  Deploy successful!
Preview URL: https://1b4d101c.infrahub-sdk-python.pages.dev
Branch Preview URL: https://pog-stable-to-develop-202512.infrahub-sdk-python.pages.dev

View logs

@codecov
Copy link

codecov bot commented Dec 2, 2025

Codecov Report

❌ Patch coverage is 82.47863% 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             @@
##           develop     #674      +/-   ##
===========================================
+ Coverage    75.57%   75.80%   +0.22%     
===========================================
  Files          113      113              
  Lines         9508     9660     +152     
  Branches      1447     1473      +26     
===========================================
+ Hits          7186     7323     +137     
- Misses        1835     1841       +6     
- Partials       487      496       +9     
Flag Coverage Δ
integration-tests 34.53% <17.94%> (-0.43%) ⬇️
python-3.10 49.54% <64.52%> (+0.68%) ⬆️
python-3.11 49.54% <64.52%> (+0.68%) ⬆️
python-3.12 49.54% <64.52%> (+0.70%) ⬆️
python-3.13 49.54% <64.52%> (+0.68%) ⬆️
python-3.9 ?
python-filler-3.12 24.10% <18.37%> (-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_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%> (ø)
infrahub_sdk/ctl/validate.py 52.11% <ø> (-0.67%) ⬇️
... and 28 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ogenstad ogenstad marked this pull request as ready for review December 2, 2025 08:10
@ogenstad ogenstad requested a review from a team December 2, 2025 08:10
@ogenstad ogenstad merged commit 1e2a513 into develop Dec 2, 2025
19 of 20 checks passed
@ogenstad ogenstad deleted the pog-stable-to-develop-20251202 branch December 2, 2025 08:12
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: 4

Caution

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

⚠️ Outside diff range comments (1)
infrahub_sdk/ctl/branch.py (1)

185-185: Bug: Wrong variable used for has_schema_changes.

This line incorrectly uses default_branch.has_schema_changes instead of branch.has_schema_changes. This causes all non-default branches to display the default branch's schema change status.

             branch.description or " - ",
             branch.origin_branch,
             f"{branch.branched_from} ({calculate_time_diff(branch.branched_from)})",
             "[green]True" if branch.sync_with_git else "[#FF7F50]False",
-            "[green]True" if default_branch.has_schema_changes else "[#FF7F50]False",
+            "[green]True" if branch.has_schema_changes else "[#FF7F50]False",
             "[green]True" if branch.is_default else "[#FF7F50]False",
             branch.status,
         )
♻️ Duplicate comments (2)
.github/workflows/labels.yml (1)

20-20: LGTM, pending verification from publish-pypi.yml.

This upgrade aligns with the broader workflow modernization. The compatibility verification requested for the publish-pypi.yml workflow applies here as well.

.github/workflows/release.yml (1)

24-24: LGTM, pending verification from publish-pypi.yml.

This upgrade aligns with the broader workflow modernization. The compatibility verification requested for the publish-pypi.yml workflow applies here as well.

🧹 Nitpick comments (13)
tests/unit/__init__.py (1)

5-5: Narrowed type ignore is appropriate; global helper pattern OK for tests

Using # type: ignore[attr-defined] here is a good tightening of the mypy suppression and matches the actual issue (builtins lacking rprint). The global assignment into builtins is acceptable for a small test convenience, though if this ever grows complex you might consider moving it into a pytest fixture instead to better control scope.

tests/fixtures/integration/test_infrahubctl/tags_transform/tags_transform.py (1)

8-13: LGTM! Return type annotation is accurate.

The return type annotation -> dict[str, str] correctly reflects the method's return value and aligns with the modernization effort to use Python 3.10+ type syntax.

For consistency, consider adding a type annotation to the data parameter as well:

-    async def transform(self, data) -> dict[str, str]:
+    async def transform(self, data: dict) -> dict[str, str]:
tests/unit/sdk/checks/test_checks.py (1)

34-36: Explicit root_directory override is well covered

Instantiating IFCheckWithName with root_directory=str(tmp_path) and asserting on check.root_directory exercises the override path and matches the CLI’s string-based path parameter. Looks good; no further changes needed.

infrahub_sdk/config.py (2)

170-176: Logger property change is fine; consider using cast instead of type: ignore

Narrowing the ignore to # type: ignore[return-value] keeps the existing runtime behavior while making the intent clearer to type checkers, which looks good given the structlog workaround.

If you want to avoid a type: ignore entirely, you could instead use an explicit cast:

-from infrahub_sdk.types import AsyncRequester, InfrahubLoggers, RequesterTransport, SyncRequester
+from infrahub_sdk.types import AsyncRequester, InfrahubLoggers, RequesterTransport, SyncRequester
+from typing import cast
@@
     @property
     def logger(self) -> InfrahubLoggers:
@@
-        return self.log  # type: ignore[return-value]
+        return cast(InfrahubLoggers, self.log)

That keeps the same assumptions while keeping static typing stricter.


187-203: Clone behavior unchanged; consider minor robustness/perf tweaks

Iterating over Config.model_fields instead of Config.model_fields.keys() is equivalent in Python (iteration yields keys), so clone behavior is preserved.

If you ever expect subclasses or want slightly better membership performance, you could:

  • Use the instance’s class to include subclass fields.
  • Use a set for covered_keys:
-        covered_keys = list(config.keys())
-        for field in Config.model_fields:
+        covered_keys = set(config.keys())
+        for field in type(self).model_fields:
             if field not in covered_keys:
                 config[field] = deepcopy(getattr(self, field))

This is non-essential but makes clone more future-proof if Config is subclassed and avoids repeated list scans.

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

65-145: Type-aware annotation helper fixtures are well-structured; consider caching reverse map

The new Callable/Mapping-based type hints on the async/sync annotation helper fixtures make their contracts explicit and easier to use in tests. As an optional tweak, you could precompute the reverse replacements dict for replace_sync_return_annotation once (e.g., in the outer fixture scope) instead of on every call, though the current cost is negligible in tests.

infrahub_sdk/template/__init__.py (1)

4-6: Callable import is fine; consider tightening the filter type annotation

Using collections.abc.Callable here is correct and consistent with the rest of the PR; no runtime behavior change. You could optionally make the filter type more explicit for static checkers:

-        filters: dict[str, Callable] | None = None,
+        filters: dict[str, Callable[..., Any]] | None = None,

This reflects that Jinja filters are callables with arbitrary arguments returning any value, while keeping the runtime identical.

Also applies to: 29-34

infrahub_sdk/batch.py (1)

4-8: collections.abc imports are appropriate; minor typing polish possible

Bringing AsyncGenerator, Awaitable, Callable, and Generator in from collections.abc and leaving Any/TYPE_CHECKING in typing is a clean, modern typing refactor with no runtime impact. The async/sync batch pair (InfrahubBatch / InfrahubBatchSync) already follows the dual operation pattern consistently. Based on learnings, this aligns well with the project’s async/sync design.

If you want to tighten types further (optional), you could parameterize the async generator return type to mirror the sync side, e.g.:

-    async def execute(self) -> AsyncGenerator:
+    async def execute(self) -> AsyncGenerator[tuple[InfrahubNode | None, Any], None]:

This keeps behavior unchanged while giving type-checkers more precise information about what InfrahubBatch.execute yields. (typeerror.org)

Also applies to: 73-89, 102-112

infrahub_sdk/ctl/graphql.py (1)

77-88: Consider specifying encoding for generated result type files as well

In generate_result_types, file_path.write_text(code) will use the platform default encoding, while other paths (e.g., export_schema) now explicitly use UTF‑8. For consistency and portability, consider:

-        file_path.write_text(code)
+        file_path.write_text(code, encoding="utf-8")
infrahub_sdk/node/attribute.py (1)

4-5: Attribute init normalization and typing import updates look good

Using Callable from collections.abc and normalizing data via if not isinstance(data, dict) or "value" not in data: plus consistent data.get(...) assignments keeps behavior intact while simplifying the logic. If you ever expect falsey-but-meaningful values for _value (e.g. 0 or ""), consider tightening the mapper guard to if self._value is not None:; otherwise this is fine as-is.

Also applies to: 29-57

tests/unit/ctl/test_transform_app.py (1)

7-40: Fixture Generator annotation is fine; optional tightening for strict type checkers

Using collections.abc.Generator[str] for tags_transform_dir matches the yield+teardown pattern and is functionally correct. If you run stricter type checking (e.g. mypy/pyright), you might prefer Generator[str, None, None] or Iterator[str] to model the fixture’s send/return types explicitly, but that’s purely optional.

pyproject.toml (1)

224-233: Review expanded flake8-builtins ignorelist.

The ignorelist now includes several common Python builtins: filter, format, input, list, and property. While id is commonly shadowed in database contexts, the other additions warrant review:

  • Shadowing filter, format, input, list can reduce code clarity
  • Shadowing property in class definitions could be particularly problematic

Consider verifying that these shadowing cases are intentional and necessary:

#!/bin/bash
# Find usages of these as variable/parameter names in the codebase
echo "Searching for builtin shadowing instances..."

for builtin in filter format input list property; do
  echo -e "\n=== Checking '$builtin' ==="
  # Look for function parameters, variable assignments, or class attributes
  rg -n --type py "\b$builtin\s*[=:]" --glob 'infrahub_sdk/**/*.py' -C 2 | head -30
done
tests/unit/ctl/test_branch_report.py (1)

205-211: Missing type annotation for fixture parameter.

For consistency with other test functions, add the type annotation for the mock_branch_report_default_branch parameter.

-def test_branch_report_command_main_branch(mock_branch_report_default_branch) -> None:
+def test_branch_report_command_main_branch(mock_branch_report_default_branch: HTTPXMock) -> None:
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 5093a3f and 17cf122.

⛔ Files ignored due to path filters (1)
  • uv.lock is excluded by !**/*.lock
📒 Files selected for processing (75)
  • .github/workflows/ci.yml (12 hunks)
  • .github/workflows/labels.yml (1 hunks)
  • .github/workflows/publish-pypi.yml (1 hunks)
  • .github/workflows/release.yml (1 hunks)
  • .github/workflows/repository-dispatch.yml (1 hunks)
  • .github/workflows/sync-docs.yml (1 hunks)
  • .github/workflows/update-submodule.yml (1 hunks)
  • CHANGELOG.md (1 hunks)
  • docs/_templates/sdk_template_reference.j2 (2 hunks)
  • docs/docs/infrahubctl/infrahubctl-branch.mdx (2 hunks)
  • docs/docs/python-sdk/reference/templating.mdx (2 hunks)
  • docs/docs/python-sdk/topics/object_file.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_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 (2 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_generator/generator.py (1 hunks)
  • infrahub_sdk/pytest_plugin/AGENTS.md (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)
  • 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 (47 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 (40 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)
🧰 Additional context used
📓 Path-based instructions (9)
docs/**/*.mdx

📄 CodeRabbit inference engine (CLAUDE.md)

Follow the Diataxis framework for documentation with four types: Tutorials (learning-oriented), How-to guides (task-oriented), Explanation (understanding-oriented), and Reference (information-oriented)

Files:

  • docs/docs/infrahubctl/infrahubctl-branch.mdx
  • docs/docs/python-sdk/reference/templating.mdx
  • docs/docs/python-sdk/topics/object_file.mdx
docs/**/*.{md,mdx}

📄 CodeRabbit inference engine (CLAUDE.md)

docs/**/*.{md,mdx}: Use professional but approachable tone, concise and direct language, and consistent document structure patterns following Diataxis categories in documentation
In documentation code examples: use proper language tags, include both async and sync examples using Tabs component where applicable, provide realistic examples, add validation steps, and use callouts for warnings and tips
Use domain-relevant Infrahub terminology (playbooks, branches, schemas, commits) consistently with Infrahub's data model and UI naming conventions in documentation
Validate documentation accuracy against the latest Infrahub version and follow markdown style as defined in .markdownlint.yaml and Vale styles

Files:

  • docs/docs/infrahubctl/infrahubctl-branch.mdx
  • docs/docs/python-sdk/reference/templating.mdx
  • docs/docs/python-sdk/topics/object_file.mdx
tests/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

tests/**/*.py: Use the custom pytest plugin (infrahub_sdk.pytest_plugin) providing fixtures for Infrahub clients, configuration, and support for testing checks, transforms, and queries
Organize unit tests in tests/unit/ for isolated component testing and integration tests in tests/integration/ for testing against real Infrahub instances

Files:

  • tests/unit/sdk/test_yaml.py
  • tests/unit/sdk/test_schema.py
  • tests/unit/ctl/conftest.py
  • tests/unit/ctl/test_repository_app.py
  • tests/unit/sdk/test_template.py
  • tests/unit/ctl/test_branch_report.py
  • tests/unit/sdk/test_batch.py
  • tests/fixtures/integration/test_infrahubctl/tags_transform/tags_transform.py
  • tests/unit/ctl/test_transform_app.py
  • tests/__init__.py
  • tests/unit/sdk/checks/test_checks.py
  • tests/unit/sdk/test_repository.py
  • tests/unit/sdk/test_node.py
  • tests/unit/ctl/test_render_app.py
  • tests/unit/sdk/test_diff_summary.py
  • tests/conftest.py
  • tests/integration/conftest.py
  • tests/integration/test_infrahub_client.py
  • tests/unit/sdk/graphql/test_plugin.py
  • tests/unit/sdk/graphql/conftest.py
  • tests/unit/__init__.py
  • tests/unit/sdk/conftest.py
  • tests/helpers/fixtures.py
infrahub_sdk/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

infrahub_sdk/**/*.py: Use InfrahubClient (async) and InfrahubClientSync (sync) providing identical interfaces following the dual client pattern
Implement all operations following the dual async/sync pattern where InfrahubClient provides async methods and InfrahubClientSync provides sync equivalents

Files:

  • infrahub_sdk/ctl/utils.py
  • infrahub_sdk/diff.py
  • infrahub_sdk/object_store.py
  • infrahub_sdk/query_groups.py
  • infrahub_sdk/utils.py
  • infrahub_sdk/node/related_node.py
  • infrahub_sdk/node/constants.py
  • infrahub_sdk/pytest_plugin/plugin.py
  • infrahub_sdk/ctl/check.py
  • infrahub_sdk/ctl/generator.py
  • infrahub_sdk/template/__init__.py
  • infrahub_sdk/operation.py
  • infrahub_sdk/graphql/constants.py
  • infrahub_sdk/transfer/importer/json.py
  • infrahub_sdk/pytest_plugin/models.py
  • infrahub_sdk/ctl/graphql.py
  • infrahub_sdk/batch.py
  • infrahub_sdk/node/attribute.py
  • infrahub_sdk/pytest_plugin/items/jinja2_transform.py
  • infrahub_sdk/ctl/branch.py
  • infrahub_sdk/ctl/importer.py
  • infrahub_sdk/schema/repository.py
  • infrahub_sdk/spec/range_expansion.py
  • infrahub_sdk/types.py
  • infrahub_sdk/graphql/renderers.py
  • infrahub_sdk/async_typer.py
  • infrahub_sdk/ctl/repository.py
  • infrahub_sdk/node/relationship.py
  • infrahub_sdk/config.py
  • infrahub_sdk/ctl/task.py
  • infrahub_sdk/ctl/cli_commands.py
  • infrahub_sdk/schema/__init__.py
  • infrahub_sdk/spec/object.py
  • infrahub_sdk/client.py
  • infrahub_sdk/schema/main.py
  • infrahub_sdk/protocols_generator/generator.py
  • infrahub_sdk/ctl/validate.py
  • infrahub_sdk/node/node.py
infrahub_sdk/ctl/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Implement CLI commands using Typer for schema management, transformations, checks, branch operations, and object management in infrahub_sdk/ctl/

Files:

  • infrahub_sdk/ctl/utils.py
  • infrahub_sdk/ctl/check.py
  • infrahub_sdk/ctl/generator.py
  • infrahub_sdk/ctl/graphql.py
  • infrahub_sdk/ctl/branch.py
  • infrahub_sdk/ctl/importer.py
  • infrahub_sdk/ctl/repository.py
  • infrahub_sdk/ctl/task.py
  • infrahub_sdk/ctl/cli_commands.py
  • infrahub_sdk/ctl/validate.py
infrahub_sdk/node/**/*.py

📄 CodeRabbit inference engine (CLAUDE.md)

Implement the Node system with lazy loading of attributes and relationships, supporting batch operations and automatic relationship handling

Files:

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

📄 CodeRabbit inference engine (CLAUDE.md)

Use validate() method (not check()) when implementing checks that inherit from InfrahubCheck

Files:

  • infrahub_sdk/ctl/check.py
infrahub_sdk/config.py

📄 CodeRabbit inference engine (CLAUDE.md)

infrahub_sdk/config.py: Use Pydantic-based Config class with environment variable support for configuration management
Configure environment variables with INFRAHUB_ prefix; use INFRAHUB_PROXY for single proxy or INFRAHUB_PROXY_MOUNTS_HTTP/INFRAHUB_PROXY_MOUNTS_HTTPS for separate proxies with mutual exclusivity validation

Files:

  • infrahub_sdk/config.py
infrahub_sdk/client.py

📄 CodeRabbit inference engine (CLAUDE.md)

Use HTTPX-based transport with proxy support (single proxy or HTTP/HTTPS mounts) and API token or JWT authentication with automatic refresh

Files:

  • infrahub_sdk/client.py
🧠 Learnings (13)
📚 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
  • tests/unit/ctl/test_branch_report.py
  • CHANGELOG.md
  • infrahub_sdk/ctl/branch.py
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Applies to docs/**/*.{md,mdx} : Use domain-relevant Infrahub terminology (playbooks, branches, schemas, commits) consistently with Infrahub's data model and UI naming conventions in documentation

Applied to files:

  • docs/docs/infrahubctl/infrahubctl-branch.mdx
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Applies to infrahub_sdk/ctl/**/*.py : Implement CLI commands using Typer for schema management, transformations, checks, branch operations, and object management in `infrahub_sdk/ctl/`

Applied to files:

  • infrahub_sdk/ctl/utils.py
  • infrahub_sdk/ctl/check.py
  • tests/unit/ctl/test_transform_app.py
  • pyproject.toml
  • infrahub_sdk/ctl/graphql.py
  • infrahub_sdk/ctl/branch.py
  • infrahub_sdk/schema/repository.py
  • infrahub_sdk/ctl/repository.py
  • infrahub_sdk/ctl/task.py
  • infrahub_sdk/ctl/cli_commands.py
  • infrahub_sdk/schema/__init__.py
  • infrahub_sdk/schema/main.py
  • infrahub_sdk/ctl/validate.py
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Applies to infrahub_sdk/**/*.py : Use `InfrahubClient` (async) and `InfrahubClientSync` (sync) providing identical interfaces following the dual client pattern

Applied to files:

  • tests/unit/ctl/test_repository_app.py
  • tests/unit/sdk/checks/test_checks.py
  • pyproject.toml
  • tests/unit/sdk/test_node.py
  • tests/unit/sdk/test_diff_summary.py
  • infrahub_sdk/ctl/branch.py
  • infrahub_sdk/schema/repository.py
  • infrahub_sdk/schema/__init__.py
  • tests/unit/sdk/conftest.py
  • infrahub_sdk/client.py
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Applies to tests/**/*.py : Use the custom pytest plugin (`infrahub_sdk.pytest_plugin`) providing fixtures for Infrahub clients, configuration, and support for testing checks, transforms, and queries

Applied to files:

  • tests/unit/ctl/test_repository_app.py
  • infrahub_sdk/pytest_plugin/plugin.py
  • tests/unit/sdk/checks/test_checks.py
  • tests/unit/sdk/test_diff_summary.py
  • tests/integration/test_infrahub_client.py
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Applies to infrahub_sdk/**/*.py : Implement all operations following the dual async/sync pattern where `InfrahubClient` provides async methods and `InfrahubClientSync` provides sync equivalents

Applied to files:

  • tests/unit/ctl/test_repository_app.py
  • infrahub_sdk/batch.py
  • tests/unit/sdk/test_node.py
  • tests/unit/sdk/test_diff_summary.py
  • infrahub_sdk/schema/repository.py
  • infrahub_sdk/schema/__init__.py
  • infrahub_sdk/client.py
  • infrahub_sdk/schema/main.py
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Applies to tests/**/*.py : Organize unit tests in `tests/unit/` for isolated component testing and integration tests in `tests/integration/` for testing against real Infrahub instances

Applied to files:

  • tests/unit/ctl/test_transform_app.py
  • tests/unit/sdk/checks/test_checks.py
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Use Ruff (0.14.5) for comprehensive linting and formatting, mypy for type checking with strict configuration, yamllint for YAML files, markdownlint for documentation consistency, and Vale for documentation style

Applied to files:

  • .github/workflows/ci.yml
  • pyproject.toml
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Run linting using `uv run invoke lint` which includes ruff, mypy, yamllint, and markdownlint

Applied to files:

  • .github/workflows/ci.yml
  • pyproject.toml
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Install dependencies using `uv sync --all-groups --all-extras`

Applied to files:

  • .github/workflows/ci.yml
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Run unit tests using `uv run pytest --cov infrahub_sdk tests/unit/`

Applied to files:

  • tests/unit/sdk/checks/test_checks.py
  • tests/unit/sdk/test_diff_summary.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/operation.py
  • tests/unit/sdk/test_node.py
  • infrahub_sdk/node/relationship.py
  • infrahub_sdk/node/node.py
📚 Learning: 2025-12-01T19:42:19.002Z
Learnt from: CR
Repo: opsmill/infrahub-sdk-python PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-12-01T19:42:19.002Z
Learning: Applies to infrahub_sdk/node/**/*.py : Implement the Node system with lazy loading of attributes and relationships, supporting batch operations and automatic relationship handling

Applied to files:

  • infrahub_sdk/operation.py
  • tests/unit/sdk/test_node.py
  • infrahub_sdk/node/relationship.py
  • infrahub_sdk/node/node.py
🧬 Code graph analysis (20)
infrahub_sdk/diff.py (1)
infrahub_sdk/graphql/query.py (1)
  • Query (31-43)
tests/unit/ctl/test_repository_app.py (1)
infrahub_sdk/client.py (1)
  • InfrahubClient (318-1744)
infrahub_sdk/query_groups.py (1)
infrahub_sdk/node/relationship.py (1)
  • peer_ids (44-45)
tests/unit/ctl/test_branch_report.py (1)
infrahub_sdk/ctl/branch.py (2)
  • check_git_files_changed (45-69)
  • format_timestamp (30-42)
infrahub_sdk/ctl/generator.py (1)
infrahub_sdk/analyzer.py (1)
  • variables (72-99)
tests/unit/sdk/checks/test_checks.py (1)
infrahub_sdk/ctl/cli_commands.py (1)
  • check (79-102)
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)
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)
infrahub_sdk/ctl/graphql.py (2)
infrahub_sdk/async_typer.py (1)
  • command (30-32)
infrahub_sdk/ctl/utils.py (1)
  • catch_exception (78-106)
infrahub_sdk/node/attribute.py (3)
infrahub_sdk/node/related_node.py (3)
  • id (83-86)
  • get (215-225)
  • get (262-272)
infrahub_sdk/schema/__init__.py (2)
  • get (251-279)
  • get (565-605)
infrahub_sdk/client.py (12)
  • get (389-405)
  • get (408-424)
  • get (427-443)
  • get (446-462)
  • get (465-481)
  • get (484-500)
  • get (502-560)
  • get (2254-2270)
  • get (2273-2289)
  • get (2292-2308)
  • get (2311-2327)
  • get (2330-2346)
tests/unit/sdk/test_node.py (2)
infrahub_sdk/node/node.py (6)
  • InfrahubNode (458-1108)
  • InfrahubNodeSync (1111-1755)
  • 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)
tests/unit/sdk/test_diff_summary.py (2)
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)
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 (2)
  • calculate_time_diff (355-378)
  • decode_json (94-98)
infrahub_sdk/schema/repository.py (1)
infrahub_sdk/node/node.py (2)
  • InfrahubNode (458-1108)
  • InfrahubNodeSync (1111-1755)
tests/integration/test_infrahub_client.py (2)
tests/unit/sdk/conftest.py (1)
  • client (32-33)
infrahub_sdk/client.py (1)
  • InfrahubClient (318-1744)
infrahub_sdk/schema/__init__.py (1)
infrahub_sdk/schema/main.py (6)
  • NodeSchema (307-309)
  • GenericSchema (283-285)
  • NodeSchemaAPI (312-314)
  • GenericSchemaAPI (288-292)
  • ProfileSchemaAPI (317-318)
  • TemplateSchemaAPI (321-322)
infrahub_sdk/spec/object.py (2)
tasks.py (1)
  • format (149-155)
infrahub_sdk/yaml.py (1)
  • data (147-150)
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)
infrahub_sdk/schema/main.py (1)
infrahub_sdk/node/node.py (2)
  • InfrahubNode (458-1108)
  • InfrahubNodeSync (1111-1755)
infrahub_sdk/ctl/validate.py (1)
infrahub_sdk/analyzer.py (1)
  • variables (72-99)
⏰ 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). (1)
  • GitHub Check: Cloudflare Pages

Comment on lines +49 to +50
- name: "Check out repository code"
uses: "actions/checkout@v6"
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

🧩 Analysis chain

🌐 Web query:

actions/checkout v6 breaking changes from v5 GitHub Actions

💡 Result:

Short summary of breaking changes from actions/checkout v5 → v6

  • persist-credentials behavior changed: credentials are no longer written directly into the checked-out repo’s .git/config; they are persisted to a file under $RUNNER_TEMP and referenced from .git/config. This is a security hardening to avoid accidental credential exfiltration. [1][2]

  • Minimum runner requirement for scenarios that read the persisted credentials from containerized actions: Actions Runner v2.329.0. (v5 required v2.327.1 for its node runtime change; v6’s new persist-credentials behavior is the primary compatibility change.) [1][3]

Notes: if your workflows (or custom scripts/docker builds) previously relied on the token being stored directly in the repo tree, update them to use the new persisted-credentials location or disable persist-credentials. [2]

Sources: [1] actions/checkout README (v6 notes), [2] GitHub Community discussion on v6 security changes, [3] v6 release notes summary.


Validate actions/checkout@v6 compatibility and update handling of persisted credentials.

There is a breaking change between v5 and v6: credential persistence behavior changed for security hardening. In v5, credentials are written directly to .git/config; in v6, they are persisted to a file under $RUNNER_TEMP and referenced from .git/config. If any custom scripts or Docker builds in this workflow (or dependent actions) access git credentials directly from the repository tree, they must be updated to use the new persisted-credentials location or explicitly set persist-credentials: false. Additionally, ensure the runner version is at least v2.329.0 to support the new persist-credentials behavior.

🤖 Prompt for AI Agents
.github/workflows/publish-pypi.yml lines 49-50: the workflow uses
actions/checkout@v6 which changed credential persistence; update the workflow to
either explicitly set persist-credentials: false on the checkout step if your
jobs/tools expect credentials in .git/config, or update any custom
scripts/Docker builds to read credentials from the new persisted-credentials
file under $RUNNER_TEMP; also ensure the GitHub-hosted runner is at least
v2.329.0 (or pin a compatible runner) so the new persist-credentials behavior
works correctly.

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 several typos: "fromatted" → "formatted", "execptions" → "exceptions", "propogated" → "propagated".

 def format_timestamp(timestamp: str) -> str:
     """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 docstring for
format_timestamp contains typos; update the text to correct "fromatted" →
"formatted", "execptions" → "exceptions", and "propogated" → "propagated", and
optionally fix minor grammar ("ISO fromatted timestamp" → "ISO-formatted
timestamp" and "Any execptions returned..." → "Any exceptions raised ...") so
the docstring is clear and typo-free.

Comment on lines +70 to +73
GRAPHQL_VARIABLE_TYPES = type[str | int | float | bool | datetime | None]


def render_variables_to_string(data: dict[str, GRAPHQL_VARIABLE_TYPES]) -> str:
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

Fix the type alias definition.

The GRAPHQL_VARIABLE_TYPES type alias appears to be incorrectly defined. type[str | int | float | bool | datetime | None] represents the type of a class (a metaclass), not instances of these types.

Apply this diff to fix the type alias:

-GRAPHQL_VARIABLE_TYPES = type[str | int | float | bool | datetime | None]
+GRAPHQL_VARIABLE_TYPES = str | int | float | bool | datetime | None

The function signature should also be updated:

-def render_variables_to_string(data: dict[str, GRAPHQL_VARIABLE_TYPES]) -> str:
+def render_variables_to_string(data: dict[str, type[GRAPHQL_VARIABLE_TYPES]]) -> str:

Or more clearly, if the intent is to map variable names to their types:

-def render_variables_to_string(data: dict[str, GRAPHQL_VARIABLE_TYPES]) -> str:
+def render_variables_to_string(data: dict[str, type[str] | type[int] | type[float] | type[bool] | type[datetime] | None]) -> str:

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In infrahub_sdk/graphql/renderers.py around lines 70-73, the
GRAPHQL_VARIABLE_TYPES alias is incorrectly defined using type[...], which
denotes a metaclass; replace it with a union of instance types (e.g. using
typing.Union or PEP 604 syntax) such as GRAPHQL_VARIABLE_TYPES = str | int |
float | bool | datetime | None, ensure typing imports if required, and update
the render_variables_to_string parameter annotation to use dict[str,
GRAPHQL_VARIABLE_TYPES] (or Dict[str, GRAPHQL_VARIABLE_TYPES]) accordingly so
the alias represents actual variable value types rather than types-of-types.

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

Docstring is misplaced after the mock setup.

The docstring appears after the httpx mock response setup, making it less effective as documentation. Move the docstring to the beginning of the function.

 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"))
🤖 Prompt for AI Agents
In tests/unit/ctl/test_branch_report.py around lines 78 to 90, the test-level
docstring is placed after the httpx mock setup; move the docstring to be the
first statement inside the async test function (immediately after the def line)
so it documents the test purpose correctly — remove the existing trailing
"""...""" and reinsert it at the top of the function as the first statement
(keeping the same text).

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.

6 participants