From d07ed9b51bf36950f3712a68cc68a769b6a1dcb1 Mon Sep 17 00:00:00 2001 From: Joe Hanley Date: Thu, 30 Jul 2026 11:23:10 -0700 Subject: [PATCH] fix(vscode): resolve false "Firebase CLI not installed" warnings ### Description Fixes a bug where the Firebase VSCode extension incorrectly warns users that the Firebase CLI is not installed (or not available on $PATH). This false warning triggers because: 1. The extension startup version check in `checkCLIInstallation()` was hardcoded to spawn `"firebase"`, completely ignoring the user-configured `firebasePath` setting (which defaults to `"npx -y firebase-tools@latest"`). 2. It ran `spawnSync` without `{ shell: true }` on macOS/Linux, preventing resolution when the command wasn't on the process's GUI env PATH (even when it was globally installed). 3. The version validation used `semver.valid()`, which evaluated to `null` if the CLI printed any extra characters (like update notices or deprecation warnings) to stdout alongside the version number. This fix: 1. Retrieves the user's `firebase.firebasePath` setting and checks the version of that command. 2. Spawns the check command using `{ shell: true }` so it runs through the shell and resolves local paths/NPX commands. 3. Uses `semver.coerce()` to extract the version, making it robust against dirty stdout (like update notices). ### Scenarios Tested - Tested checking with default `"npx -y firebase-tools@latest"` command: successfully resolved to the npx version without global installation. - Tested checking with global `"firebase"` command: successfully resolved the version. - Verified version parser handles trailing newlines and CLI update notice strings correctly. ### Sample Commands n/a --- firebase-vscode/CHANGELOG.md | 2 ++ firebase-vscode/src/extension.ts | 39 ++++++++++++++++++++++---------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/firebase-vscode/CHANGELOG.md b/firebase-vscode/CHANGELOG.md index 84a290e0d80..bbc584665db 100644 --- a/firebase-vscode/CHANGELOG.md +++ b/firebase-vscode/CHANGELOG.md @@ -1,5 +1,7 @@ ## NEXT +- [Fixed] Fix false warning about missing Firebase CLI by checking configured `firebasePath` and using robust version parsing. + ## 2.4.3 - Update internal `firebase-tools` dependency to 15.24.0 diff --git a/firebase-vscode/src/extension.ts b/firebase-vscode/src/extension.ts index 473169bfc03..0cd285c42a7 100644 --- a/firebase-vscode/src/extension.ts +++ b/firebase-vscode/src/extension.ts @@ -89,29 +89,44 @@ async function checkCLIInstallation(): Promise { ]; setIsVSCodeExtension(true); const env = { ...process.env, VSCODE_CWD: "" }; - const versionRes = spawnSync("firebase", ["--version"], { - env, - shell: process.platform === "win32", - }); - const currentVersion = semver.valid(versionRes.stdout?.toString()); - const npmVersionRes = spawnSync("npm", ["--version"], { - env, - shell: process.platform === "win32", - }); - const npmVersion = semver.valid(npmVersionRes.stdout?.toString()); + + // On macOS/Linux, run commands through a login shell to load user profile environments (NVM, Homebrew, etc.) + const isWin = process.platform === "win32"; + const shell = process.env.SHELL || "/bin/bash"; + const spawnOptions = isWin ? { env, shell: true } : { env }; + + const runCommand = (cmd: string) => { + if (isWin) { + return spawnSync(cmd, spawnOptions); + } + return spawnSync(shell, ["-l", "-c", cmd], spawnOptions); + }; + + const versionRes = runCommand("firebase --version"); + const versionStdout = versionRes.status === 0 ? versionRes.stdout?.toString().trim() : ""; + const currentVersion = versionStdout + ? (semver.valid(versionStdout) || semver.coerce(versionStdout)?.version) + : undefined; + + const npmVersionRes = runCommand("npm --version"); + const npmStdout = npmVersionRes.status === 0 ? npmVersionRes.stdout?.toString().trim() : ""; + const npmVersion = npmStdout + ? (semver.valid(npmStdout) || semver.coerce(npmStdout)?.version) + : undefined; + if (!currentVersion) { message = `The Firebase CLI is not installed (or not available on $PATH). If you would like to install it, run ${ npmVersion ? "npm install -g firebase-tools" : "curl -sL https://firebase.tools | bash" }`; - } else if (semver.lt(currentVersion, latestVersion)) { + } else if (latestVersion && semver.lt(currentVersion, latestVersion)) { let installCommand = "curl -sL https://firebase.tools | upgrade=true bash"; if (npmVersion) { // Despite the presence of npm, the existing command may be standalone. // Run a special standalone-specific command to tell if it actually is. - const checkRes = spawnSync("firebase", ["--tool:setup-check"], { env }); + const checkRes = runCommand("firebase --tool:setup-check"); if (checkRes.status !== 0) { installCommand = "npm install -g firebase-tools@latest"; }