Skip to content

ECOPROJECT-4793 | feat: add rightsizing information in the cluster recommendation output#766

Open
ammont82 wants to merge 1 commit into
kubev2v:masterfrom
ammont82:ECOPROJECT-4793
Open

ECOPROJECT-4793 | feat: add rightsizing information in the cluster recommendation output#766
ammont82 wants to merge 1 commit into
kubev2v:masterfrom
ammont82:ECOPROJECT-4793

Conversation

@ammont82

@ammont82 ammont82 commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

Summary by CodeRabbit

  • New Features

    • Added utilization-based cluster sizing comparison view displaying baseline allocation versus recommendations based on actual usage patterns.
    • Infrastructure savings calculations now visible, including estimated cost reductions and confidence metrics.
  • Chores

    • Updated @openshift-migration-advisor/planner-sdk dependency to latest version.

…commendation output

Signed-off-by: Montse Ortega <mortegag@redhat.com>
@openshift-ci

openshift-ci Bot commented Jun 15, 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 assign nirarg for approval. 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

@coderabbitai

coderabbitai Bot commented Jun 15, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds utilization-based cluster sizing comparison: a new utilizationSizing.ts module with a type guard, formatters, and compute helpers; a UtilizationComparisonCards React component showing baseline vs. recommended sizing; conditional rendering in SizingResult and ClusterSizingWizard; an alternate plain-text recommendation path; new SDK type re-exports; and full unit/render tests.

Changes

Utilization Comparison Sizing Feature

Layer / File(s) Summary
SDK upgrade and new type exports
package.json, src/ui/report/views/cluster-sizer/types.ts
Upgrades @openshift-migration-advisor/planner-sdk from ^0.13.4 to ^0.13.6 and re-exports OptimizationStatus and Savings types.
utilizationSizing utilities
src/ui/report/views/cluster-sizer/utilizationSizing.ts
Defines UtilizationComparisonResponse type, hasUtilizationComparison type guard (confidence threshold + success-reason check), formatUtilizationPercent, computeEffectiveCpu, and computeEffectiveMemory.
UtilizationComparisonCards component
src/ui/report/views/cluster-sizer/UtilizationComparisonCards.tsx
New PatternFly Grid-based component rendering a baseline card (100% allocation) and a recommended card (actual usage), with a DetailRow helper, conditional single-node rows, and a savings banner.
Conditional rendering in SizingResult and ClusterSizingWizard
src/ui/report/views/cluster-sizer/SizingResult.tsx, src/ui/report/views/cluster-sizer/ClusterSizingWizard.tsx
SizingResult returns UtilizationComparisonCards early when hasUtilizationComparison is true; ClusterSizingWizard suppresses the architecture tab alert in that same condition.
Plain-text recommendation alternate path
src/ui/report/view-models/ClusterSizingHelpers.ts
generatePlainTextRecommendation gains an early branch for utilization-comparison outputs that returns a formatted text block with effective CPU/memory, confidence, and savings instead of the existing layout.
Tests and mocks
src/ui/report/views/cluster-sizer/__tests__/utilizationSizing.test.ts, src/ui/report/views/cluster-sizer/__tests__/SizingResult.test.tsx, src/ui/report/views/cluster-sizer/__tests__/mocks/ClusterRequirementsResponse.mock.ts
Adds mockUtilizationComparisonResponse fixture, extends the mock factory with optimizedSizing/savings/optimizationStatus, adds unit tests for all utilizationSizing utilities, and adds a SizingResult render test for the utilization comparison path.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SizingResult
    participant hasUtilizationComparison
    participant UtilizationComparisonCards
    participant computeEffectiveCpu/Memory

    User->>SizingResult: renders with sizerOutput
    SizingResult->>hasUtilizationComparison: check(sizerOutput)
    alt utilization comparison present
        hasUtilizationComparison-->>SizingResult: true (UtilizationComparisonResponse)
        SizingResult->>UtilizationComparisonCards: render(sizerOutput, formValues)
        UtilizationComparisonCards->>computeEffectiveCpu/Memory: scale inventory by utilization %
        computeEffectiveCpu/Memory-->>UtilizationComparisonCards: effective CPU / memory
        UtilizationComparisonCards-->>User: baseline + recommended cards with savings banner
    else no utilization comparison
        hasUtilizationComparison-->>SizingResult: false
        SizingResult-->>User: existing description-list sizing UI
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • kubev2v/migration-planner-ui-app#759: Touches src/ui/report/views/cluster-sizer/types.ts to extend planner-SDK sizing type exports, which this PR builds on for OptimizationStatus and Savings.

Suggested labels

lgtm, approved, ready-to-review

Suggested reviewers

  • rh-gvincent
  • jkilzi

Poem

🐇 Hop, hop, a new card appears,
Two columns side by side — the cluster cheers!
Utilization measured, savings shown,
Effective CPU and memory grown.
With confidence high and a percent saved,
This bunny's sizing path is freshly paved! 🌿

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding rightsizing information to cluster recommendation output, which aligns with all file modifications introducing utilization comparison UI and utilities.
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.

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

✨ 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 and usage tips.

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

🧹 Nitpick comments (2)
src/ui/report/views/cluster-sizer/__tests__/utilizationSizing.test.ts (1)

53-70: ⚡ Quick win

Add explicit edge-case tests for nullable/undefined branches.

Please add assertions for hasUtilizationComparison(undefined/null) and formatUtilizationPercent(undefined) to lock down the public helper contract.

Suggested test additions
 describe("hasUtilizationComparison", () => {
+  it("returns false for null/undefined output", () => {
+    expect(hasUtilizationComparison(undefined)).toBe(false);
+    expect(hasUtilizationComparison(null)).toBe(false);
+  });
+
   it("returns true when optimization succeeded with confidence above 50%", () => {
 describe("formatUtilizationPercent", () => {
   it("formats values with one decimal place", () => {
     expect(formatUtilizationPercent(45.2)).toBe("45.2%");
     expect(formatUtilizationPercent(87.5)).toBe("87.5%");
   });
+
+  it("returns em dash when value is undefined", () => {
+    expect(formatUtilizationPercent(undefined)).toBe("—");
+  });
 });
🤖 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 `@src/ui/report/views/cluster-sizer/__tests__/utilizationSizing.test.ts` around
lines 53 - 70, Add explicit edge-case test assertions to validate the behavior
of public helper functions when passed undefined or null values. Create test
cases for hasUtilizationComparison function with both undefined and null
arguments to verify it handles these nullable inputs correctly, and add a test
case for formatUtilizationPercent function with an undefined argument to ensure
it gracefully handles undefined values. These tests should be added to their
respective describe blocks in the test file to lock down the public contract of
these utility functions.
src/ui/report/views/cluster-sizer/utilizationSizing.ts (1)

1-44: ⚡ Quick win

Rename this file to match src/** file naming rules.

utilizationSizing.ts is camelCase, but non-hook files under src/** are required to be PascalCase. Please rename it (for example, UtilizationSizing.ts) and update imports accordingly in the touched call sites.

As per coding guidelines, src/**: "File naming: files are PascalCase, hooks (use*) are camelCase, index/constants/types/styles are all-lowercase, directories are kebab-case."

🤖 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 `@src/ui/report/views/cluster-sizer/utilizationSizing.ts` around lines 1 - 44,
The file utilizationSizing.ts violates the naming convention for non-hook files
under src/**, which require PascalCase naming. Rename the file from
utilizationSizing.ts to UtilizationSizing.ts and update all imports of this file
at the touched call sites to reference the new file name.

Source: Coding guidelines

🤖 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/ui/report/views/cluster-sizer/UtilizationComparisonCards.tsx`:
- Around line 133-147: The UtilizationComparisonCards view component contains
business logic for data derivation (computing isSNO, extracting utilization
values, calculating effectiveCpu and effectiveMemory via computeEffectiveCpu and
computeEffectiveMemory functions, and computing savingsPercent) which violates
the guideline that views should be render-only. Create a custom view-model hook
(e.g., useUtilizationComparisonData) that takes the necessary inputs
(formValues, optimizedSizing, inventoryTotals, savings) and returns all these
computed values as an object, then replace all these derivation statements in
the component with a single call to that hook at the top of the component,
keeping the view focused solely on rendering.

---

Nitpick comments:
In `@src/ui/report/views/cluster-sizer/__tests__/utilizationSizing.test.ts`:
- Around line 53-70: Add explicit edge-case test assertions to validate the
behavior of public helper functions when passed undefined or null values. Create
test cases for hasUtilizationComparison function with both undefined and null
arguments to verify it handles these nullable inputs correctly, and add a test
case for formatUtilizationPercent function with an undefined argument to ensure
it gracefully handles undefined values. These tests should be added to their
respective describe blocks in the test file to lock down the public contract of
these utility functions.

In `@src/ui/report/views/cluster-sizer/utilizationSizing.ts`:
- Around line 1-44: The file utilizationSizing.ts violates the naming convention
for non-hook files under src/**, which require PascalCase naming. Rename the
file from utilizationSizing.ts to UtilizationSizing.ts and update all imports of
this file at the touched call sites to reference the new file name.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: bcb2851a-628a-4121-a374-30b74097fea3

📥 Commits

Reviewing files that changed from the base of the PR and between 0713bb0 and 8668de1.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (10)
  • package.json
  • src/ui/report/view-models/ClusterSizingHelpers.ts
  • src/ui/report/views/cluster-sizer/ClusterSizingWizard.tsx
  • src/ui/report/views/cluster-sizer/SizingResult.tsx
  • src/ui/report/views/cluster-sizer/UtilizationComparisonCards.tsx
  • src/ui/report/views/cluster-sizer/__tests__/SizingResult.test.tsx
  • src/ui/report/views/cluster-sizer/__tests__/mocks/ClusterRequirementsResponse.mock.ts
  • src/ui/report/views/cluster-sizer/__tests__/utilizationSizing.test.ts
  • src/ui/report/views/cluster-sizer/types.ts
  • src/ui/report/views/cluster-sizer/utilizationSizing.ts

Comment on lines +133 to +147
const isSNO = formValues.clusterMode === "single-node";

const cpuUtilization = optimizedSizing.cpuUtilizationMax;
const memoryUtilization = optimizedSizing.memoryUtilizationMax;
const effectiveCpu = computeEffectiveCpu(
inventoryTotals.totalCPU,
cpuUtilization,
);
const effectiveMemory = computeEffectiveMemory(
inventoryTotals.totalMemory,
memoryUtilization,
);

const savingsPercent = Math.round(savings.percentageReduction);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Move derived sizing computations into a view-model hook.

This view currently performs business/data-derivation logic (isSNO, effective CPU/memory, savings percent) instead of staying render-only.

Suggested direction
- export const UtilizationComparisonCards: React.FC<
-   UtilizationComparisonCardsProps
- > = ({ sizerOutput, formValues }) => {
-   const { clusterSizing, optimizedSizing, savings, inventoryTotals } =
-     sizerOutput;
-   const isSNO = formValues.clusterMode === "single-node";
-   const cpuUtilization = optimizedSizing.cpuUtilizationMax;
-   const memoryUtilization = optimizedSizing.memoryUtilizationMax;
-   const effectiveCpu = computeEffectiveCpu(
-     inventoryTotals.totalCPU,
-     cpuUtilization,
-   );
-   const effectiveMemory = computeEffectiveMemory(
-     inventoryTotals.totalMemory,
-     memoryUtilization,
-   );
-   const savingsPercent = Math.round(savings.percentageReduction);
+ export const UtilizationComparisonCards: React.FC<
+   UtilizationComparisonCardsProps
+ > = ({ sizerOutput, formValues }) => {
+   const vm = useUtilizationComparisonCardsViewModel({ sizerOutput, formValues });
+   const {
+     clusterSizing,
+     optimizedSizing,
+     savings,
+     isSNO,
+     cpuUtilization,
+     memoryUtilization,
+     effectiveCpu,
+     effectiveMemory,
+     savingsPercent,
+   } = vm;

As per coding guidelines, “Views in src/ui/*/views/ should render only with no business logic. Call view model hook at top.”

🤖 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 `@src/ui/report/views/cluster-sizer/UtilizationComparisonCards.tsx` around
lines 133 - 147, The UtilizationComparisonCards view component contains business
logic for data derivation (computing isSNO, extracting utilization values,
calculating effectiveCpu and effectiveMemory via computeEffectiveCpu and
computeEffectiveMemory functions, and computing savingsPercent) which violates
the guideline that views should be render-only. Create a custom view-model hook
(e.g., useUtilizationComparisonData) that takes the necessary inputs
(formValues, optimizedSizing, inventoryTotals, savings) and returns all these
computed values as an object, then replace all these derivation statements in
the component with a single call to that hook at the top of the component,
keeping the view focused solely on rendering.

Source: Coding guidelines

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.

1 participant