From 123c3e7c7f5d63dba149f673b71ab124a7f03772 Mon Sep 17 00:00:00 2001 From: Devansh Sharma Date: Tue, 15 Jul 2025 11:49:46 +0200 Subject: [PATCH] feat: add a warning that shows if user uses node -v <20 #2930 (#3371) Co-authored-by: Jacob Richman --- .../cli/src/utils/userStartupWarnings.test.ts | 46 +++++++++++++++++++ packages/cli/src/utils/userStartupWarnings.ts | 18 +++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/packages/cli/src/utils/userStartupWarnings.test.ts b/packages/cli/src/utils/userStartupWarnings.test.ts index 61053029..8210d4e3 100644 --- a/packages/cli/src/utils/userStartupWarnings.test.ts +++ b/packages/cli/src/utils/userStartupWarnings.test.ts @@ -8,6 +8,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; import { getUserStartupWarnings } from './userStartupWarnings.js'; import * as os from 'os'; import fs from 'fs/promises'; +import semver from 'semver'; vi.mock('os', () => ({ default: { homedir: vi.fn() }, @@ -18,6 +19,13 @@ vi.mock('fs/promises', () => ({ default: { realpath: vi.fn() }, })); +vi.mock('semver', () => ({ + default: { + major: vi.fn(), + }, + major: vi.fn(), +})); + describe('getUserStartupWarnings', () => { const homeDir = '/home/user'; @@ -66,6 +74,44 @@ describe('getUserStartupWarnings', () => { }); }); + function setNodeVersionMajor(majorVersion: number) { + vi.mocked(semver.major).mockReturnValue(majorVersion); + } + + describe('node version check', () => { + afterEach(() => { + setNodeVersionMajor(20); + }); + + it('should return a warning if Node.js version is less than minMajor', async () => { + setNodeVersionMajor(18); + const warnings = await getUserStartupWarnings(''); + expect(warnings).toHaveLength(1); + expect(warnings[0]).toContain('Node.js'); + expect(warnings[0]).toContain('requires Node.js 20 or higher'); + }); + + it('should not return a warning if Node.js version is equal to minMajor', async () => { + setNodeVersionMajor(20); + const warnings = await getUserStartupWarnings(''); + expect(warnings).toEqual([]); + }); + + it('should not return a warning if Node.js version is greater than minMajor', async () => { + setNodeVersionMajor(22); + const warnings = await getUserStartupWarnings(''); + expect(warnings).toEqual([]); + }); + + it('should use default minMajor=20 if not provided', async () => { + setNodeVersionMajor(18); + const warnings = await getUserStartupWarnings(''); + expect(warnings).toHaveLength(1); + expect(warnings[0]).toContain('Node.js'); + expect(warnings[0]).toContain('requires Node.js 20 or higher'); + }); + }); + // // Example of how to add a new check: // describe('node version check', () => { // // Tests for node version check would go here diff --git a/packages/cli/src/utils/userStartupWarnings.ts b/packages/cli/src/utils/userStartupWarnings.ts index 3d76a6e1..ddf2300d 100644 --- a/packages/cli/src/utils/userStartupWarnings.ts +++ b/packages/cli/src/utils/userStartupWarnings.ts @@ -6,6 +6,7 @@ import fs from 'fs/promises'; import * as os from 'os'; +import semver from 'semver'; type WarningCheck = { id: string; @@ -32,8 +33,23 @@ const homeDirectoryCheck: WarningCheck = { }, }; +const nodeVersionCheck: WarningCheck = { + id: 'node-version', + check: async (_workspaceRoot: string) => { + const minMajor = 20; + const major = semver.major(process.versions.node); + if (major < minMajor) { + return `You are using Node.js v${process.versions.node}. Gemini CLI requires Node.js ${minMajor} or higher for best results.`; + } + return null; + }, +}; + // All warning checks -const WARNING_CHECKS: readonly WarningCheck[] = [homeDirectoryCheck]; +const WARNING_CHECKS: readonly WarningCheck[] = [ + homeDirectoryCheck, + nodeVersionCheck, +]; export async function getUserStartupWarnings( workspaceRoot: string,