Skip to content

[main-pf5] NETOBSERV-428 aggregate topology edges between groups - #1698

Merged
jpinsonneau merged 5 commits into
netobserv:main-pf5from
openshift-cherrypick-robot:cherry-pick-1618-to-main-pf5
Aug 14, 2026
Merged

jpinsonneau merged 5 commits into
netobserv:main-pf5from
openshift-cherrypick-robot:cherry-pick-1618-to-main-pf5

Conversation

@openshift-cherrypick-robot

@openshift-cherrypick-robot openshift-cherrypick-robot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

This is an automated cherry-pick of #1618

/assign jpinsonneau

Summary by CodeRabbit

  • New Features

    • Added optional Group edges display control for topology views.
    • Topology diagrams now combine cross-group connections into clearer aggregate paths, including entry, bridge, and exit segments.
    • Aggregate connections preserve relevant metrics, labels, highlighting, selection, and multi-selection behavior.
    • Aggregate edges automatically resnap after layout changes and group expansion or collapse.
  • Bug Fixes

    • Improved topology layout handling by excluding hidden, invalid, duplicate, and self-loop connections.
  • Tests

    • Expanded coverage for topology aggregation, edge filtering, layout behavior, and display-option states.

jpinsonneau and others added 4 commits August 12, 2026 13:19
…licker

Clear fixed endpoints and force-resnap only on collapse and layout end,
and wrap group collapse mutations in MobX action without deep-importing
DefaultGroup (avoids duplicate ElementContext vs Console vendors).

Co-authored-by: Cursor <cursoragent@cursor.com>
Clear unset endpoints before early-return in applySnapPlan, fall back from
bridgeId to bridgeKey, and mirror Ctrl/Meta multi-select for related segments.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Aug 12, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 6e38d9c2-6e25-4968-9420-1f919e7d92a4

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The topology now supports optional grouped edge aggregation across collapsed groups. It adds aggregate segment generation, model metadata, layout filtering, snapping and selection rendering, collapse resynchronization, in-place highlighting, localized controls, and automated coverage.

Changes

Aggregate topology edges

Layer / File(s) Summary
Aggregate edge model
web/src/utils/create-aggregate-edges.ts, web/src/model/topology.ts, web/src/model/__tests__/topology.spec.ts
Adds groupEdges, aggregate segment generation, metric and visual-state propagation, hidden leaf-edge removal, and tests for nested groups and bypass conditions.
Aggregate-aware layout links
web/src/components/tabs/netflow-topology/2d/layouts/*
Adds shared layout-link filtering and local breadth-first and Cola layout implementations that exclude aggregate entry and exit stubs, invalid endpoints, and self-loops.
Aggregate edge rendering and geometry
web/src/components/tabs/netflow-topology/2d/styles/*, web/src/components/tabs/netflow-topology/2d/components/edge.tsx, web/src/components/tabs/netflow-topology/2d/componentFactories/*
Adds aggregate-edge rendering, border snapping, bridge lookup, role-specific terminals, segment selection, snap-generation context, MobX-safe group mutations, and edge test identifiers.
Topology rebuild and interaction updates
web/src/components/tabs/netflow-topology/2d/topology-content.tsx
Rebuilds and resnaps aggregate edges after layout and collapse changes. Updates highlights in place and includes aggregate edges in reset and metric-tag handling.
Group-edges display option
web/src/components/dropdowns/topology-display-options.tsx, web/locales/en/plugin__netobserv-plugin.json, web/cypress/e2e/topology/topology.spec.ts
Adds the localized group-edges checkbox and verifies its checked, toggled, and disabled states.
Estimated code review effort: 5 (Critical) ~120 minutes
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description only states that this is an automated cherry-pick and omits the required summary, dependencies, and checklist information. Add the required description sections and complete the dependency, testing, unit-test, and QE checklist items.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: aggregating topology edges between groups.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@openshift-ci

openshift-ci Bot commented Aug 12, 2026

Copy link
Copy Markdown

Hi @openshift-cherrypick-robot. Thanks for your PR.

I'm waiting for a netobserv member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work.

Tip

We noticed you've done this a few times! Consider joining the org to skip this step and gain /lgtm and other bot rights. We recommend asking approvers on your previous PRs to sponsor you.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository.

@codecov

codecov Bot commented Aug 12, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 33.70079% with 421 lines in your changes missing coverage. Please review.
✅ Project coverage is 52.06%. Comparing base (74444fc) to head (f13f771).

Files with missing lines Patch % Lines
.../netflow-topology/2d/styles/styleAggregateEdge.tsx 9.30% 234 Missing ⚠️
web/src/utils/create-aggregate-edges.ts 54.54% 56 Missing and 29 partials ⚠️
...ents/tabs/netflow-topology/2d/topology-content.tsx 21.95% 59 Missing and 5 partials ⚠️
...nts/tabs/netflow-topology/2d/styles/styleGroup.tsx 15.38% 11 Missing ⚠️
web/src/model/topology.ts 82.22% 4 Missing and 4 partials ⚠️
.../netflow-topology/2d/layouts/breadthFirstLayout.ts 33.33% 6 Missing ⚠️
...bs/netflow-topology/2d/layouts/colaGroupsLayout.ts 33.33% 6 Missing ⚠️
...nts/tabs/netflow-topology/2d/layouts/baseLayout.ts 25.00% 3 Missing ⚠️
.../components/dropdowns/topology-display-options.tsx 0.00% 2 Missing ⚠️
...topology/2d/componentFactories/componentFactory.ts 50.00% 1 Missing ⚠️
... and 1 more
Additional details and impacted files
@@             Coverage Diff              @@
##           main-pf5    #1698      +/-   ##
============================================
- Coverage     52.79%   52.06%   -0.73%     
============================================
  Files           240      246       +6     
  Lines         13081    13690     +609     
  Branches       1731     1890     +159     
============================================
+ Hits           6906     7128     +222     
- Misses         5536     5881     +345     
- Partials        639      681      +42     
Flag Coverage Δ
uitests 55.71% <33.70%> (-1.21%) ⬇️
unittests 40.83% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
...etflow-topology/2d/aggregate-edge-snap-context.tsx 100.00% <100.00%> (ø)
...nents/tabs/netflow-topology/2d/components/edge.tsx 21.95% <ø> (ø)
...s/tabs/netflow-topology/2d/layouts/layout-edges.ts 100.00% <100.00%> (ø)
.../tabs/netflow-topology/2d/layouts/layoutFactory.ts 41.17% <100.00%> (+7.84%) ⬆️
...ents/tabs/netflow-topology/2d/styles/styleEdge.tsx 33.33% <ø> (ø)
...topology/2d/componentFactories/componentFactory.ts 33.33% <50.00%> (+3.33%) ⬆️
...y/2d/componentFactories/stylesComponentFactory.tsx 50.00% <66.66%> (+3.84%) ⬆️
.../components/dropdowns/topology-display-options.tsx 37.14% <0.00%> (-2.26%) ⬇️
...nts/tabs/netflow-topology/2d/layouts/baseLayout.ts 15.70% <25.00%> (+0.66%) ⬆️
.../netflow-topology/2d/layouts/breadthFirstLayout.ts 33.33% <33.33%> (ø)
... and 6 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Amoghrd

Amoghrd commented Aug 12, 2026

Copy link
Copy Markdown
Member

/ok-to-test

@openshift-ci openshift-ci Bot added ok-to-test To set manually when a PR is safe to test. Triggers image build on PR. and removed needs-ok-to-test labels Aug 12, 2026
@github-actions

Copy link
Copy Markdown

New images:

quay.io/netobserv/network-observability-console-plugin:a75ca48c
quay.io/netobserv/network-observability-standalone-frontend:a75ca48c

They will expire in two weeks.

To deploy this build, run from the operator repo, assuming the operator is running:

USER=netobserv VERSION=a75ca48c make set-plugin-image

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (7)
web/cypress/e2e/topology/topology.spec.ts (1)

88-100: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the dedicated data-test selector.

The component adds data-test="group-edges-switch" at Line 190, but the E2E test queries #group-edges-switch. Use the dedicated selector to reduce coupling to the rendered input id.

As per path instructions, web/cypress/**/*.ts must verify selector resilience.

🤖 Prompt for 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.

In `@web/cypress/e2e/topology/topology.spec.ts` around lines 88 - 100, Update the
topology E2E test queries for the group-edges control to use its dedicated
data-test selector, matching the component’s group-edges-switch hook, instead of
the rendered `#group-edges-switch` ID. Apply this to every reference to that
control while preserving the existing assertions and interactions.

Source: Path instructions

web/src/components/tabs/netflow-topology/2d/styles/styleGroup.tsx (1)

33-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Move this hook to web/src/utils.

useMobxSafeCollapseMutations is reusable component logic. Place it in a focused hook file, for example web/src/utils/mobx-collapse-hook.ts, and import it here.

As per coding guidelines: "Extract custom React component logic into focused hooks in web/src/utils/*-hook.ts".

🤖 Prompt for 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.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleGroup.tsx` around
lines 33 - 54, Move useMobxSafeCollapseMutations into a focused hook file under
web/src/utils, such as mobx-collapse-hook.ts, preserving its existing MobX
wrapping and cleanup behavior. Export the hook from that file and update the
netflow topology styleGroup module to import and use it instead of defining it
locally.

Source: Coding guidelines

web/src/components/tabs/netflow-topology/2d/styles/styleAggregateEdge.tsx (1)

341-354: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Avoid the graph-wide bridge scan during render.

geoKey calls findRelatedBridge on every render for exit and entry roles. When bridgeId resolution fails, that helper iterates getGraph().getEdges() for each segment. During a Cola tick every edge re-renders per frame, so the cost becomes O(segments × edges) per frame. Cache the resolved bridge in a ref keyed by bridgeId/bridgeKey, or build one bridge index per graph revision.

Per path instructions: "Check React hooks dependencies, component re-render optimization, and TypeScript type safety."

🤖 Prompt for 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.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleAggregateEdge.tsx`
around lines 341 - 354, Update the render logic surrounding geoKey and
findRelatedBridge to avoid scanning all graph edges on every render. Cache the
resolved bridge by bridgeId/bridgeKey in a React ref, or maintain an equivalent
bridge index scoped to the current graph revision, and reuse it when
constructing geoKey for entry and exit roles. Ensure hook dependencies remain
correct and preserve TypeScript-safe handling when no bridge resolves.

Source: Path instructions

web/src/components/tabs/netflow-topology/2d/layouts/breadthFirstLayout.ts (1)

16-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the pass-through constructor.

The constructor only forwards to super. TypeScript inherits the base signature when the constructor is absent. The same pattern exists in colaGroupsLayout.ts.

🤖 Prompt for 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.

In `@web/src/components/tabs/netflow-topology/2d/layouts/breadthFirstLayout.ts`
around lines 16 - 18, Remove the redundant pass-through constructor from
PfBreadthFirstLayout so the class inherits the constructor signature from its
base class. Apply the same cleanup to the corresponding constructor in
colaGroupsLayout.ts.
web/src/utils/create-aggregate-edges.ts (2)

242-250: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the unused leafSource parameter from createSegmentEdge.

createSegmentEdge accepts leafSource but never reads it. It hardcodes bidirectional: false. mergeSegment uses leafSource, so the asymmetry is easy to misread as a bug. Drop the parameter, or add a comment that the first leaf always defines the segment direction.

Also applies to: 270-277

🤖 Prompt for 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.

In `@web/src/utils/create-aggregate-edges.ts` around lines 242 - 250, Remove the
unused leafSource parameter from createSegmentEdge and update every call site,
including mergeSegment, to match the revised signature. Keep leafSource handling
in mergeSegment unchanged and preserve createSegmentEdge’s existing hardcoded
bidirectional behavior.

204-213: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive bridgeId from segmentId instead of duplicating the format string.

segmentId builds the bridge id as aggregate_bridge_${segment.bridgeKey} at Line 209. createSegmentEdge rebuilds the same string at Line 260. If the bridge id scheme changes in one place, stub bridgeId values point at a non-existent edge and runtime bridge resolution falls back silently.

♻️ Proposed fix
+const bridgeSegmentId = (bridgeKey: string): string => `aggregate_bridge_${bridgeKey}`;
+
 const segmentId = (segment: PathSegment, legacyBridgeId = false): string => {
   if (segment.role === 'bridge') {
     if (legacyBridgeId) {
       return `aggregate_${segment.source}_${segment.target}`;
     }
-    return `aggregate_bridge_${segment.bridgeKey}`;
+    return bridgeSegmentId(segment.bridgeKey);
   }
       // O(1) bridge lookup for exit/entry stub snapping (avoids scanning all graph edges).
-      ...(segment.role !== 'bridge' ? { bridgeId: `aggregate_bridge_${segment.bridgeKey}` } : {}),
+      ...(segment.role !== 'bridge' ? { bridgeId: bridgeSegmentId(segment.bridgeKey) } : {}),

Also applies to: 256-265

🤖 Prompt for 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.

In `@web/src/utils/create-aggregate-edges.ts` around lines 204 - 213, Update
createSegmentEdge to derive the stub bridgeId by calling segmentId with the
current segment and non-legacy mode, instead of duplicating the aggregate_bridge
format string. Keep the existing edge creation behavior unchanged while ensuring
bridge references use the same identifier generated by segmentId.
web/src/model/__tests__/topology.spec.ts (1)

113-141: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for collapsed groups and bidirectional bridges.

The fixtures never set collapsed: true, so the collapse remap branch of createAggregateEdges is untested here. The fixtures also only use one direction (a1→b1, a2→b1), so mergeSegment never sets bidirectional: true. Two extra cases would lock both behaviors:

  • a collapsed ns-a with an edge from a1 to b1, asserting the bridge ends at ns-a;
  • edges a1→b1 and b1→a2, asserting bridges[0].data.bidirectional === true.

I can write these tests if you want.

🤖 Prompt for 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.

In `@web/src/model/__tests__/topology.spec.ts` around lines 113 - 141, Extend the
topology aggregation tests around baseNodes/baseEdges and maybeAggregateEdges to
cover both missing branches: add a case with ns-a collapsed and an a1→b1 edge,
asserting the aggregate bridge terminates at ns-a, and add a bidirectional case
with a1→b1 plus b1→a2, asserting the resulting bridge data has bidirectional set
to true.
🤖 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 `@web/cypress/e2e/topology/topology.spec.ts`:
- Around line 92-100: The topology test currently verifies group-edges disabling
only with groupTypes set to none. Add a separate assertion path that selects a
non-none group type, disables edges, and verifies `#group-edges-switch` is
disabled, while retaining the existing none-group assertion independently.
- Around line 87-94: Update the toggle-switch flow in the topology test to
assert that `#group-edges-switch` starts checked, verify it becomes unchecked
after the click, and click it back on before collapsing groups. Preserve the
existing disabled-state assertions after selecting “none” so the test explicitly
covers the enabled group-edges path.

In `@web/src/components/tabs/netflow-topology/2d/layouts/layoutFactory.ts`:
- Around line 12-13: Update ConcentricLayout, DagreLayout, DagreGroupsLayout,
ForceLayout, and GridLayout to filter aggregate stub edges from their layout
links, matching the existing filtering behavior. Leave Cola and ColaNoForce
unchanged because they already inherit it from the vendored BaseLayout.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleAggregateEdge.tsx`:
- Around line 42-58: Update the bridge resolution logic around getEdgeById so it
only returns when an edge is actually found; if the lookup returns undefined,
continue to the existing bridgeKey resolution path. Preserve the current error
handling and fallback behavior for thrown lookup errors.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleGroup.tsx`:
- Around line 39-54: Remove the method reassignment logic from
useMobxSafeCollapseMutations, especially the setDimensions and setCollapsed
overrides, because MobX-managed methods must not be overwritten. Use the
supported collapse handler API to wrap the required mutations instead; if shared
patching is unavoidable, implement reference-counted ownership with cleanup
rather than a boolean marker.

In `@web/src/components/tabs/netflow-topology/2d/topology-content.tsx`:
- Around line 512-528: Update highlighting in topology-content.tsx and the
corresponding logic in topology.ts to use exact peer, source, and target ID
equality rather than includes or delimiter-based prefix/suffix matching. For
aggregated edges, retain or reuse structured leaf endpoint data instead of
splitting aggregatedEdgeIds on '.', and mark highlights only when an exact
endpoint/peer ID matches highlightedId.

---

Nitpick comments:
In `@web/cypress/e2e/topology/topology.spec.ts`:
- Around line 88-100: Update the topology E2E test queries for the group-edges
control to use its dedicated data-test selector, matching the component’s
group-edges-switch hook, instead of the rendered `#group-edges-switch` ID. Apply
this to every reference to that control while preserving the existing assertions
and interactions.

In `@web/src/components/tabs/netflow-topology/2d/layouts/breadthFirstLayout.ts`:
- Around line 16-18: Remove the redundant pass-through constructor from
PfBreadthFirstLayout so the class inherits the constructor signature from its
base class. Apply the same cleanup to the corresponding constructor in
colaGroupsLayout.ts.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleAggregateEdge.tsx`:
- Around line 341-354: Update the render logic surrounding geoKey and
findRelatedBridge to avoid scanning all graph edges on every render. Cache the
resolved bridge by bridgeId/bridgeKey in a React ref, or maintain an equivalent
bridge index scoped to the current graph revision, and reuse it when
constructing geoKey for entry and exit roles. Ensure hook dependencies remain
correct and preserve TypeScript-safe handling when no bridge resolves.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleGroup.tsx`:
- Around line 33-54: Move useMobxSafeCollapseMutations into a focused hook file
under web/src/utils, such as mobx-collapse-hook.ts, preserving its existing MobX
wrapping and cleanup behavior. Export the hook from that file and update the
netflow topology styleGroup module to import and use it instead of defining it
locally.

In `@web/src/model/__tests__/topology.spec.ts`:
- Around line 113-141: Extend the topology aggregation tests around
baseNodes/baseEdges and maybeAggregateEdges to cover both missing branches: add
a case with ns-a collapsed and an a1→b1 edge, asserting the aggregate bridge
terminates at ns-a, and add a bidirectional case with a1→b1 plus b1→a2,
asserting the resulting bridge data has bidirectional set to true.

In `@web/src/utils/create-aggregate-edges.ts`:
- Around line 242-250: Remove the unused leafSource parameter from
createSegmentEdge and update every call site, including mergeSegment, to match
the revised signature. Keep leafSource handling in mergeSegment unchanged and
preserve createSegmentEdge’s existing hardcoded bidirectional behavior.
- Around line 204-213: Update createSegmentEdge to derive the stub bridgeId by
calling segmentId with the current segment and non-legacy mode, instead of
duplicating the aggregate_bridge format string. Keep the existing edge creation
behavior unchanged while ensuring bridge references use the same identifier
generated by segmentId.
🪄 Autofix

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 Plus

Run ID: d24c2f7e-e7eb-4b35-9965-4ea10736df16

📥 Commits

Reviewing files that changed from the base of the PR and between 74444fc and a75ca48.

📒 Files selected for processing (20)
  • web/cypress/e2e/topology/topology.spec.ts
  • web/locales/en/plugin__netobserv-plugin.json
  • web/src/components/dropdowns/topology-display-options.tsx
  • web/src/components/tabs/netflow-topology/2d/aggregate-edge-snap-context.tsx
  • web/src/components/tabs/netflow-topology/2d/componentFactories/componentFactory.ts
  • web/src/components/tabs/netflow-topology/2d/componentFactories/stylesComponentFactory.tsx
  • web/src/components/tabs/netflow-topology/2d/components/edge.tsx
  • web/src/components/tabs/netflow-topology/2d/layouts/__tests__/layout-edges.spec.ts
  • web/src/components/tabs/netflow-topology/2d/layouts/baseLayout.ts
  • web/src/components/tabs/netflow-topology/2d/layouts/breadthFirstLayout.ts
  • web/src/components/tabs/netflow-topology/2d/layouts/colaGroupsLayout.ts
  • web/src/components/tabs/netflow-topology/2d/layouts/layout-edges.ts
  • web/src/components/tabs/netflow-topology/2d/layouts/layoutFactory.ts
  • web/src/components/tabs/netflow-topology/2d/styles/styleAggregateEdge.tsx
  • web/src/components/tabs/netflow-topology/2d/styles/styleEdge.tsx
  • web/src/components/tabs/netflow-topology/2d/styles/styleGroup.tsx
  • web/src/components/tabs/netflow-topology/2d/topology-content.tsx
  • web/src/model/__tests__/topology.spec.ts
  • web/src/model/topology.ts
  • web/src/utils/create-aggregate-edges.ts
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • netobserv/netobserv-operator (manual)
  • netobserv/flowlogs-pipeline (manual)

Comment thread web/cypress/e2e/topology/topology.spec.ts
Comment thread web/cypress/e2e/topology/topology.spec.ts
Comment thread web/src/components/tabs/netflow-topology/2d/styles/styleGroup.tsx
Comment thread web/src/components/tabs/netflow-topology/2d/topology-content.tsx
@openshift-ci

openshift-ci Bot commented Aug 13, 2026

Copy link
Copy Markdown

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please ask for approval from jpinsonneau. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@github-actions github-actions Bot removed the ok-to-test To set manually when a PR is safe to test. Triggers image build on PR. label Aug 13, 2026
@jpinsonneau

Copy link
Copy Markdown
Member

Actionable comments posted: 6

🧹 Nitpick comments (7)

web/cypress/e2e/topology/topology.spec.ts (1)> 88-100: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the dedicated data-test selector.
The component adds data-test="group-edges-switch" at Line 190, but the E2E test queries #group-edges-switch. Use the dedicated selector to reduce coupling to the rendered input id.
As per path instructions, web/cypress/**/*.ts must verify selector resilience.

🤖 Prompt for 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.

In `@web/cypress/e2e/topology/topology.spec.ts` around lines 88 - 100, Update the
topology E2E test queries for the group-edges control to use its dedicated
data-test selector, matching the component’s group-edges-switch hook, instead of
the rendered `#group-edges-switch` ID. Apply this to every reference to that
control while preserving the existing assertions and interactions.

Source: Path instructions

web/src/components/tabs/netflow-topology/2d/styles/styleGroup.tsx (1)> 33-54: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Move this hook to web/src/utils.
useMobxSafeCollapseMutations is reusable component logic. Place it in a focused hook file, for example web/src/utils/mobx-collapse-hook.ts, and import it here.
As per coding guidelines: "Extract custom React component logic into focused hooks in web/src/utils/*-hook.ts".

🤖 Prompt for 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.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleGroup.tsx` around
lines 33 - 54, Move useMobxSafeCollapseMutations into a focused hook file under
web/src/utils, such as mobx-collapse-hook.ts, preserving its existing MobX
wrapping and cleanup behavior. Export the hook from that file and update the
netflow topology styleGroup module to import and use it instead of defining it
locally.

Source: Coding guidelines

web/src/components/tabs/netflow-topology/2d/styles/styleAggregateEdge.tsx (1)> 341-354: 🚀 Performance & Scalability | 🔵 Trivial | 🏗️ Heavy lift

Avoid the graph-wide bridge scan during render.
geoKey calls findRelatedBridge on every render for exit and entry roles. When bridgeId resolution fails, that helper iterates getGraph().getEdges() for each segment. During a Cola tick every edge re-renders per frame, so the cost becomes O(segments × edges) per frame. Cache the resolved bridge in a ref keyed by bridgeId/bridgeKey, or build one bridge index per graph revision.
Per path instructions: "Check React hooks dependencies, component re-render optimization, and TypeScript type safety."

🤖 Prompt for 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.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleAggregateEdge.tsx`
around lines 341 - 354, Update the render logic surrounding geoKey and
findRelatedBridge to avoid scanning all graph edges on every render. Cache the
resolved bridge by bridgeId/bridgeKey in a React ref, or maintain an equivalent
bridge index scoped to the current graph revision, and reuse it when
constructing geoKey for entry and exit roles. Ensure hook dependencies remain
correct and preserve TypeScript-safe handling when no bridge resolves.

Source: Path instructions

web/src/components/tabs/netflow-topology/2d/layouts/breadthFirstLayout.ts (1)> 16-18: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Drop the pass-through constructor.
The constructor only forwards to super. TypeScript inherits the base signature when the constructor is absent. The same pattern exists in colaGroupsLayout.ts.

🤖 Prompt for 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.

In `@web/src/components/tabs/netflow-topology/2d/layouts/breadthFirstLayout.ts`
around lines 16 - 18, Remove the redundant pass-through constructor from
PfBreadthFirstLayout so the class inherits the constructor signature from its
base class. Apply the same cleanup to the corresponding constructor in
colaGroupsLayout.ts.

web/src/utils/create-aggregate-edges.ts (2)> 242-250: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove the unused leafSource parameter from createSegmentEdge.
createSegmentEdge accepts leafSource but never reads it. It hardcodes bidirectional: false. mergeSegment uses leafSource, so the asymmetry is easy to misread as a bug. Drop the parameter, or add a comment that the first leaf always defines the segment direction.
Also applies to: 270-277

🤖 Prompt for 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.

In `@web/src/utils/create-aggregate-edges.ts` around lines 242 - 250, Remove the
unused leafSource parameter from createSegmentEdge and update every call site,
including mergeSegment, to match the revised signature. Keep leafSource handling
in mergeSegment unchanged and preserve createSegmentEdge’s existing hardcoded
bidirectional behavior.

204-213: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Derive bridgeId from segmentId instead of duplicating the format string.
segmentId builds the bridge id as aggregate_bridge_${segment.bridgeKey} at Line 209. createSegmentEdge rebuilds the same string at Line 260. If the bridge id scheme changes in one place, stub bridgeId values point at a non-existent edge and runtime bridge resolution falls back silently.

♻️ Proposed fix

+const bridgeSegmentId = (bridgeKey: string): string => `aggregate_bridge_${bridgeKey}`;
+
 const segmentId = (segment: PathSegment, legacyBridgeId = false): string => {
   if (segment.role === 'bridge') {
     if (legacyBridgeId) {
       return `aggregate_${segment.source}_${segment.target}`;
     }
-    return `aggregate_bridge_${segment.bridgeKey}`;
+    return bridgeSegmentId(segment.bridgeKey);
   }
       // O(1) bridge lookup for exit/entry stub snapping (avoids scanning all graph edges).
-      ...(segment.role !== 'bridge' ? { bridgeId: `aggregate_bridge_${segment.bridgeKey}` } : {}),
+      ...(segment.role !== 'bridge' ? { bridgeId: bridgeSegmentId(segment.bridgeKey) } : {}),

Also applies to: 256-265

🤖 Prompt for 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.

In `@web/src/utils/create-aggregate-edges.ts` around lines 204 - 213, Update
createSegmentEdge to derive the stub bridgeId by calling segmentId with the
current segment and non-legacy mode, instead of duplicating the aggregate_bridge
format string. Keep the existing edge creation behavior unchanged while ensuring
bridge references use the same identifier generated by segmentId.

web/src/model/tests/topology.spec.ts (1)> 113-141: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Add coverage for collapsed groups and bidirectional bridges.
The fixtures never set collapsed: true, so the collapse remap branch of createAggregateEdges is untested here. The fixtures also only use one direction (a1→b1, a2→b1), so mergeSegment never sets bidirectional: true. Two extra cases would lock both behaviors:

  • a collapsed ns-a with an edge from a1 to b1, asserting the bridge ends at ns-a;
  • edges a1→b1 and b1→a2, asserting bridges[0].data.bidirectional === true.

I can write these tests if you want.

🤖 Prompt for 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.

In `@web/src/model/__tests__/topology.spec.ts` around lines 113 - 141, Extend the
topology aggregation tests around baseNodes/baseEdges and maybeAggregateEdges to
cover both missing branches: add a case with ns-a collapsed and an a1→b1 edge,
asserting the aggregate bridge terminates at ns-a, and add a bidirectional case
with a1→b1 plus b1→a2, asserting the resulting bridge data has bidirectional set
to true.

🤖 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 `@web/cypress/e2e/topology/topology.spec.ts`:
- Around line 92-100: The topology test currently verifies group-edges disabling
only with groupTypes set to none. Add a separate assertion path that selects a
non-none group type, disables edges, and verifies `#group-edges-switch` is
disabled, while retaining the existing none-group assertion independently.
- Around line 87-94: Update the toggle-switch flow in the topology test to
assert that `#group-edges-switch` starts checked, verify it becomes unchecked
after the click, and click it back on before collapsing groups. Preserve the
existing disabled-state assertions after selecting “none” so the test explicitly
covers the enabled group-edges path.

In `@web/src/components/tabs/netflow-topology/2d/layouts/layoutFactory.ts`:
- Around line 12-13: Update ConcentricLayout, DagreLayout, DagreGroupsLayout,
ForceLayout, and GridLayout to filter aggregate stub edges from their layout
links, matching the existing filtering behavior. Leave Cola and ColaNoForce
unchanged because they already inherit it from the vendored BaseLayout.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleAggregateEdge.tsx`:
- Around line 42-58: Update the bridge resolution logic around getEdgeById so it
only returns when an edge is actually found; if the lookup returns undefined,
continue to the existing bridgeKey resolution path. Preserve the current error
handling and fallback behavior for thrown lookup errors.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleGroup.tsx`:
- Around line 39-54: Remove the method reassignment logic from
useMobxSafeCollapseMutations, especially the setDimensions and setCollapsed
overrides, because MobX-managed methods must not be overwritten. Use the
supported collapse handler API to wrap the required mutations instead; if shared
patching is unavoidable, implement reference-counted ownership with cleanup
rather than a boolean marker.

In `@web/src/components/tabs/netflow-topology/2d/topology-content.tsx`:
- Around line 512-528: Update highlighting in topology-content.tsx and the
corresponding logic in topology.ts to use exact peer, source, and target ID
equality rather than includes or delimiter-based prefix/suffix matching. For
aggregated edges, retain or reuse structured leaf endpoint data instead of
splitting aggregatedEdgeIds on '.', and mark highlights only when an exact
endpoint/peer ID matches highlightedId.

---

Nitpick comments:
In `@web/cypress/e2e/topology/topology.spec.ts`:
- Around line 88-100: Update the topology E2E test queries for the group-edges
control to use its dedicated data-test selector, matching the component’s
group-edges-switch hook, instead of the rendered `#group-edges-switch` ID. Apply
this to every reference to that control while preserving the existing assertions
and interactions.

In `@web/src/components/tabs/netflow-topology/2d/layouts/breadthFirstLayout.ts`:
- Around line 16-18: Remove the redundant pass-through constructor from
PfBreadthFirstLayout so the class inherits the constructor signature from its
base class. Apply the same cleanup to the corresponding constructor in
colaGroupsLayout.ts.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleAggregateEdge.tsx`:
- Around line 341-354: Update the render logic surrounding geoKey and
findRelatedBridge to avoid scanning all graph edges on every render. Cache the
resolved bridge by bridgeId/bridgeKey in a React ref, or maintain an equivalent
bridge index scoped to the current graph revision, and reuse it when
constructing geoKey for entry and exit roles. Ensure hook dependencies remain
correct and preserve TypeScript-safe handling when no bridge resolves.

In `@web/src/components/tabs/netflow-topology/2d/styles/styleGroup.tsx`:
- Around line 33-54: Move useMobxSafeCollapseMutations into a focused hook file
under web/src/utils, such as mobx-collapse-hook.ts, preserving its existing MobX
wrapping and cleanup behavior. Export the hook from that file and update the
netflow topology styleGroup module to import and use it instead of defining it
locally.

In `@web/src/model/__tests__/topology.spec.ts`:
- Around line 113-141: Extend the topology aggregation tests around
baseNodes/baseEdges and maybeAggregateEdges to cover both missing branches: add
a case with ns-a collapsed and an a1→b1 edge, asserting the aggregate bridge
terminates at ns-a, and add a bidirectional case with a1→b1 plus b1→a2,
asserting the resulting bridge data has bidirectional set to true.

In `@web/src/utils/create-aggregate-edges.ts`:
- Around line 242-250: Remove the unused leafSource parameter from
createSegmentEdge and update every call site, including mergeSegment, to match
the revised signature. Keep leafSource handling in mergeSegment unchanged and
preserve createSegmentEdge’s existing hardcoded bidirectional behavior.
- Around line 204-213: Update createSegmentEdge to derive the stub bridgeId by
calling segmentId with the current segment and non-legacy mode, instead of
duplicating the aggregate_bridge format string. Keep the existing edge creation
behavior unchanged while ensuring bridge references use the same identifier
generated by segmentId.

🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:

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

ℹ️ Review info

Ignoring rabbit feedback as those were not triggered in main branch and not mandatory here
We can still open a polishing PR on main + pf5 if we feel needed

@Amoghrd

Amoghrd commented Aug 13, 2026

Copy link
Copy Markdown
Member

/ok-to-test

@openshift-ci openshift-ci Bot added the ok-to-test To set manually when a PR is safe to test. Triggers image build on PR. label Aug 13, 2026
@github-actions

Copy link
Copy Markdown

New images:

quay.io/netobserv/network-observability-console-plugin:f13f7718
quay.io/netobserv/network-observability-standalone-frontend:f13f7718

They will expire in two weeks.

To deploy this build, run from the operator repo, assuming the operator is running:

USER=netobserv VERSION=f13f7718 make set-plugin-image

@openshift-ci

openshift-ci Bot commented Aug 13, 2026

Copy link
Copy Markdown

@openshift-cherrypick-robot: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/pf5-integration-tests f13f771 link false /test pf5-integration-tests
ci/prow/pf5-images f13f771 link true /test pf5-images

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@Amoghrd

Amoghrd commented Aug 14, 2026

Copy link
Copy Markdown
Member

/label qe-approved

@openshift-ci openshift-ci Bot added the qe-approved QE has approved this pull request label Aug 14, 2026
@jpinsonneau
jpinsonneau merged commit 780d8e7 into netobserv:main-pf5 Aug 14, 2026
11 of 14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ok-to-test To set manually when a PR is safe to test. Triggers image build on PR. qe-approved QE has approved this pull request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants