v1.22.0
1.22.0 - 2026-06-23
Added
- Added
query_nameparameter toall(),filters(),count()andget()methods inInfrahubClientandInfrahubClientSyncto be used as meaningful GraphQL operation name for observability (#923) - Add
infrahubctl graphql query-reportto analyze a GraphQL query and report whether it targets unique nodes, which controls whether Infrahub limits artifact regeneration to changed nodes or regenerates all artifacts on any relevant node change. Supports--onlineto fetch the query from the server by name. - Added
OrderByEntryand anOrder.byfield so query results can be ordered by attributes, related-node attributes, or node metadata, e.g.Order(by=[OrderByEntry(field="name__value", direction=OrderDirection.DESC)]). TheOrder.node_metadatafield is deprecated; usebywith thenode_metadata__created_at/node_metadata__updated_atfields instead. - Added graph traversal support for Infrahub 1.10:
InfrahubClient.traverse_paths()(shortest path(s) between two nodes),InfrahubClient.reachable_nodes()(nodes of given kinds reachable from a source), andInfrahubClient.path_exists()(boolean convenience for checks) — all with sync equivalents. Source and destination accept either a node id or anInfrahubNode; kind filters accept kind strings or protocol classes; eachPathNodein the result exposes.fetch()to resolve the full node (store-backed). Calling these against a pre-1.10 server raises a clearVersionNotSupportedError.
Fixed
-
Calling
.save(allow_upsert=True)on a node whose human-friendly identifier contains a CoreNumberPool-sourced attribute now raises a clearValidationErrorinstead of crashing with an opaque backend error. (#339) -
RelatedNode,RelatedNodeSync,RelationshipManagerandRelationshipManagerSyncare now generic over their peer type, andinfrahubctl protocolsparameterises generated relationships accordingly (e.g.device: RelatedNode[NetworkDevice],interfaces: RelationshipManager[NetworkInterface]).Traversing a relationship via
.peer,.peersor indexing now preserves the peer's type instead of collapsing to the dynamicInfrahubNode, so chains such asdevice.rack.peer.name.valuetype-check under mypy/ty without casts. Existing un-parameterisedRelatedNode/RelationshipManagerusage is unaffected — the peer type defaults toInfrahubNode/InfrahubNodeSync, preserving current behaviour. (#1063) (#1063) -
Cardinality-one relationships in generated protocols are now typed with a
RelationshipAttribute[...]descriptor. It still reads back as a typedRelatedNode[Peer](so.peerkeeps the peer type), but it accepts assignment of an id string, an HFID, a peer node, orNone— mirroring the runtimeInfrahubNode.__setattr__, which wraps the assigned value in aRelatedNode.Previously relationships were typed read-only as
RelatedNode, so the documented way of setting a relationship (node.rel = "<id>"ornode.rel = peer_node) failed under mypy/ty with anassignmenterror. The descriptor only appears in generated protocols and is never instantiated at runtime.Because the new typing lives in the generated protocols, existing projects must regenerate them with
infrahubctl protocolsto pick up the change — it does not take effect for already-generated protocol files. (#1064) (#1064) -
Calling
.save(allow_upsert=True)on a node hydrated byfrom_graphqlno longer silently clears optional one-cardinality relationships that the GraphQL response didn't fetch. Explicitly assigningnode.rel = Nonestill clears the relationship. (#1080) -
Send the GraphQL operation name as
operationNamein the request payload so tracing and observability tools can identify each query.