diff options
| author | Eddie Santos <[email protected]> | 2025-06-17 08:24:07 -0700 |
|---|---|---|
| committer | GitHub <[email protected]> | 2025-06-17 15:24:07 +0000 |
| commit | c3971754bf4bd5877d7a57c523b981c09d4fa35d (patch) | |
| tree | bda44458964d2c141977e321ed39cfd2dba99a8d /packages/cli/src | |
| parent | bc3fa71234638abd623479d81b52302c21630e87 (diff) | |
Auto-update notifications (#1110)
Diffstat (limited to 'packages/cli/src')
| -rw-r--r-- | packages/cli/src/gemini.test.tsx | 8 | ||||
| -rw-r--r-- | packages/cli/src/ui/App.tsx | 9 | ||||
| -rw-r--r-- | packages/cli/src/ui/components/UpdateNotification.tsx | 23 | ||||
| -rw-r--r-- | packages/cli/src/ui/utils/updateCheck.ts | 35 | ||||
| -rw-r--r-- | packages/cli/src/utils/sandbox.ts | 5 |
5 files changed, 78 insertions, 2 deletions
diff --git a/packages/cli/src/gemini.test.tsx b/packages/cli/src/gemini.test.tsx index f77f9577..952b4a77 100644 --- a/packages/cli/src/gemini.test.tsx +++ b/packages/cli/src/gemini.test.tsx @@ -44,11 +44,17 @@ vi.mock('./config/config.js', () => ({ vi.mock('read-package-up', () => ({ readPackageUp: vi.fn().mockResolvedValue({ - packageJson: { version: 'test-version' }, + packageJson: { name: 'test-pkg', version: 'test-version' }, path: '/fake/path/package.json', }), })); +vi.mock('update-notifier', () => ({ + default: vi.fn(() => ({ + notify: vi.fn(), + })), +})); + vi.mock('./utils/sandbox.js', () => ({ sandbox_command: vi.fn(() => ''), // Default to no sandbox command start_sandbox: vi.fn(() => Promise.resolve()), // Mock as an async function that resolves diff --git a/packages/cli/src/ui/App.tsx b/packages/cli/src/ui/App.tsx index 9a4ecbd3..a5317b30 100644 --- a/packages/cli/src/ui/App.tsx +++ b/packages/cli/src/ui/App.tsx @@ -60,6 +60,8 @@ import { import { useGitBranchName } from './hooks/useGitBranchName.js'; import { useTextBuffer } from './components/shared/text-buffer.js'; import * as fs from 'fs'; +import { UpdateNotification } from './components/UpdateNotification.js'; +import { checkForUpdates } from './utils/updateCheck.js'; const CTRL_EXIT_PROMPT_DURATION_MS = 1000; @@ -76,6 +78,12 @@ export const AppWrapper = (props: AppProps) => ( ); const App = ({ config, settings, startupWarnings = [] }: AppProps) => { + const [updateMessage, setUpdateMessage] = useState<string | null>(null); + + useEffect(() => { + checkForUpdates().then(setUpdateMessage); + }, []); + const { history, addItem, clearItems, loadHistory } = useHistory(); const { consoleMessages, @@ -467,6 +475,7 @@ const App = ({ config, settings, startupWarnings = [] }: AppProps) => { <Box flexDirection="column" key="header"> <Header terminalWidth={terminalWidth} /> <Tips config={config} /> + {updateMessage && <UpdateNotification message={updateMessage} />} </Box>, ...history.map((h) => ( <HistoryItemDisplay diff --git a/packages/cli/src/ui/components/UpdateNotification.tsx b/packages/cli/src/ui/components/UpdateNotification.tsx new file mode 100644 index 00000000..b88c9bd5 --- /dev/null +++ b/packages/cli/src/ui/components/UpdateNotification.tsx @@ -0,0 +1,23 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import { Box, Text } from 'ink'; +import { Colors } from '../colors.js'; + +interface UpdateNotificationProps { + message: string; +} + +export const UpdateNotification = ({ message }: UpdateNotificationProps) => ( + <Box + borderStyle="round" + borderColor={Colors.AccentYellow} + paddingX={1} + marginY={1} + > + <Text color={Colors.AccentYellow}>{message}</Text> + </Box> +); diff --git a/packages/cli/src/ui/utils/updateCheck.ts b/packages/cli/src/ui/utils/updateCheck.ts new file mode 100644 index 00000000..17d30378 --- /dev/null +++ b/packages/cli/src/ui/utils/updateCheck.ts @@ -0,0 +1,35 @@ +/** + * @license + * Copyright 2025 Google LLC + * SPDX-License-Identifier: Apache-2.0 + */ + +import updateNotifier from 'update-notifier'; +import { readPackageUp } from 'read-package-up'; +import process from 'node:process'; + +export async function checkForUpdates(): Promise<string | null> { + // read-package-up looks for the closest package.json from cwd + const pkgResult = await readPackageUp({ cwd: process.cwd() }); + if (!pkgResult) { + return null; + } + + const { packageJson } = pkgResult; + const notifier = updateNotifier({ + pkg: { + name: packageJson.name, + version: packageJson.version, + }, + // check every time + updateCheckInterval: 0, + // allow notifier to run in scripts + shouldNotifyInNpmScript: true, + }); + + if (notifier.update) { + return `Gemini CLI update available! ${notifier.update.current} → ${notifier.update.latest}\nRun npm install -g ${packageJson.name} to update`; + } + + return null; +} diff --git a/packages/cli/src/utils/sandbox.ts b/packages/cli/src/utils/sandbox.ts index 08714bd8..36dec7f0 100644 --- a/packages/cli/src/utils/sandbox.ts +++ b/packages/cli/src/utils/sandbox.ts @@ -659,7 +659,10 @@ export async function start_sandbox(sandbox: string) { // Determine if the current user's UID/GID should be passed to the sandbox. // See shouldUseCurrentUserInSandbox for more details. let userFlag = ''; - if (await shouldUseCurrentUserInSandbox()) { + if (process.env.GEMINI_CLI_INTEGRATION_TEST === 'true') { + args.push('--user', 'root'); + userFlag = '--user root'; + } else if (await shouldUseCurrentUserInSandbox()) { const uid = execSync('id -u').toString().trim(); const gid = execSync('id -g').toString().trim(); args.push('--user', `${uid}:${gid}`); |
