Skip to content

minikube fixes#546

Draft
illume wants to merge 53 commits intoheadlamp-k8s:mainfrom
illume:minikube-fixes2-rebased
Draft

minikube fixes#546
illume wants to merge 53 commits intoheadlamp-k8s:mainfrom
illume:minikube-fixes2-rebased

Conversation

@illume
Copy link
Contributor

@illume 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

illume added 8 commits March 3, 2026 10:14
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>
@illume illume force-pushed the minikube-fixes2-rebased branch from 5aadfb7 to ab5b9f6 Compare March 3, 2026 13:22
illume added 21 commits March 3, 2026 10:26
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>
illume added 22 commits March 3, 2026 10:26
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>
@illume illume force-pushed the minikube-fixes2-rebased branch from ab5b9f6 to 9e3f586 Compare March 3, 2026 13:26
@illume illume requested a review from Copilot March 3, 2026 13:27
@illume illume marked this pull request as draft March 3, 2026 13:27
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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.js helper script and bundles it via headlamp.extraDist, plus a dev testplugins script.
  • Introduces an useInfo() hook to detect system/minikube profile info and uses it to drive driver selection + warnings.
  • Adds a ClusterStatus UI integration (via registerClusterStatus) 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

  • driver state is string | null, but onConfirm is typed to require { driver: string } and you pass driver through directly. This is a compile-time type error (and a runtime issue if null slips through). Either make driver always a string before enabling the action (e.g., default to ''/first detected driver) or change the onConfirm contract and handle null explicitly.
          {!useGrid && <Button onClick={() => onClose(true)}>Cancel</Button>}
          <Button
            onClick={() => {
              if (clusterName) {
                onConfirm({ clusterName, driver });
              }
            }}

minikube/src/CommandCluster/DriverSelect.tsx:203

  • Select is rendered with value={driver} where driver can be null (initial state). MUI Select expects a string/number value (typically '' for “no selection”), and null can cause warnings and inconsistent behavior. Consider using value={driver ?? ''} (and/or initialize driver to '') 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.

Comment on lines +66 to +69
>
{/* <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>
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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).

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think this is what headlamp provides... but need to check.

Comment on lines +181 to +212
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(' ') : '');
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
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;
}

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Could be... need to look at this more closely.

}
}
}
}, [runningCommandsRef.current]);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
}, [runningCommandsRef.current]);
}, [runningCommandsRef]);

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need to look into this some more.

Comment on lines +476 to +506
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 {
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@illume illume Mar 3, 2026

Choose a reason for hiding this comment

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

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);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
console.log("process.env:", process.env.PATH);
if (DEBUG) {
console.log('process.env.PATH:', process.env.PATH);
}

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

@illume illume Mar 3, 2026

Choose a reason for hiding this comment

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

This is very useful for debugging user issues... that it should be on for now. Until the code stabalizes.

Comment on lines 1 to 8
import {
registerAddClusterProvider,
registerAppBarAction,
registerClusterProviderDialog,
registerClusterProviderMenuItem,
// @ts-ignore
registerClusterStatus,
registerRoute,
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't know if this is needed anymore... headlamp has been released with this fix.

Comment on lines +99 to +121
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) {
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Need to look into this.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

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

  • onConfirm is typed as receiving { clusterName: string; driver: string }, but this component’s driver state is string | null and can still be null for non-"start" flows (e.g., stop/delete when askClusterName is false). This is both a TypeScript type error and can propagate null into callers. Either change the callback type (and downstream handlers) to accept string | null, or ensure you always pass a string (e.g., default to ''/'auto') before calling onConfirm.
        <>
          {!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.

Comment on lines +176 to +177
// alert(import.meta.env.HEADLAMP_APP_PLUGIN_PACKAGE_PATH);
// alert(import.meta.env.VITE_PLUGIN_PACKAGE_PATH);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
// alert(import.meta.env.HEADLAMP_APP_PLUGIN_PACKAGE_PATH);
// alert(import.meta.env.VITE_PLUGIN_PACKAGE_PATH);

Copilot uses AI. Check for mistakes.
Comment on lines +15 to +17
"test": "headlamp-plugin test",
"testplugins": "rsync -av src/ ../../testplugins/minikube/src && rsync -av manage-minikube.js ../../testplugins/minikube/",
"i18n": "headlamp-plugin i18n"
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Copilot uses AI. Check for mistakes.
Comment on lines 188 to 193
<Select
labelId="driver-select-label"
id="driver-select"
value={{ value: driver }}
value={driver}
label="Driver"
displayEmpty
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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).

Copilot uses AI. Check for mistakes.
}

// 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);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
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;
}
}

Copilot uses AI. Check for mistakes.
Comment on lines +24 to +32
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;

Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
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);

Copilot uses AI. Check for mistakes.
Comment on lines +181 to +213
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);
Copy link

Copilot AI Mar 3, 2026

Choose a reason for hiding this comment

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

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.

Suggested change
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);

Copilot uses AI. Check for mistakes.
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