Skip to content

feat: nest HelmRelease inventory children in resource tree - #750

Closed
artemiyokulov wants to merge 1 commit into
openchoreo:mainfrom
artemiyokulov:feat/resource-drawer-child-events
Closed

feat: nest HelmRelease inventory children in resource tree#750
artemiyokulov wants to merge 1 commit into
openchoreo:mainfrom
artemiyokulov:feat/resource-drawer-child-events

Conversation

@artemiyokulov

@artemiyokulov artemiyokulov commented Aug 7, 2026

Copy link
Copy Markdown

Summary

Nest Flux HelmRelease inventory workloads (Deployment / PVC / …) under the HelmRelease in the runtime resource tree.

Previously those children often hung as flat siblings under RenderedRelease (missing parentRefs), so the HelmRelease looked like a leaf and there was no place to open per-child Events.

Behavior

  • Parse HelmRelease.status.inventory.entries and re-parent matching tree nodes under that HelmRelease
  • Fallback: if there is a single HelmRelease and a Deployment/StatefulSet/PVC still only under RenderedRelease, nest it under the HelmRelease
  • Events stay per-node — click Deployment/Pod to see that object's Events (no aggregation into the parent)

Out of scope / companion

  • Discovering workloads that are absent from k8sresources/tree (empty inventory and no live objects) needs openchoreo-api expansion (parentRefs + optional Flux label LIST). This PR only fixes nesting for nodes already returned by the tree API.

Test plan

  • Unit: helmInventoryNesting.test.ts, treeLayoutUtils inventory nesting case
  • Runtime tree with HelmRelease that has inventory Deployment → Deployment appears under HelmRelease
  • Click Deployment / Pod → EVENTS shows that resource's events only
  • Click HelmRelease → EVENTS does not list child Pod/RS events

Summary by CodeRabbit

  • New Features

    • HelmRelease-managed workloads now appear nested beneath their HelmRelease in the runtime resource tree.
    • Each nested workload is displayed as a separate resource node with its own Events tab.
  • Bug Fixes

    • Improved event sorting when resources have invalid or missing timestamps.
  • Tests

    • Added coverage for HelmRelease inventory relationships and resource tree nesting.

@github-actions

github-actions Bot commented Aug 7, 2026

Copy link
Copy Markdown

Changeset detected — the following file(s) will be released with this PR:

.changeset/resource-tree-helm-children.md

@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Helm resource tree behavior

Layer / File(s) Summary
Helm inventory parsing and nesting
plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/helmInventoryNesting.ts
Flux inventory IDs are parsed into resource references. Matching workloads are nested under their HelmRelease, with a fallback for a single release.
Tree layout integration and validation
plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/treeLayoutUtils.ts, plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/*test.ts, .changeset/resource-tree-helm-children.md
Tree construction invokes HelmRelease nesting. Tests cover inventory parsing, workload reparenting, and parent-linked Pods. The changeset documents the runtime tree behavior.
Invalid event timestamp handling
plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceEventsTable.tsx
Event sorting treats invalid lastTimestamp values as zero timestamps.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant treeLayoutUtils
  participant nestHelmReleaseChildren
  participant FluxInventoryEntries
  participant TreeNodes
  treeLayoutUtils->>nestHelmReleaseChildren: invoke after release nodes are appended
  nestHelmReleaseChildren->>FluxInventoryEntries: parse inventory entry IDs
  FluxInventoryEntries-->>nestHelmReleaseChildren: return resource references
  nestHelmReleaseChildren->>TreeNodes: assign matching workload parents
Loading

Suggested reviewers: stefinie123

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description explains the feature and test plan but omits most required template sections, including goals, approach, documentation, security, and test environment. Complete the required template sections and provide the requested documentation, security, automation test, migration, and test-environment details.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the primary change: nesting HelmRelease inventory children in the resource tree.
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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (4)
plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceEventsTable.tsx (4)

149-159: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

isOwn is never read.

fetchEventsForNode sets isOwn: false for every event. The effect then overwrites it at line 211 with source.id === node.id. No render code reads the field. The helper also cannot know ownership, so setting it here is misleading.

Either remove isOwn from AggregatedResourceEvent and from this helper, or use it in the table, for example to de-emphasize child rows.

♻️ Proposed refactor: drop the field from the helper
   const resourceRef = formatResourceRef(source);
-  return fetched.map(event => ({
-    ...event,
-    resourceRef,
-    isOwn: false,
-  }));
+  return fetched.map(event => ({ ...event, resourceRef }));

Change the helper return type to Omit<AggregatedResourceEvent, 'isOwn'>[] and let the caller at line 209 attach isOwn.

🤖 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
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceEventsTable.tsx`
around lines 149 - 159, Remove the misleading isOwn assignment from
fetchEventsForNode and change its return type to Omit<AggregatedResourceEvent,
'isOwn'>[]. Keep ownership assignment in the caller’s aggregation logic, where
source.id === node.id can determine the correct value.

195-198: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Reuse the eventSources memo, and derive truncatedChildren.

The effect recomputes collectEventSourceNodes(node, allNodes) at line 195. The eventSources memo at line 177 already holds the same value for the same inputs. Two independent computations of the fetch set can diverge later. The hint at line 304 reads eventSources.length while the fetch uses sources.

truncatedChildren is a pure function of children and eventSources. Derive it with useMemo instead of storing it in state and setting it inside the effect. This removes one render pass and one source of stale state.

♻️ Proposed refactor
-  const [truncatedChildren, setTruncatedChildren] = useState(0);
+  const truncatedChildren = useMemo(
+    () => Math.max(0, children.length - (eventSources.length - 1)),
+    [children.length, eventSources.length],
+  );
       try {
-        const sources = collectEventSourceNodes(node, allNodes);
-        setTruncatedChildren(
-          Math.max(0, children.length - (sources.length - 1)),
-        );
-
         const batches = await Promise.all(
-          sources.map(async source => {
+          eventSources.map(async source => {

Then replace node, allNodes, and children.length in the dependency array at lines 256-258 with eventSources and node.id.

🤖 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
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceEventsTable.tsx`
around lines 195 - 198, Reuse the existing eventSources memo in the fetch effect
instead of recomputing collectEventSourceNodes, and update the fetch logic to
use eventSources consistently. Replace truncatedChildren state and its
effect-based setter with a useMemo derived from children and eventSources, then
update the effect dependencies to use eventSources and node.id rather than node,
allNodes, and children.length.

272-316: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Extract the child display limit, and merge the duplicated hint blocks.

The literal 12 appears at lines 272, 300, and 301, and the complementary condition repeats at line 308. If one occurrence changes, the hint text no longer matches the rendered list.

The string 'Events below include this resource and its children.' appears at line 305 and line 314. The two Typography blocks are mutually exclusive and produce the same element. One block with a conditional prefix covers both cases.

♻️ Proposed refactor

Add a constant near MAX_EVENT_SOURCE_NODES usage:

/** Max child resources listed above the events table. */
const MAX_LISTED_CHILDREN = 12;
-            {children.slice(0, 12).map(child => (
+            {children.slice(0, MAX_LISTED_CHILDREN).map(child => (
-          {(children.length > 12 || truncatedChildren > 0) && (
-            <Typography
-              variant="caption"
-              color="textSecondary"
-              className={classes.sectionHint}
-            >
-              {children.length > 12
-                ? `Showing 12 of ${children.length} children. `
-                : ''}
-              {truncatedChildren > 0
-                ? `Events fetched for ${eventSources.length} resources (unhealthy first).`
-                : 'Events below include this resource and its children.'}
-            </Typography>
-          )}
-          {children.length <= 12 && truncatedChildren === 0 && (
-            <Typography
-              variant="caption"
-              color="textSecondary"
-              className={classes.sectionHint}
-            >
-              Events below include this resource and its children.
-            </Typography>
-          )}
+          <Typography
+            variant="caption"
+            color="textSecondary"
+            className={classes.sectionHint}
+          >
+            {children.length > MAX_LISTED_CHILDREN
+              ? `Showing ${MAX_LISTED_CHILDREN} of ${children.length} children. `
+              : ''}
+            {truncatedChildren > 0
+              ? `Events fetched for ${eventSources.length} resources (unhealthy first).`
+              : 'Events below include this resource and its children.'}
+          </Typography>
🤖 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
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceEventsTable.tsx`
around lines 272 - 316, Extract the child display limit into a named constant
near the existing MAX_EVENT_SOURCE_NODES constant, then use it for slicing,
truncation checks, and “Showing” text in ResourceEventsTable. Merge the mutually
exclusive sectionHint Typography blocks into one, conditionally rendering the
“Showing…” prefix while always preserving the shared events description.

200-218: 🚀 Performance & Scalability | 🔵 Trivial

Consider limiting fetch concurrency.

This block issues up to MAX_EVENT_SOURCE_NODES (25) requests at once when the user opens the Events tab on a large parent resource. The browser queues them against the per-host connection limit, and the backend receives a burst per drawer open. Each request also has no explicit timeout, so one slow child request delays Promise.all and keeps the spinner visible.

Two options:

  • Run the requests in small batches, for example 5 at a time.
  • Render the selected resource events first, then merge child results as they arrive.

The per-source catch at line 213 correctly keeps one failed child from failing the whole view.

🤖 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
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceEventsTable.tsx`
around lines 200 - 218, Limit concurrency in the source-fetching block around
fetchEventsForNode by processing sources in small batches (for example, five at
a time) instead of issuing all requests through one Promise.all. Preserve the
per-source catch behavior that returns an empty AggregatedResourceEvent[] and
continue aggregating every successful batch result.
🤖 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
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceEventsTable.tsx`:
- Around line 220-234: Update the merged-event handling in ResourceEventsTable
so timestamps are compared with an explicit NaN-safe fallback for empty or
invalid lastTimestamp values, preserving deterministic ordering. After sorting,
cap the displayed list to 25 events using a MAX_AGGREGATED_EVENTS constant,
while retaining the existing setEvents flow and optionally indicating truncation
in the UI.

In
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/resourceTreeDescendants.ts`:
- Around line 15-30: The hasAncestor function in resourceTreeDescendants.ts must
prevent cyclic and repeated ancestor traversal by accepting and propagating a
visited Set<string>, returning false when node.id is already visited. In
resourceTreeDescendants.test.ts, add coverage for mutually referencing nodes
completing without recursion failure and for a diamond-shaped graph where
collectDescendantNodes reports the shared descendant only once; apply the
changes at both specified sites.

---

Nitpick comments:
In
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceEventsTable.tsx`:
- Around line 149-159: Remove the misleading isOwn assignment from
fetchEventsForNode and change its return type to Omit<AggregatedResourceEvent,
'isOwn'>[]. Keep ownership assignment in the caller’s aggregation logic, where
source.id === node.id can determine the correct value.
- Around line 195-198: Reuse the existing eventSources memo in the fetch effect
instead of recomputing collectEventSourceNodes, and update the fetch logic to
use eventSources consistently. Replace truncatedChildren state and its
effect-based setter with a useMemo derived from children and eventSources, then
update the effect dependencies to use eventSources and node.id rather than node,
allNodes, and children.length.
- Around line 272-316: Extract the child display limit into a named constant
near the existing MAX_EVENT_SOURCE_NODES constant, then use it for slicing,
truncation checks, and “Showing” text in ResourceEventsTable. Merge the mutually
exclusive sectionHint Typography blocks into one, conditionally rendering the
“Showing…” prefix while always preserving the shared events description.
- Around line 200-218: Limit concurrency in the source-fetching block around
fetchEventsForNode by processing sources in small batches (for example, five at
a time) instead of issuing all requests through one Promise.all. Preserve the
per-source catch behavior that returns an empty AggregatedResourceEvent[] and
continue aggregating every successful batch result.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 164ebbd4-44b6-4415-a322-4a6e68a3764c

📥 Commits

Reviewing files that changed from the base of the PR and between 67ba0da and 2971de5.

📒 Files selected for processing (8)
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceDetailPanel.test.tsx
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceDetailPanel.tsx
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceDetailTabs.test.tsx
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceDetailTabs.tsx
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceEventsTable.tsx
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceTreeView.tsx
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/resourceTreeDescendants.test.ts
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/resourceTreeDescendants.ts

Comment on lines +15 to +30
export function hasAncestor(
node: LayoutNode,
ancestorId: string,
nodesById: Map<string, LayoutNode>,
): boolean {
for (const parentId of node.parentIds) {
if (parentId === ancestorId) {
return true;
}
const parent = nodesById.get(parentId);
if (parent && hasAncestor(parent, ancestorId, nodesById)) {
return true;
}
}
return false;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Unguarded ancestor traversal, and no test coverage for it. hasAncestor walks parentIds recursively with no visited set. A cycle in the node graph causes non-terminating recursion, and a diamond-shaped DAG causes repeated traversal of shared ancestors. The current tests only cover a strict tree, so neither case is detected.

  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/resourceTreeDescendants.ts#L15-L30: add a visited: Set<string> parameter, return false when node.id is already present, and pass the set through the recursive call.
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/resourceTreeDescendants.test.ts#L67-L73: add two cases — a node pair whose parentIds reference each other, which must return without hanging, and a node reachable through two distinct parent paths, which must be reported once by collectDescendantNodes.
📍 Affects 2 files
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/resourceTreeDescendants.ts#L15-L30 (this comment)
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/resourceTreeDescendants.test.ts#L67-L73
🤖 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
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/resourceTreeDescendants.ts`
around lines 15 - 30, The hasAncestor function in resourceTreeDescendants.ts
must prevent cyclic and repeated ancestor traversal by accepting and propagating
a visited Set<string>, returning false when node.id is already visited. In
resourceTreeDescendants.test.ts, add coverage for mutually referencing nodes
completing without recursion failure and for a diamond-shaped graph where
collectDescendantNodes reports the shared descendant only once; apply the
changes at both specified sites.

@artemiyokulov
artemiyokulov force-pushed the feat/resource-drawer-child-events branch from 2971de5 to 0693e77 Compare August 7, 2026 07:32
Attach Flux inventory workloads under their HelmRelease so Deployment/Pod
appear as separate tree nodes with their own Events tabs, instead of flat
siblings under RenderedRelease.

Signed-off-by: Artemy Okulov <artemy.okulov@x5.ru>
Co-authored-by: Cursor <cursoragent@cursor.com>
@artemiyokulov artemiyokulov changed the title feat: aggregate child resource events in release tree drawer feat: nest HelmRelease inventory children in resource tree Aug 7, 2026
@artemiyokulov
artemiyokulov force-pushed the feat/resource-drawer-child-events branch from 0693e77 to 5cd20a4 Compare August 7, 2026 08:30
@coderabbitai

coderabbitai Bot commented Aug 7, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 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
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/helmInventoryNesting.ts`:
- Around line 74-75: Update resourceKey to include the API group in its
generated key, then pass parsed.group and node.group at its two call sites so
resources from different groups remain distinct. Add a test covering
same-namespace, kind, and name resources from different API groups and verify
they do not collide or get incorrectly reparented.
- Around line 87-137: Scope the nesting logic in helmInventoryNesting to the
current RenderedRelease identified by releaseNodeId: filter helmReleases and
candidate nodes to that release before counting or reparenting, so prior
releases cannot affect the single-HelmRelease fallback or resource matching. Add
a regression test covering two rendered releases and verify resources from the
earlier release remain unchanged.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 32369387-bf7c-469a-873d-f671d531c806

📥 Commits

Reviewing files that changed from the base of the PR and between 67ba0da and 5cd20a4.

📒 Files selected for processing (6)
  • .changeset/resource-tree-helm-children.md
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/ResourceEventsTable.tsx
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/helmInventoryNesting.test.ts
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/helmInventoryNesting.ts
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/treeLayoutUtils.test.ts
  • plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/treeLayoutUtils.ts

Comment on lines +74 to +75
function resourceKey(kind: string, name: string, namespace?: string): string {
return `${namespace ?? ''}/${kind}/${name}`;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Include the API group in the inventory key.

Line 74 discards parsed.group, while each TreeNode also has group. Resources from different API groups can have the same namespace, kind, and name. Line 122 can then reparent both resources under the HelmRelease.

Add group to resourceKey, and pass parsed.group and node.group at the two call sites. Add a collision test.

🤖 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
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/helmInventoryNesting.ts`
around lines 74 - 75, Update resourceKey to include the API group in its
generated key, then pass parsed.group and node.group at its two call sites so
resources from different groups remain distinct. Add a test covering
same-namespace, kind, and name resources from different API groups and verify
they do not collide or get incorrectly reparented.

Comment on lines +87 to +137
const helmReleases = nodes.filter(n => n.kind === 'HelmRelease');
if (helmReleases.length === 0) {
return;
}

for (const hr of helmReleases) {
const inventoryKeys = new Set<string>();
const entries =
(
hr.specObject as
| { status?: { inventory?: { entries?: Array<{ id?: string }> } } }
| undefined
)?.status?.inventory?.entries ?? [];

for (const entry of entries) {
const parsed = parseFluxHelmInventoryEntryId(String(entry?.id || ''));
if (!parsed?.kind || !parsed?.name) {
continue;
}
inventoryKeys.add(
resourceKey(parsed.kind, parsed.name, parsed.namespace),
);
}

for (const node of nodes) {
if (node.id === hr.id || node.isRoot || node.kind === 'RenderedRelease') {
continue;
}

const key = resourceKey(node.kind, node.name, node.namespace);
const listedInInventory = inventoryKeys.has(key);
const onlyUnderRelease =
node.parentIds.length === 1 && node.parentIds[0] === releaseNodeId;
const alreadyUnderHr = node.parentIds.includes(hr.id);

if (listedInInventory && !alreadyUnderHr) {
node.parentIds = [hr.id];
continue;
}

if (
onlyUnderRelease &&
helmReleases.length === 1 &&
(node.kind === 'Deployment' ||
node.kind === 'StatefulSet' ||
node.kind === 'DaemonSet' ||
node.kind === 'PersistentVolumeClaim') &&
!alreadyUnderHr
) {
node.parentIds = [hr.id];
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Scope nesting to the current RenderedRelease.

buildTreeNodes calls this helper after each rendered release, but nodes contains nodes from earlier releases. Line 87 counts HelmReleases from every rendered release. This disables the single-HelmRelease fallback when another rendered release has a HelmRelease. It can also reparent an earlier release resource when the current inventory has the same resource key.

Filter both HelmReleases and candidate nodes to releaseNodeId, or pass only the current release node set to this helper. Add a two-rendered-release regression test.

🤖 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
`@plugins/openchoreo/src/components/Environments/ReleaseDataRenderer/ResourceTreeView/helmInventoryNesting.ts`
around lines 87 - 137, Scope the nesting logic in helmInventoryNesting to the
current RenderedRelease identified by releaseNodeId: filter helmReleases and
candidate nodes to that release before counting or reparenting, so prior
releases cannot affect the single-HelmRelease fallback or resource matching. Add
a regression test covering two rendered releases and verify resources from the
earlier release remain unchanged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants