Skip to content

fix(dependency_graph): remove orphaned children in remove_dependency#1106

Merged
LalatenduMohanty merged 1 commit into
mainfrom
fix/remove-dependency-orphans
May 6, 2026
Merged

fix(dependency_graph): remove orphaned children in remove_dependency#1106
LalatenduMohanty merged 1 commit into
mainfrom
fix/remove-dependency-orphans

Conversation

@jskladan
Copy link
Copy Markdown
Contributor

@jskladan jskladan commented May 4, 2026

When a node is removed, child nodes that have no remaining parents are now recursively removed as well, preventing orphaned nodes from lingering in the graph.

Closes: #1041

[X] PR follows CONTRIBUTING.md guidelines

@jskladan jskladan requested a review from a team as a code owner May 4, 2026 11:13
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: bc358d88-d6b0-4cdb-9e0c-64e3c3604996

📥 Commits

Reviewing files that changed from the base of the PR and between f827fd2 and ff21497.

📒 Files selected for processing (2)
  • src/fromager/dependency_graph.py
  • tests/test_dependency_graph.py

📝 Walkthrough

Walkthrough

DependencyGraph.remove_dependency() was rewritten to remove the target node and then iteratively remove any descendant nodes that become orphaned (no remaining parents). The implementation snapshots direct children, removes the deleted node from each child’s parents and from each parent’s children, deletes the node from self.nodes, and enqueues children that now have no parents (excluding ROOT) for further removal until the queue is empty. A local build_graph() helper and multiple tests (test_remove_dependency*) were added to cover leaf removal, cascading orphan removal, shared-child preservation, diamond topologies, mid-graph removals, already-removed targets, and removal of nonexistent nodes.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing remove_dependency to remove orphaned children from the graph.
Description check ✅ Passed The description accurately explains the change: orphaned child nodes are now recursively removed when a parent is deleted, and references issue #1041.
Linked Issues check ✅ Passed The PR implementation meets all requirements from #1041: it removes orphaned children iteratively via queue-based approach, cleans up stale parent references, and recursively/iteratively removes descendants without remaining parents.
Out of Scope Changes check ✅ Passed All changes are in-scope: dependency_graph.py implements the orphan-removal fix, and test_dependency_graph.py adds comprehensive test coverage for the new behavior with no unrelated modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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.

@mergify mergify Bot added the ci label May 4, 2026
smoparth
smoparth previously approved these changes May 4, 2026
rd4398
rd4398 previously approved these changes May 4, 2026
Copy link
Copy Markdown
Contributor

@rd4398 rd4398 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks good!

@LalatenduMohanty
Copy link
Copy Markdown
Member

@mergify rebase

@mergify
Copy link
Copy Markdown
Contributor

mergify Bot commented May 5, 2026

rebase

✅ Branch has been successfully rebased

Copy link
Copy Markdown

@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: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/fromager/dependency_graph.py`:
- Around line 389-392: The recursive call in remove_dependency (the loop over
children checking child.key != ROOT and child.key in self.nodes and not
child.parents) causes repeated global child-edge cleanup and O(n²) behavior
during cascades; fix by avoiding re-entering remove_dependency for each orphan —
instead, when you detect an orphan node (use children, ROOT, self.nodes,
child.parents, child.canonicalized_name, child.version to locate it), remove it
from its direct parents' children lists and add it to a local queue of nodes to
delete, then process that queue iteratively (or mark nodes for bulk deletion) so
global child-edge cleanup runs once per node rather than once per orphan
recursion.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: dc241074-4cae-4bfb-b1ea-5676ca7ac3e5

📥 Commits

Reviewing files that changed from the base of the PR and between bc300d4 and 1f8c31c.

📒 Files selected for processing (2)
  • src/fromager/dependency_graph.py
  • tests/test_dependency_graph.py

Comment thread src/fromager/dependency_graph.py Outdated
@jskladan
Copy link
Copy Markdown
Contributor Author

jskladan commented May 5, 2026

@coderabbitai please re-review this

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 5, 2026

Tip

For best results, initiate chat on the files or code changes.

@jskladan Sure, I'll re-review the PR now!

[full_review]

@jskladan
Copy link
Copy Markdown
Contributor Author

jskladan commented May 5, 2026

@rd4398 / @LalatenduMohanty - if you could have a look, I addressed the feedback from the Coderabbit, it IMO made sense to make this into a pretty straightforward stack-driven BFS instead of the recursion (funny enough, I've seen the coderabbit implementation after I've made the changes 🥲 didn't know it proposes detailed solutions, but it is virtually the same, only I decided to use dequeue instead of plain list)

@LalatenduMohanty
Copy link
Copy Markdown
Member

@jskladan The BFS approach is the better choice here since it avoids stack depth issues on deep dependency chains and makes the traversal order explicit . You can squash the commits. I can approve the PR after that

When a node is removed, child nodes that have no remaining parents
are now removed as well, preventing orphaned nodes from lingering
in the graph.

Closes: #1041
Signed-off-by: Josef Skladanka <jskladan@redhat.com>
Co-Authored-By: Claude <claude@anthropic.com>
@jskladan jskladan force-pushed the fix/remove-dependency-orphans branch from f827fd2 to ff21497 Compare May 6, 2026 09:36
@jskladan
Copy link
Copy Markdown
Contributor Author

jskladan commented May 6, 2026

Done. Squashed and rebased.

@LalatenduMohanty LalatenduMohanty merged commit 97fd8e1 into main May 6, 2026
43 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(dependency_graph): remove_dependency leaves orphaned child nodes in graph

4 participants