Conversation
Adds `infrahubctl schema export` to fetch user-defined schemas from an Infrahub server and write them as YAML files (one per namespace). Restricted namespaces (Core, Builtin, Internal, etc.) and auto-generated types (ProfileSchemaAPI, TemplateSchemaAPI) are excluded by default. RESTRICTED_NAMESPACES is mirrored from the Infrahub server constants so the server can later consume it from the SDK. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Remind agents to run `invoke generate-sdk generate-infrahubctl` after changing CLI commands or SDK config so generated docs stay in sync. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
WalkthroughThe changes introduce a schema export capability to the Infrahub CLI. A new constant RESTRICTED_NAMESPACES is added to define server-reserved namespace names. The InfrahubClientMode enum is expanded with a TRACKING mode. A new export CLI command is implemented in the schema management module to export user-defined schemas as YAML files organized by namespace, excluding certain restricted namespaces and internal fields. Corresponding unit tests are added to validate export behavior including namespace filtering and directory handling. Additionally, documentation is updated to include a guideline for running a generation command after CLI or SDK config modifications. 🚥 Pre-merge checks | ❌ 3❌ Failed checks (3 warnings)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. 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. Comment |
Deploying infrahub-sdk-python with
|
| Latest commit: |
45ecc8f
|
| Status: | ✅ Deploy successful! |
| Preview URL: | https://4070a110.infrahub-sdk-python.pages.dev |
| Branch Preview URL: | https://bkr-agents-regenerate-docs.infrahub-sdk-python.pages.dev |
Codecov Report❌ Patch coverage is
@@ Coverage Diff @@
## stable #837 +/- ##
==========================================
+ Coverage 80.36% 80.38% +0.02%
==========================================
Files 115 115
Lines 9875 9926 +51
Branches 1504 1515 +11
==========================================
+ Hits 7936 7979 +43
- Misses 1417 1423 +6
- Partials 522 524 +2
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 1 file with indirect coverage changes 🚀 New features to boost your workflow:
|
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (3)
infrahub_sdk/ctl/schema.py (1)
227-247:model_dump()serializes attributes/relationships that are immediately overwritten.Line 229 dumps the entire schema (including
attributesandrelationshipsas plain dicts), but lines 231–245 immediately overwrite both keys with re-processed lists from the original Pydantic objects. Adding"attributes"and"relationships"to the top-level exclude set makes the intent clearer and avoids wasted serialization.Also, wrapping
model_dump()indict()on lines 232 and 240 is redundant —model_dump()already returns adict.♻️ Suggested cleanup
-_SCHEMA_EXPORT_EXCLUDE: set[str] = {"hash", "hierarchy", "used_by", "id", "state"} +_SCHEMA_EXPORT_EXCLUDE: set[str] = {"hash", "hierarchy", "used_by", "id", "state", "attributes", "relationships"} _FIELD_EXPORT_EXCLUDE: set[str] = {"inherited", "read_only", "allow_override", "hierarchical", "id", "state"} def _schema_to_export_dict(schema: NodeSchemaAPI | GenericSchemaAPI) -> dict[str, Any]: """Convert an API schema object to an export-ready dict (omits API-internal fields).""" data = schema.model_dump(exclude=_SCHEMA_EXPORT_EXCLUDE, exclude_none=True) data["attributes"] = [ - dict(attr.model_dump(exclude=_FIELD_EXPORT_EXCLUDE, exclude_none=True)) + attr.model_dump(exclude=_FIELD_EXPORT_EXCLUDE, exclude_none=True) for attr in schema.attributes if not attr.inherited ] if not data["attributes"]: data.pop("attributes") data["relationships"] = [ - dict(rel.model_dump(exclude=_FIELD_EXPORT_EXCLUDE, exclude_none=True)) + rel.model_dump(exclude=_FIELD_EXPORT_EXCLUDE, exclude_none=True) for rel in schema.relationships if not rel.inherited ] if not data["relationships"]: data.pop("relationships") return data🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@infrahub_sdk/ctl/schema.py` around lines 227 - 247, In _schema_to_export_dict, avoid serializing attributes/relationships twice by adding "attributes" and "relationships" to the exclude set used in schema.model_dump (referencing _SCHEMA_EXPORT_EXCLUDE) so model_dump doesn't include those keys, and remove the redundant dict(...) wrappers around attr.model_dump and rel.model_dump (they already return dicts); keep the subsequent list comprehensions that build attributes and relationships using _FIELD_EXPORT_EXCLUDE and the inherited check.infrahub_sdk/constants.py (1)
3-19: Dual-source-of-truth risk is acknowledged but worth tracking.The comment correctly notes the duplication with the server's constants. Until the server consumes this SDK list, any namespace added server-side must also be added here. Consider adding a link to the server file or a CI check to detect drift.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@infrahub_sdk/constants.py` around lines 3 - 19, The RESTRICTED_NAMESPACES list is duplicated from the server and risks drifting; add a clear comment above RESTRICTED_NAMESPACES that includes a link to the authoritative server file (backend/infrahub/core/constants/__init__.py) and add or reference a CI check that compares this SDK list against the server source (or fails the build when they differ) so maintainers are alerted to changes on the server; mention the symbol name RESTRICTED_NAMESPACES in the comment so it’s obvious what is guarded.tests/unit/ctl/test_schema_export.py (1)
161-181: Consider consolidating near-duplicate restricted-namespace tests.
test_schema_export_excludes_restricted_namespacesandtest_schema_export_no_user_schemaexercise the same code path (all nodes in restricted namespaces → early exit with warning). They differ only in node names. You could parametrize them or keep just one, freeing space for an edge-case test (e.g., a mix of restricted and user namespaces verifying that only user namespaces are exported).Also applies to: 225-245
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@tests/unit/ctl/test_schema_export.py` around lines 161 - 181, Consolidate the two near-duplicate tests test_schema_export_excludes_restricted_namespaces and test_schema_export_no_user_schema by either parameterizing the test with different node lists or removing one and adding an edge-case test; update the pytest test (the function(s) calling runner.invoke(app=app, args=["export", "--directory", ...]) and using remove_ansi_color(result.stdout)) so it accepts multiple inputs (e.g., parametrize node sets like ["Core","Builtin","Internal"] and another variant) or replace one with a mixed-namespace case to verify only user namespaces are exported—adjust the HTTPX mock response setup (_schema_response/_make_node) and assertions accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@infrahub_sdk/ctl/schema.py`:
- Around line 250-258: The callable default _default_export_directory()
currently returns a str which prevents Typer/Click from converting it to a Path
for the export() option; update _default_export_directory() so it returns a
pathlib.Path instance (not a str) so that the directory parameter in
export(directory: Path...) is a Path when the default is used, ensuring
directory.mkdir() and directory / "..." operations work correctly.
---
Nitpick comments:
In `@infrahub_sdk/constants.py`:
- Around line 3-19: The RESTRICTED_NAMESPACES list is duplicated from the server
and risks drifting; add a clear comment above RESTRICTED_NAMESPACES that
includes a link to the authoritative server file
(backend/infrahub/core/constants/__init__.py) and add or reference a CI check
that compares this SDK list against the server source (or fails the build when
they differ) so maintainers are alerted to changes on the server; mention the
symbol name RESTRICTED_NAMESPACES in the comment so it’s obvious what is
guarded.
In `@infrahub_sdk/ctl/schema.py`:
- Around line 227-247: In _schema_to_export_dict, avoid serializing
attributes/relationships twice by adding "attributes" and "relationships" to the
exclude set used in schema.model_dump (referencing _SCHEMA_EXPORT_EXCLUDE) so
model_dump doesn't include those keys, and remove the redundant dict(...)
wrappers around attr.model_dump and rel.model_dump (they already return dicts);
keep the subsequent list comprehensions that build attributes and relationships
using _FIELD_EXPORT_EXCLUDE and the inherited check.
In `@tests/unit/ctl/test_schema_export.py`:
- Around line 161-181: Consolidate the two near-duplicate tests
test_schema_export_excludes_restricted_namespaces and
test_schema_export_no_user_schema by either parameterizing the test with
different node lists or removing one and adding an edge-case test; update the
pytest test (the function(s) calling runner.invoke(app=app, args=["export",
"--directory", ...]) and using remove_ansi_color(result.stdout)) so it accepts
multiple inputs (e.g., parametrize node sets like ["Core","Builtin","Internal"]
and another variant) or replace one with a mixed-namespace case to verify only
user namespaces are exported—adjust the HTTPX mock response setup
(_schema_response/_make_node) and assertions accordingly.
|
It looks like you accidently included "Add infrahubctl schema export command" in this PR |
Summary by CodeRabbit
Release Notes
New Features
Documentation
invoke generate-sdk generate-infrahubctlafter changing CLI commands or SDK config so generated docs stay in sync