Skip to content

EDM-3529: Properly set default for new device img. Do not require con…#574

Merged
rawagner merged 1 commit intoflightctl:mainfrom
rawagner:fix_new_device
Mar 17, 2026
Merged

EDM-3529: Properly set default for new device img. Do not require con…#574
rawagner merged 1 commit intoflightctl:mainfrom
rawagner:fix_new_device

Conversation

@rawagner
Copy link
Collaborator

@rawagner rawagner commented Mar 17, 2026

…firmation when clicking on close

Summary by CodeRabbit

Release Notes

  • Bug Fixes
    • Modified confirmation dialog behavior to prevent unnecessary prompts during new device selection in the installation wizard.
    • Refined artifact filtering logic to ensure only compatible versions matching your current configuration are displayed during the installation process.

@coderabbitai
Copy link

coderabbitai bot commented Mar 17, 2026

Walkthrough

These changes modify the InstallWizard component flow by conditionally hiding a leave confirmation dialog when targeting a new device, and refactoring artifact filtering in the SelectTargetStep to use only artifacts present in the current version's references.

Changes

Cohort / File(s) Summary
InstallWizard Confirmation & Artifact Filtering
libs/ui-components/src/components/Catalog/InstallWizard/InstallOsWizard.tsx, libs/ui-components/src/components/Catalog/InstallWizard/steps/SelectTargetStep.tsx
Updated conditional rendering of LeaveFormConfirmation to exclude it when target is 'new-device' and on selectTargetStepId step. Refactored artifact selection in NewDeviceTarget to filter by current version references, updated useEffect dependencies to include deploymentTarget, and simplified FormSelect items generation logic.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title partially relates to the changeset. It mentions setting a default for new device image and not requiring confirmation on close, which are addressed in the PR objectives and code changes, but is truncated and incomplete.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
📝 Coding Plan
  • Generate coding plan for human review comments

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.

Copy link

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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@libs/ui-components/src/components/Catalog/InstallWizard/steps/SelectTargetStep.tsx`:
- Around line 227-230: The current effect only sets a default when
values.deploymentTarget is falsy, leaving a stale deploymentTarget if the
selected version's artifacts no longer include that type; update the effect
watching artifacts and values.deploymentTarget to check whether
values.deploymentTarget exists in artifacts.map(a => a.type) and if not call
setFieldValue('deploymentTarget', artifacts.length ? artifacts[0].type :
undefined) (or null) so the field is reset to a valid option or cleared;
reference values.deploymentTarget, artifacts, and setFieldValue in the
SelectTargetStep effect when implementing this change.
- Around line 220-223: The current render builds the artifact list by calling
.sort() directly on catalogItem.spec.artifacts (used in SelectTargetStep), which
mutates the source; change the pipeline that produces the sorted list to operate
on an immutable copy (e.g., clone via slice() or spread) before calling sort,
keep the existing filter that uses versionRefs (from const versionRefs =
catalogItem.spec.versions.find(...)?), and ensure you still call
getArtifactLabel(t, a.type, a.name) for comparison—this prevents side effects
across consumers of catalogItem.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 50a0a671-d05f-4374-bdcc-f60052f9ccb9

📥 Commits

Reviewing files that changed from the base of the PR and between 0155317 and 02171e5.

📒 Files selected for processing (2)
  • libs/ui-components/src/components/Catalog/InstallWizard/InstallOsWizard.tsx
  • libs/ui-components/src/components/Catalog/InstallWizard/steps/SelectTargetStep.tsx

Comment on lines +220 to +223
const versionRefs = catalogItem.spec.versions.find((v) => v.version === values.version)?.references || {};
return catalogItem.spec.artifacts
?.sort((a, b) => getArtifactLabel(t, a.type, a.name).localeCompare(getArtifactLabel(t, b.type, b.name)))
.filter((a) => Object.keys(versionRefs).includes(a.type));
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify this in-place sort usage in the changed file
rg -nP --type=tsx 'catalogItem\.spec\.artifacts\s*\??\.sort\('

Repository: flightctl/flightctl-ui

Length of output: 93


🏁 Script executed:

fd "SelectTargetStep.tsx" --type f

Repository: flightctl/flightctl-ui

Length of output: 148


🏁 Script executed:

wc -l libs/ui-components/src/components/Catalog/InstallWizard/steps/SelectTargetStep.tsx

Repository: flightctl/flightctl-ui

Length of output: 152


🏁 Script executed:

sed -n '210,260p' libs/ui-components/src/components/Catalog/InstallWizard/steps/SelectTargetStep.tsx

Repository: flightctl/flightctl-ui

Length of output: 2083


🏁 Script executed:

sed -n '1,220p' libs/ui-components/src/components/Catalog/InstallWizard/steps/SelectTargetStep.tsx | tail -30

Repository: flightctl/flightctl-ui

Length of output: 1049


🏁 Script executed:

sed -n '200,225p' libs/ui-components/src/components/Catalog/InstallWizard/steps/SelectTargetStep.tsx

Repository: flightctl/flightctl-ui

Length of output: 917


🏁 Script executed:

# Check if catalogItem type definition confirms spec.artifacts is array from API
rg "spec\s*:\s*{" libs/ui-components/src/components/Catalog/InstallWizard/steps/SelectTargetStep.tsx -A 10

Repository: flightctl/flightctl-ui

Length of output: 153


🏁 Script executed:

# Search for CatalogItem type definition
rg "type CatalogItem|interface CatalogItem" -A 5

Repository: flightctl/flightctl-ui

Length of output: 6812


🏁 Script executed:

cat libs/types/alpha/models/CatalogItemSpec.ts

Repository: flightctl/flightctl-ui

Length of output: 1888


🏁 Script executed:

# Check if catalogItem comes from API/parent by looking at how NewDeviceTarget is used
rg "NewDeviceTarget" -B 5 -A 2 | head -40

Repository: flightctl/flightctl-ui

Length of output: 2178


Avoid mutating catalogItem.spec.artifacts in render-time memo.

Line 222 calls .sort() directly on catalogItem.spec.artifacts, which mutates the source array and can cause side effects across consumers of the same object.

Suggested fix
-  return catalogItem.spec.artifacts
-    ?.sort((a, b) => getArtifactLabel(t, a.type, a.name).localeCompare(getArtifactLabel(t, b.type, b.name)))
-    .filter((a) => Object.keys(versionRefs).includes(a.type));
+  const refTypes = new Set(Object.keys(versionRefs));
+  return [...catalogItem.spec.artifacts]
+    .filter((a) => refTypes.has(a.type))
+    .sort((a, b) => getArtifactLabel(t, a.type, a.name).localeCompare(getArtifactLabel(t, b.type, b.name)));
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const versionRefs = catalogItem.spec.versions.find((v) => v.version === values.version)?.references || {};
return catalogItem.spec.artifacts
?.sort((a, b) => getArtifactLabel(t, a.type, a.name).localeCompare(getArtifactLabel(t, b.type, b.name)))
.filter((a) => Object.keys(versionRefs).includes(a.type));
const versionRefs = catalogItem.spec.versions.find((v) => v.version === values.version)?.references || {};
const refTypes = new Set(Object.keys(versionRefs));
return (catalogItem.spec.artifacts || [])
.filter((a) => refTypes.has(a.type))
.sort((a, b) => getArtifactLabel(t, a.type, a.name).localeCompare(getArtifactLabel(t, b.type, b.name)));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libs/ui-components/src/components/Catalog/InstallWizard/steps/SelectTargetStep.tsx`
around lines 220 - 223, The current render builds the artifact list by calling
.sort() directly on catalogItem.spec.artifacts (used in SelectTargetStep), which
mutates the source; change the pipeline that produces the sorted list to operate
on an immutable copy (e.g., clone via slice() or spread) before calling sort,
keep the existing filter that uses versionRefs (from const versionRefs =
catalogItem.spec.versions.find(...)?), and ensure you still call
getArtifactLabel(t, a.type, a.name) for comparison—this prevents side effects
across consumers of catalogItem.

Comment on lines +227 to +230
if (!values.deploymentTarget && artifacts.length) {
setFieldValue('deploymentTarget', artifacts[0].type);
}
}, [values, artifacts, setFieldValue]);
}, [artifacts, values.deploymentTarget, setFieldValue]);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Reset deploymentTarget when it becomes invalid for the selected version.

Line 227 only sets a default when deploymentTarget is empty. If version changes and the currently selected type is no longer present in artifacts, stale state remains.

Suggested fix
 React.useEffect(() => {
-  if (!values.deploymentTarget && artifacts.length) {
-    setFieldValue('deploymentTarget', artifacts[0].type);
-  }
+  const isCurrentSelectionValid = artifacts.some((a) => a.type === values.deploymentTarget);
+  if (!isCurrentSelectionValid) {
+    setFieldValue('deploymentTarget', artifacts[0]?.type);
+  }
 }, [artifacts, values.deploymentTarget, setFieldValue]);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@libs/ui-components/src/components/Catalog/InstallWizard/steps/SelectTargetStep.tsx`
around lines 227 - 230, The current effect only sets a default when
values.deploymentTarget is falsy, leaving a stale deploymentTarget if the
selected version's artifacts no longer include that type; update the effect
watching artifacts and values.deploymentTarget to check whether
values.deploymentTarget exists in artifacts.map(a => a.type) and if not call
setFieldValue('deploymentTarget', artifacts.length ? artifacts[0].type :
undefined) (or null) so the field is reset to a valid option or cleared;
reference values.deploymentTarget, artifacts, and setFieldValue in the
SelectTargetStep effect when implementing this change.

@rawagner rawagner merged commit b75d779 into flightctl:main Mar 17, 2026
6 checks passed
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