Conversation
illume
commented
Mar 3, 2026
- minikube: Fix useClustersConf import
- minikube: Use pluginPermissionSecrets with runCommand
- minikube: manage-minikube.js: Add minimal script for testing
- minikube: Use pluginRunCommand instead of runCommand
- minikube: index: Add button to help manually test more easily
- minikube: CommandCluster: Fix running command so it remembers
- minikube: windows: Add command for elevated privs and hyperv
- minikube: CommandCluster: Fix running command to remember
- minikube: manage-minikube: Add info command
- minikube: artifacthub-pkg: Update to minikube 1.36.0
- minikube: DriverSelect: Fix driver select not rendering
- minikube: DriverSelect: Update vfkit to non-experimental
- minikube: manage-minikube: Use require imports for compatibility
- minikube: Fix to detect windows paths for plugin path
- minikube: CommandCluster: Fix formatting turn debug off
- minikube: DriverSelect: Add useDrivers hook with detection logic
- minikube: CommandCluster: Use hyperv script to start/stop etc
- minikube: CommandCluster: Add detection of minikube profiles
- minikube: DriverSelect: Add loading state for driver loading
- minikube: CommandDialog: Fix cluster name input so can type again
- minikube: CommandDialog: Fix label so it does not cover input field
- minikube: Add logging
- minikube: Fix windows error with extra text
- minikube: Try throwing error to stop rest of script running.
- minikube: Put info in setImmediate
- minikube: Remove setImmediate
- minikube: manage-minikube: Add slow computer simulation for info
- minikube: CommandCluster: Add wait for driver detection
- minikube: cleanup
- minikube: CommandCluster: Add container runtime and CNI flags
- minikube: manage-minikube: Add minikube-profile and start-minikube-vfkit
- minikube: manage-minikube: Cleanups
- minikube: CommandCluster: Fix useMinikubeProfileList
- minikube: manage-minikube: Add freeRam in GB to info output
- minikube: manage-minikube: Add free disk and free memory warnings
- minikube: CommandCluster: Exract useInfo to own file
- minikube: package.json: Add testplugins script
- minikube: CommandCluster: Add extra addons for vfkit and hyperv
- minikube: artifacthub-pkg: Add vfkit to extra files for mac
- minikube: ClusterStatus: Add component to start/stop on home
- minikube: index: Add DEBUG mode
- minikube: Change title to "Create Local Cluster" on provider page
- minikube: Add ram default of 3072
- minikube: manage-minikube: Add enabling of hyperV if it is stopped
- minikube: Add detectIfHyperVEnabled check instead of just running
- minikube: manage-minikube: Add hyperv wrappers for stop and delete
- minikube: CommandCluster: Use wrapper for stop/delete on HyperV
- minikube: manage-minikube: CommandCluster: Add wait for info
- minikube: manage-minikube: Fix hyperv stop and delete commands
- minikube: manage-minikube: Flush stdout on info command
- minikube: Upgrade headlamp-plugin to 0.13.0-alpha.11
- minikube: CommandCluster: ClusterStatus: Add cancel handling
- minikube: manage-minikube: Add fallbacks on windows for wmic
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
This is so the runCommand will be allowed to work. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
5aadfb7 to
ab5b9f6
Compare
To see what services are running, and ram/free disk. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
This handles asking for admin rights as required. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
So that we can query their information, like the driver for the profile. This lets us use driver specific code if needed. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
There was a bug where the initial name is set, but you can't change it. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
So that it's easier to detect problems, and see load states. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Only show the start button once drivers have been detected. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
For copying changes to the testplugin repo. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
This is used by the minikube driver called vfkit on mac. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Hides the script button used for debugging. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
This is to reduce the amount given for lower ram machines. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
It can be after computer restart that HyperV service is not enabled. Without this minikube start does not work. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
It can be HyperV is disabled after computer restart, so a running check is not sufficient. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
This is so it can make sure the VM service is running and also ask for privs to do it. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Because how we act depends on the driver and OS. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Sometimes it was not writing all data to stdout before exiting. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
Signed-off-by: René Dudfield <renedudfield@microsoft.com>
If closing on cancel we do not need to reload the page. So clicking stop on a cluster and then cancel does not reload the page. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
On some systems wmic is not installed. Signed-off-by: René Dudfield <renedudfield@microsoft.com>
ab5b9f6 to
9e3f586
Compare
There was a problem hiding this comment.
Pull request overview
This PR updates the Headlamp minikube plugin to improve local cluster creation/management across OSes (notably Windows Hyper-V and macOS vfkit), adds an external helper script, and enhances the UI with driver detection and status controls.
Changes:
- Adds
manage-minikube.jshelper script and bundles it viaheadlamp.extraDist, plus a devtestpluginsscript. - Introduces an
useInfo()hook to detect system/minikube profile info and uses it to drive driver selection + warnings. - Adds a
ClusterStatusUI integration (viaregisterClusterStatus) and updates command handling to support Hyper-V/vfkit flows.
Reviewed changes
Copilot reviewed 10 out of 11 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| minikube/src/index.tsx | Registers new app-bar/debug action (guarded), cluster status integration, and renames provider title. |
| minikube/src/CreateClusterPage.tsx | Removes finishedText usage from CommandCluster. |
| minikube/src/CommandCluster/useInfo.ts | New hook that runs manage-minikube.js info and parses JSON into UI state. |
| minikube/src/CommandCluster/DriverSelect.tsx | Adds driver detection ordering logic and a loading state. |
| minikube/src/CommandCluster/CommandDialog.tsx | Adds info-driven warnings and changes driver/close handling semantics. |
| minikube/src/CommandCluster/CommandCluster.tsx | Refactors command execution to “remember” running commands and adds Hyper-V/vfkit handling via helper script. |
| minikube/src/ClusterStatus.tsx | New home/status widget to start/stop minikube clusters. |
| minikube/package.json | Bundles manage-minikube.js into dist and adds a testplugins script. |
| minikube/manage-minikube.js | New cross-platform helper script (info, vfkit setup, Hyper-V privileged wrappers). |
| minikube/artifacthub-pkg.yml | Updates minikube artifacts to v1.36.0 and adds vfkit extra files for macOS. |
Comments suppressed due to low confidence (2)
minikube/src/CommandCluster/CommandDialog.tsx:179
driverstate isstring | null, butonConfirmis typed to require{ driver: string }and you passdriverthrough directly. This is a compile-time type error (and a runtime issue ifnullslips through). Either makedriveralways a string before enabling the action (e.g., default to''/first detected driver) or change theonConfirmcontract and handlenullexplicitly.
{!useGrid && <Button onClick={() => onClose(true)}>Cancel</Button>}
<Button
onClick={() => {
if (clusterName) {
onConfirm({ clusterName, driver });
}
}}
minikube/src/CommandCluster/DriverSelect.tsx:203
Selectis rendered withvalue={driver}wheredrivercan benull(initial state). MUI Select expects a string/number value (typically''for “no selection”), andnullcan cause warnings and inconsistent behavior. Consider usingvalue={driver ?? ''}(and/or initializedriverto'') so the component stays controlled.
<FormControl>
<Select
labelId="driver-select-label"
id="driver-select"
value={driver}
label="Driver"
displayEmpty
onChange={handleChange}
aria-labelledby="driver-select-label"
>
{drivers.map(dr => (
<MenuItem key={dr.value} value={dr.value}>
{dr.label}
</MenuItem>
))}
</Select>
</FormControl>
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| > | ||
| {/* <Icon icon="mdi:play" width={16} height={16} color={theme.palette.home.status.error} /> */} | ||
| <Icon icon="mdi:play" width={16} height={16} color={theme.palette.common.primary} /> | ||
| </IconButton> |
There was a problem hiding this comment.
theme.palette.common.primary is not a standard MUI palette key (MUI common is usually just { black, white }). This will likely be undefined, so the icon color may not render as intended. Consider using theme.palette.primary.main (or another defined palette value).
There was a problem hiding this comment.
I think this is what headlamp provides... but need to check.
| if (!detectIfHyperVRunning()) { | ||
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | ||
| runPrivilegedCommand( | ||
| 'powershell -Command "Start-Service vmms"' | ||
| ); | ||
| } | ||
| const mainCommand = | ||
| 'minikube start --driver=hyperv' + (args.length > 0 ? ' ' + args.join(' ') : ''); | ||
| runPrivilegedCommand(mainCommand); | ||
| } | ||
|
|
||
| function stopMinikubeHyperV(args) { | ||
| if (!detectIfHyperVRunning()) { | ||
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | ||
| runPrivilegedCommand( | ||
| 'powershell -Command "Start-Service vmms"' | ||
| ); | ||
| } | ||
| const mainCommand = | ||
| 'minikube stop' + (args.length > 0 ? ' ' + args.join(' ') : ''); | ||
| runPrivilegedCommand(mainCommand); | ||
| } | ||
|
|
||
| function deleteMinikubeHyperV(args) { | ||
| if (!detectIfHyperVRunning()) { | ||
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | ||
| runPrivilegedCommand( | ||
| 'powershell -Command "Start-Service vmms"' | ||
| ); | ||
| } | ||
| const mainCommand = | ||
| 'minikube delete' + (args.length > 0 ? ' ' + args.join(' ') : ''); |
There was a problem hiding this comment.
runPrivilegedCommand calls process.exit(...) once the pipes close, but startMinikubeHyperV may call runPrivilegedCommand twice (first to start the vmms service, then to start minikube). The first call can terminate the process before the second completes, causing flaky or broken starts when Hyper-V isn’t already running. Consider chaining the service-start and minikube command into a single elevated invocation, or refactor runPrivilegedCommand to return a Promise/callback instead of exiting the whole process.
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| runPrivilegedCommand( | |
| 'powershell -Command "Start-Service vmms"' | |
| ); | |
| } | |
| const mainCommand = | |
| 'minikube start --driver=hyperv' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| runPrivilegedCommand(mainCommand); | |
| } | |
| function stopMinikubeHyperV(args) { | |
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| runPrivilegedCommand( | |
| 'powershell -Command "Start-Service vmms"' | |
| ); | |
| } | |
| const mainCommand = | |
| 'minikube stop' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| runPrivilegedCommand(mainCommand); | |
| } | |
| function deleteMinikubeHyperV(args) { | |
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| runPrivilegedCommand( | |
| 'powershell -Command "Start-Service vmms"' | |
| ); | |
| } | |
| const mainCommand = | |
| 'minikube delete' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| const minikubeCommand = | |
| 'minikube start --driver=hyperv' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| let mainCommand = minikubeCommand; | |
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| // Chain starting the vmms service and starting minikube into a single privileged command. | |
| mainCommand = | |
| 'powershell -Command "Start-Service vmms" && ' + minikubeCommand; | |
| } | |
| runPrivilegedCommand(mainCommand); | |
| } | |
| function stopMinikubeHyperV(args) { | |
| const minikubeCommand = | |
| 'minikube stop' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| let mainCommand = minikubeCommand; | |
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| // Chain starting the vmms service and stopping minikube into a single privileged command. | |
| mainCommand = | |
| 'powershell -Command "Start-Service vmms" && ' + minikubeCommand; | |
| } | |
| runPrivilegedCommand(mainCommand); | |
| } | |
| function deleteMinikubeHyperV(args) { | |
| const minikubeCommand = | |
| 'minikube delete' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| let mainCommand = minikubeCommand; | |
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| // Chain starting the vmms service and deleting the minikube cluster into a single privileged command. | |
| mainCommand = | |
| 'powershell -Command "Start-Service vmms" && ' + minikubeCommand; | |
| } |
There was a problem hiding this comment.
Could be... need to look at this more closely.
| } | ||
| } | ||
| } | ||
| }, [runningCommandsRef.current]); |
There was a problem hiding this comment.
This effect uses runningCommandsRef.current in the dependency array. Mutating the array (e.g., push) won’t change the reference, so the effect won’t re-run when commands are added/updated. Also, referencing ref.current in deps is generally unreliable for change tracking. If you need to react to command list changes, consider storing the list in React state (or updating a separate version counter) instead of relying on a ref mutation.
| }, [runningCommandsRef.current]); | |
| }, [runningCommandsRef]); |
There was a problem hiding this comment.
Need to look into this some more.
| const simulateSlowComputer = true; | ||
| const output = JSON.stringify(info) + '\n'; | ||
|
|
||
| // Flush stdout reliably across platforms (some pipes/windows consoles | ||
| // need an extra empty write to actually flush the stream). | ||
| const flushAndExit = (code = 0) => { | ||
| // helper that performs an extra empty write then exits on next tick | ||
| const doEmptyWriteAndExit = () => { | ||
| process.stdout.write('', () => { | ||
| setImmediate(() => process.exit(code)); | ||
| }); | ||
| }; | ||
|
|
||
| // Write the real output first | ||
| const ok = process.stdout.write(output, 'utf8'); | ||
|
|
||
| if (!ok) { | ||
| // Wait for drain, then perform an empty write and exit | ||
| process.stdout.once('drain', doEmptyWriteAndExit); | ||
| } else { | ||
| // Already flushed synchronously in libuv queue, but do an empty write | ||
| // to coax some platforms/pipes to finish flushing. | ||
| doEmptyWriteAndExit(); | ||
| } | ||
| }; | ||
|
|
||
| if (simulateSlowComputer) { | ||
| setTimeout(() => { | ||
| flushAndExit(0); | ||
| }, 1000); | ||
| } else { |
There was a problem hiding this comment.
simulateSlowComputer is hard-coded to true, which forces every info call to wait 1 second. This will slow down the UI’s driver/info detection in normal usage. Consider defaulting it to false and only enabling the delay behind an explicit CLI flag or environment variable used in testing.
There was a problem hiding this comment.
Yes, this should be default false.
| // Build the minikube command with arguments for zsh -l -c | ||
| const minikubeCmd = ['minikube', ...allArgs].map(arg => `'${arg.replace(/'/g, `'\\''`)}'`).join(' '); | ||
| const zshArgs = [...shellArgs, minikubeCmd]; | ||
| console.log("process.env:", process.env.PATH); |
There was a problem hiding this comment.
This logs process.env.PATH unconditionally during start-minikube-vfkit. PATH can contain sensitive or noisy user-specific data, and it also pollutes stdout/stderr for troubleshooting. Consider removing this log or gating it behind DEBUG.
| console.log("process.env:", process.env.PATH); | |
| if (DEBUG) { | |
| console.log('process.env.PATH:', process.env.PATH); | |
| } |
There was a problem hiding this comment.
This is very useful for debugging user issues... that it should be on for now. Until the code stabalizes.
| import { | ||
| registerAddClusterProvider, | ||
| registerAppBarAction, | ||
| registerClusterProviderDialog, | ||
| registerClusterProviderMenuItem, | ||
| // @ts-ignore | ||
| registerClusterStatus, | ||
| registerRoute, |
There was a problem hiding this comment.
Using // @ts-ignore to import registerClusterStatus hides type/export issues at the module boundary and can mask real breakages when upgrading @kinvolk/headlamp-plugin. Prefer updating/augmenting the plugin type declarations (e.g. via headlamp-plugin.d.ts) so the import is type-safe without suppression.
There was a problem hiding this comment.
I don't know if this is needed anymore... headlamp has been released with this fix.
| function useDrivers(info: DriverInfo | null): { value: string; label: string }[] | null { | ||
| const os = detectOS(); | ||
| const drivers = driverLists[os]; | ||
| const isInfoAvailable = info !== null; | ||
| if (DEBUG) { | ||
| console.log('info, isInfoAvailable:', info, isInfoAvailable); | ||
| } | ||
|
|
||
| if (!isInfoAvailable) { | ||
| return null; | ||
| } | ||
|
|
||
| if (os === 'macos') { | ||
| const macOSVersion = getMacOSVersion(); | ||
| if (macOSVersion && parseFloat(macOSVersion) >= 10.13) { | ||
| // remove vfkit if it exists | ||
| const vfkitIndex = drivers.findIndex(driver => driver.value === 'vfkit'); | ||
| if (vfkitIndex !== -1) { | ||
| drivers.splice(vfkitIndex, 1); | ||
| } | ||
| // add vfkit to the top | ||
| drivers.unshift({ value: 'vfkit', label: 'VFkit' }); | ||
| } else if (info && info.dockerRunning) { |
There was a problem hiding this comment.
useDrivers mutates the shared driverLists[os] array via splice()/unshift(). Because driverLists is module-level, this permanently reorders the list for all future renders/calls (and can lead to unexpected ordering across components). Make a copy (e.g., const drivers = [...driverLists[os]]) before reordering/removing items.
There was a problem hiding this comment.
Need to look into this.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 10 out of 11 changed files in this pull request and generated 6 comments.
Comments suppressed due to low confidence (1)
minikube/src/CommandCluster/CommandDialog.tsx:179
onConfirmis typed as receiving{ clusterName: string; driver: string }, but this component’sdriverstate isstring | nulland can still benullfor non-"start" flows (e.g., stop/delete whenaskClusterNameis false). This is both a TypeScript type error and can propagatenullinto callers. Either change the callback type (and downstream handlers) to acceptstring | null, or ensure you always pass a string (e.g., default to''/'auto') before callingonConfirm.
<>
{!useGrid && <Button onClick={() => onClose(true)}>Cancel</Button>}
<Button
onClick={() => {
if (clusterName) {
onConfirm({ clusterName, driver });
}
}}
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // alert(import.meta.env.HEADLAMP_APP_PLUGIN_PACKAGE_PATH); | ||
| // alert(import.meta.env.VITE_PLUGIN_PACKAGE_PATH); |
There was a problem hiding this comment.
These commented-out alert(...) lines look like leftover local debugging and will ship in the compiled bundle. Please remove them (or gate behind the existing DEBUG flag) to avoid noise and accidental popups if uncommented later.
| // alert(import.meta.env.HEADLAMP_APP_PLUGIN_PACKAGE_PATH); | |
| // alert(import.meta.env.VITE_PLUGIN_PACKAGE_PATH); |
| "test": "headlamp-plugin test", | ||
| "testplugins": "rsync -av src/ ../../testplugins/minikube/src && rsync -av manage-minikube.js ../../testplugins/minikube/", | ||
| "i18n": "headlamp-plugin i18n" |
There was a problem hiding this comment.
The testplugins script relies on rsync, which isn’t available by default on Windows and can make local testing harder for Windows contributors. Consider switching this to a cross-platform Node script (or use something like shx/cpx), or document that it requires rsync.
| <Select | ||
| labelId="driver-select-label" | ||
| id="driver-select" | ||
| value={{ value: driver }} | ||
| value={driver} | ||
| label="Driver" | ||
| displayEmpty |
There was a problem hiding this comment.
Select is rendered with value={driver} while driver can be null (it’s initialized as null and only set in an effect after the first render). This can trigger MUI “out-of-range value” warnings and/or uncontrolled/controlled transitions. Consider rendering the Select only once driver is non-null, or pass a safe fallback like driver ?? '' (and ensure the empty value exists in the menu).
| } | ||
|
|
||
| // Set the runningCommand to the last one in the list that has the same command. | ||
| const runningCommand = runningCommandsRef.current.find(cmd => cmd.props.command === command); |
There was a problem hiding this comment.
This effect’s comment says it should select the last running command for the current command, but .find(...) returns the first match. If multiple commands of the same type are in runningCommandsRef.current, this can restore the wrong one. Consider selecting the last match (e.g., iterate from the end) or explicitly track the most recent command per type.
| const runningCommand = runningCommandsRef.current.find(cmd => cmd.props.command === command); | |
| let runningCommand; | |
| for (let i = runningCommandsRef.current.length - 1; i >= 0; i -= 1) { | |
| const cmd = runningCommandsRef.current[i]; | |
| if (cmd.props.command === command) { | |
| runningCommand = cmd; | |
| break; | |
| } | |
| } |
| const packagePath = | ||
| pluginPath.startsWith('plugins/') || pluginPath.startsWith('plugins\\') | ||
| ? pluginPath.substring(8) | ||
| : pluginPath.startsWith('user-plugins/') || pluginPath.startsWith('user-plugins\\') | ||
| ? pluginPath.substring(13) | ||
| : pluginPath.startsWith('static-plugins/') || pluginPath.startsWith('static-plugins\\') | ||
| ? pluginPath.substring(15) | ||
| : pluginPath; | ||
|
|
There was a problem hiding this comment.
packagePath normalization logic is duplicated in multiple places (here, index.tsx, and CommandCluster.tsx). Duplicating this parsing increases the chance of drift/bugs when updating path rules. Consider extracting this into a shared helper (e.g., src/utils/pluginPath.ts) and reusing it.
| const packagePath = | |
| pluginPath.startsWith('plugins/') || pluginPath.startsWith('plugins\\') | |
| ? pluginPath.substring(8) | |
| : pluginPath.startsWith('user-plugins/') || pluginPath.startsWith('user-plugins\\') | |
| ? pluginPath.substring(13) | |
| : pluginPath.startsWith('static-plugins/') || pluginPath.startsWith('static-plugins\\') | |
| ? pluginPath.substring(15) | |
| : pluginPath; | |
| function normalizePluginPath(rawPath: string): string { | |
| if (rawPath.startsWith('plugins/') || rawPath.startsWith('plugins\\')) { | |
| return rawPath.substring(8); | |
| } | |
| if (rawPath.startsWith('user-plugins/') || rawPath.startsWith('user-plugins\\')) { | |
| return rawPath.substring(13); | |
| } | |
| if (rawPath.startsWith('static-plugins/') || rawPath.startsWith('static-plugins\\')) { | |
| return rawPath.substring(15); | |
| } | |
| return rawPath; | |
| } | |
| const packagePath = normalizePluginPath(pluginPath); |
| if (!detectIfHyperVRunning()) { | ||
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | ||
| runPrivilegedCommand( | ||
| 'powershell -Command "Start-Service vmms"' | ||
| ); | ||
| } | ||
| const mainCommand = | ||
| 'minikube start --driver=hyperv' + (args.length > 0 ? ' ' + args.join(' ') : ''); | ||
| runPrivilegedCommand(mainCommand); | ||
| } | ||
|
|
||
| function stopMinikubeHyperV(args) { | ||
| if (!detectIfHyperVRunning()) { | ||
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | ||
| runPrivilegedCommand( | ||
| 'powershell -Command "Start-Service vmms"' | ||
| ); | ||
| } | ||
| const mainCommand = | ||
| 'minikube stop' + (args.length > 0 ? ' ' + args.join(' ') : ''); | ||
| runPrivilegedCommand(mainCommand); | ||
| } | ||
|
|
||
| function deleteMinikubeHyperV(args) { | ||
| if (!detectIfHyperVRunning()) { | ||
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | ||
| runPrivilegedCommand( | ||
| 'powershell -Command "Start-Service vmms"' | ||
| ); | ||
| } | ||
| const mainCommand = | ||
| 'minikube delete' + (args.length > 0 ? ' ' + args.join(' ') : ''); | ||
| runPrivilegedCommand(mainCommand); |
There was a problem hiding this comment.
runPrivilegedCommand exits the Node process when its three pipes close. In startMinikubeHyperV (and similarly in stopMinikubeHyperV/deleteMinikubeHyperV), calling runPrivilegedCommand(...) to start vmms and then calling it again for the actual minikube command can cause the first invocation to terminate the process before the second completes, leading to flaky/broken behavior when Hyper-V isn’t already running. Prefer chaining service start + minikube action into a single elevated command, or refactor runPrivilegedCommand to return a Promise/callback instead of calling process.exit() internally.
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| runPrivilegedCommand( | |
| 'powershell -Command "Start-Service vmms"' | |
| ); | |
| } | |
| const mainCommand = | |
| 'minikube start --driver=hyperv' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| runPrivilegedCommand(mainCommand); | |
| } | |
| function stopMinikubeHyperV(args) { | |
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| runPrivilegedCommand( | |
| 'powershell -Command "Start-Service vmms"' | |
| ); | |
| } | |
| const mainCommand = | |
| 'minikube stop' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| runPrivilegedCommand(mainCommand); | |
| } | |
| function deleteMinikubeHyperV(args) { | |
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| runPrivilegedCommand( | |
| 'powershell -Command "Start-Service vmms"' | |
| ); | |
| } | |
| const mainCommand = | |
| 'minikube delete' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| runPrivilegedCommand(mainCommand); | |
| const minikubeCommand = | |
| 'minikube start --driver=hyperv' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| const mainCommand = | |
| 'powershell -Command "Start-Service vmms; ' + minikubeCommand + '"'; | |
| runPrivilegedCommand(mainCommand); | |
| return; | |
| } | |
| runPrivilegedCommand(minikubeCommand); | |
| } | |
| function stopMinikubeHyperV(args) { | |
| const minikubeCommand = | |
| 'minikube stop' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| const mainCommand = | |
| 'powershell -Command "Start-Service vmms; ' + minikubeCommand + '"'; | |
| runPrivilegedCommand(mainCommand); | |
| return; | |
| } | |
| runPrivilegedCommand(minikubeCommand); | |
| } | |
| function deleteMinikubeHyperV(args) { | |
| const minikubeCommand = | |
| 'minikube delete' + (args.length > 0 ? ' ' + args.join(' ') : ''); | |
| if (!detectIfHyperVRunning()) { | |
| console.error('Hyper-V is not running. Starting Hyper-V service...'); | |
| const mainCommand = | |
| 'powershell -Command "Start-Service vmms; ' + minikubeCommand + '"'; | |
| runPrivilegedCommand(mainCommand); | |
| return; | |
| } | |
| runPrivilegedCommand(minikubeCommand); |