IFC-2113: Fix failure when removing a profile with a many relationship and overriding with same peers#9350
IFC-2113: Fix failure when removing a profile with a many relationship and overriding with same peers#9350solababs wants to merge 1 commit into
Conversation
There was a problem hiding this comment.
No issues found across 2 files
Confidence score: 5/5
- Automated review surfaced no issues in the provided summaries.
- No files require special attention.
Shadow auto-approve: would auto-approve. The change is a narrowly scoped bug fix that clears the is_from_profile flag on reused relationship peers to prevent them from being incorrectly removed by the profile applier, with a small line count, passing tests, and no impact on API, schema, or infrastructure.
Re-trigger cubic
| return None | ||
|
|
||
| async def update( | ||
| async def update( # noqa: PLR0915 |
There was a problem hiding this comment.
should either add this to the exceptions in pyproject.toml or refactor the method so the error isn't raised
| assert len(node_map) == 1 | ||
| final_child_one = node_map[child_and_thing_nodes.child_nodes[0].id] | ||
|
|
||
| await _validate_node_profile_relationships( |
There was a problem hiding this comment.
not caused by this PR, but it looks like this function does not correctly validate the case where peers are defined and source_uuid="", which is what we need to test for this case. it looks like it correctly tests that the source of the peer(s) is empty if no ExpectedProfileRelationship for the relationship name, but does not verify that if the ExpectedProfileRealtionship is defined with a source set to the empty string
Why
When a node's cardinality-many relationship is sourced from a profile (peers A, B, C) and the user saves an override containing a peer that also appears in the profile (e.g. [C, D, E]), peer C is silently dropped. Only D and E remain.
The root cause:
RelationshipManager.update()reuses the existingRelationshipobject for C without clearing itsis_from_profile=Trueflag. WhenNodeProfilesApplier.apply_profiles()runs immediately after (beforesave()), it sees C as profile-sourced and removes it because C is not in the set of user-set peers.This PR clears
is_from_profileand the source metadata on any reused relationship peer when the user explicitly includes it in their override.What changed
RelationshipManager.update()now clearsis_from_profileon reused peers — when a peer fromprevious_relationshipsis included in the new override list,is_from_profileis set toFalseandclear_source()is called before appending to_relationships. This applies to all three reuse branches (node-object, string peer-ID, dict).After the fix, when
apply_profiles()runs, the overlapping peer is already inuser_set_peer_idsand is not removed. No schema changes, no API changes, no change toNodeProfilesApplierlogic.How to test
uv run pytest backend/tests/component/core/profiles/ -v # 49 passed (was 47 passed + 2 xfailed)The previously-xfailed
test_get_many_with_profile_relationships_partial_overridenow passes and validates the fix directly: profile sets things=[T0, T1], user callsthings.update([T1, T2]), result is exactly [T1, T2] with no profile source.Impact & rollout
Checklist
uv run towncrier create ...)