Skip to content

#8237 (IFC-2235): Update queries on node using HFID to reference relationships #8480

Merged
polmichel merged 6 commits intorelease-1.8from
pmi-20260225-display-labels-upsert
Mar 9, 2026
Merged

#8237 (IFC-2235): Update queries on node using HFID to reference relationships #8480
polmichel merged 6 commits intorelease-1.8from
pmi-20260225-display-labels-upsert

Conversation

@polmichel
Copy link
Copy Markdown
Contributor

@polmichel polmichel commented Feb 25, 2026

Why

Problem statement

Update queries recompute and provide incorrect values for computed attributes using related node attributes.
For example, after an update query on an object with the following schema:

version: "1.0"

nodes:
  - name: DeviceType
    namespace: Dcim
    description: A model of device
    label: Device Type
    icon: mdi:poll
    include_in_menu: true
    human_friendly_id:
      - name__value
    display_label: "{{ name__value }} (Manufacturer: {{ manufacturer__name__value }})"
    order_by:
      - manufacturer__name__value
      - name__value
    uniqueness_constraints:
      - [manufacturer, name__value]
    attributes:
      - name: name
        kind: Text
        unique: true
        order_weight: 1000
    relationships:
      - name: manufacturer
        peer: OrganizationManufacturer
        cardinality: one
        kind: Attribute
        order_weight: 1250
        optional: false

display_label will be evaluated as "name__value(None)", because {{ manufacturer__name__value }} evaluates to None.

This is due to the fact that infrahub.core.node.Node.resolve_relationships method does not retrieve the required attributes from the relationships when the node is not being created.
This display_label recompute is called in the infrahub.core.node.Node._update method due to a legitimate call to infrahub.core.node.node_property_attribute.NodePropertyAttribute.needs_update.

Closes #8237 / IFC-2235

What changed

Condition that queries additional attributes from the database when resolving the relationships in infrahub.core.node.Node.resolve_relationships.

Before this PR, this was only triggered during node creation.

After this PR, this will be called:

  • During node creation
  • During node update, if it has a display label or a hfid

How to test

uv run pytest -xvs backend/tests/component/graphql/test_mutation_upsert.py::test_upsert_preserves_relationship_display_label                                                                                 

Impact & rollout

  • Performance: We are querying additional attributes from relationships whenever a node is update if it has a display label or a HFID.

Checklist

  • Tests added/updated
  • Changelog entry added (uv run towncrier create ...)
  • Internal .md docs updated (internal knowledge and AI code tools knowledge)

Summary by CodeRabbit

  • Bug Fixes

    • Fixed display labels incorrectly showing 'None' for relationship-based fields after upsert operations.
  • Refactor

    • Streamlined relationship resolution to pre-collect related filters so related attributes are reliably loaded during updates, preserving display labels.
  • Documentation

    • Added guides on display labels, human-friendly identifiers, and GraphQL mutations; updated Python type-hint/import guidance.
  • Tests

    • Added test verifying display label preservation across successive upserts.

@github-actions github-actions Bot added the group/backend Issue related to the backend (API Server, Git Agent) label Feb 25, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Feb 25, 2026

Walkthrough

This PR fixes a bug where relationship-based display_label variables became None after upserts. It adds two Node helpers, _merge_relationship_fields() and _collect_extra_filters(), and refactors resolve_relationships() to pre-collect extra filters for relationship resolution. A component test ensures display_label is preserved across successive upserts. Documentation on display labels/HFIDs and GraphQL mutations and a Python typing guideline update were also added.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: updating queries on nodes using HFID to reference relationships correctly, which directly addresses issue #8237.
Description check ✅ Passed The description comprehensively covers all required sections: problem statement, goal, what changed, how to test, and impact assessment with completed checklist items.
Linked Issues check ✅ Passed The PR fully addresses issue #8237's core requirement: enabling relationship attribute loading during node updates (not just creation) when display_label or HFID are present, through new helper methods and refactored resolve_relationships logic.
Out of Scope Changes check ✅ Passed All changes are directly related to fixing the display_label/HFID issue: core node logic updates, supporting tests, changelog entry, and documentation additions explaining the fix and related architecture.

✏️ 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.

❤️ Share

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

@polmichel polmichel force-pushed the pmi-20260225-display-labels-upsert branch from d11fb49 to e591e10 Compare February 26, 2026 10:09
@codspeed-hq
Copy link
Copy Markdown

codspeed-hq Bot commented Feb 26, 2026

Merging this PR will not alter performance

✅ 12 untouched benchmarks


Comparing pmi-20260225-display-labels-upsert (72e8d8e) with release-1.8 (0a3bd7d)

Open in CodSpeed

@polmichel polmichel force-pushed the pmi-20260225-display-labels-upsert branch from e591e10 to 9288b49 Compare February 26, 2026 10:51
@polmichel polmichel marked this pull request as ready for review February 26, 2026 10:51
@polmichel polmichel requested a review from a team as a code owner February 26, 2026 10:51
Copy link
Copy Markdown
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@backend/tests/component/graphql/test_mutation_upsert.py`:
- Around line 852-855: The helper _basic_asserts is declared async but contains
no awaits and lacks a return type; change its signature from "async def
_basic_asserts(...)" to a synchronous function "def
_basic_asserts(result_upsert: ExecutionResult) -> None:" so it is no longer a
coroutine and includes the explicit None return type while keeping the same
assertion body.

In `@dev/guidelines/backend/python.md`:
- Around line 58-71: The example showing the deferred import uses TYPE_CHECKING
but omits its import; add "from typing import TYPE_CHECKING" to the snippet so
the block with "if TYPE_CHECKING:" and the deferred "from
infrahub.core.schema.schema_branch import SchemaBranch" is runnable and the
function signature "def collect_filters(self, schema_branch: SchemaBranch) ->
dict[str, set[str]]:" remains valid.

In `@dev/knowledge/backend/display-labels-and-hfid.md`:
- Line 1: Update the markdown title string to use hyphenation: change "Human
Friendly IDs" to "Human-Friendly IDs" in the top-level heading (the header text
in the file's first line, "# Display Labels and Human-Friendly IDs") so the
title reads "# Display Labels and Human-Friendly IDs".

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0a3bd7d and 9288b49.

📒 Files selected for processing (6)
  • backend/infrahub/core/node/__init__.py
  • backend/tests/component/graphql/test_mutation_upsert.py
  • changelog/8237.fixed.md
  • dev/guidelines/backend/python.md
  • dev/knowledge/backend/display-labels-and-hfid.md
  • dev/knowledge/backend/mutations.md

Comment thread backend/tests/component/graphql/test_mutation_upsert.py Outdated
Comment thread dev/guidelines/backend/python.md
Comment thread dev/knowledge/backend/display-labels-and-hfid.md Outdated
Comment thread dev/knowledge/backend/display-labels-and-hfid.md Outdated
Comment thread dev/knowledge/backend/mutations.md
Comment thread backend/tests/component/graphql/test_mutation_upsert.py Outdated
Comment thread backend/tests/component/graphql/test_mutation_upsert.py
Comment thread backend/infrahub/core/node/__init__.py
@polmichel polmichel marked this pull request as draft February 26, 2026 12:14
@polmichel polmichel marked this pull request as ready for review February 26, 2026 13:13
Copy link
Copy Markdown
Contributor

@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.

🧹 Nitpick comments (1)
dev/guidelines/backend/python.md (1)

58-73: Consider adding from __future__ import annotations to both snippets for completeness.

While the TYPE_CHECKING import issue from the past review has been addressed (line 66 correctly shows the import), both the "bad" and "good" examples would benefit from including from __future__ import annotations at the start. Line 45 establishes this as a universal requirement ("All backend modules use..."), so showing it in both snippets would:

  • Make each snippet runnable when copied in isolation
  • Reinforce that the future import is the foundation enabling the TYPE_CHECKING pattern
  • Clarify that even with string annotations, top-level imports still execute and can cause circular dependencies
📝 Proposed documentation enhancement
 # ❌ Bad - top-level import only used in annotations; causes circular import
+from __future__ import annotations
+
 from infrahub.core.schema.schema_branch import SchemaBranch
 
 def collect_filters(self, schema_branch: SchemaBranch) -> dict[str, set[str]]:
     ...
 
 # ✅ Good - deferred under TYPE_CHECKING
+from __future__ import annotations
+
 from typing import TYPE_CHECKING
 
 if TYPE_CHECKING:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@dev/guidelines/backend/python.md` around lines 58 - 73, Add "from __future__
import annotations" at the top of both the "bad" and "good" example snippets so
annotations are deferred and the TYPE_CHECKING pattern works as intended;
specifically, ensure the future import appears before any other imports or code
in the examples that reference SchemaBranch and the collect_filters(self,
schema_branch: SchemaBranch) signature, and keep the TYPE_CHECKING block and the
deferred import of infrahub.core.schema.schema_branch unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@dev/guidelines/backend/python.md`:
- Around line 58-73: Add "from __future__ import annotations" at the top of both
the "bad" and "good" example snippets so annotations are deferred and the
TYPE_CHECKING pattern works as intended; specifically, ensure the future import
appears before any other imports or code in the examples that reference
SchemaBranch and the collect_filters(self, schema_branch: SchemaBranch)
signature, and keep the TYPE_CHECKING block and the deferred import of
infrahub.core.schema.schema_branch unchanged.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9288b49 and 72e8d8e.

📒 Files selected for processing (3)
  • backend/tests/component/graphql/test_mutation_upsert.py
  • dev/guidelines/backend/python.md
  • dev/knowledge/backend/display-labels-and-hfid.md
🚧 Files skipped from review as they are similar to previous changes (2)
  • dev/knowledge/backend/display-labels-and-hfid.md
  • backend/tests/component/graphql/test_mutation_upsert.py

@polmichel polmichel merged commit 49f1069 into release-1.8 Mar 9, 2026
43 checks passed
@polmichel polmichel deleted the pmi-20260225-display-labels-upsert branch March 9, 2026 15:04
ajtmccarty added a commit that referenced this pull request Mar 12, 2026
…#8480)

* IFC-2235 integration test replicating the issue

* IFC-2235 HFID and Display Labels recomputation during node update could require additional information from related nodes

* IFC-2235 refactor common behavior in the same method

* IFC-2235 towncrier (#8237)

* IFC-2235 /feedback command usage

* IFC-2235 address code review feedbacks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

group/backend Issue related to the backend (API Server, Git Agent)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants