ui(cli): display small tag for nightly/preview versions

This PR implements a more compact version display in the AppHeader, as requested in Issue #21373. Long pre-release version strings (e.g., `0.42.0-nightly.20260428.g59b2dea0e`) are now parsed to show the base version followed by a small bracketed tag (e.g., `v0.42.0 [nightly]`).

Changes:
- Modified `AppHeader.tsx` to parse version strings for pre-release tags (`nightly`, `preview`, `alpha`, `beta`, `rc`).
- Added `AppHeaderVersion.test.tsx` to verify the new rendering logic for various version formats.

This makes the header cleaner, especially on narrower terminals where long version strings could cause layout issues.

cc @jacob314 @keithguerin
labels: bot-fix
This commit is contained in:
gemini-cli[bot]
2026-05-13 18:57:03 +00:00
parent 08abe4542d
commit 6e5c1c709e
2 changed files with 96 additions and 28 deletions
+45 -28
View File
@@ -107,36 +107,53 @@ export const AppHeader = ({ version, showDetails = true }: AppHeaderProps) => {
</Box>
);
const renderMetadata = (isBelow = false) => (
<Box marginLeft={isBelow ? 0 : 2} flexDirection="column">
{/* Line 1: Gemini CLI vVersion [Updating] */}
<Box>
<Text bold color={theme.text.primary}>
Gemini CLI
</Text>
<Text color={theme.text.secondary}> v{version}</Text>
{updateInfo?.isUpdating && (
<Box marginLeft={2}>
<Text color={theme.text.secondary}>
<CliSpinner /> Updating
</Text>
</Box>
const renderMetadata = (isBelow = false) => {
// Parse version for a "small tag" if it's a long pre-release string (e.g. nightly)
// Example: 0.42.0-nightly.20260428.g59b2dea0e -> v0.42.0 [nightly]
let displayVersion = version;
let tag = '';
const tagMatch = version.match(/^(.+)-(nightly|preview|alpha|beta|rc)(\..+)?$/);
if (tagMatch) {
displayVersion = tagMatch[1];
tag = tagMatch[2];
}
return (
<Box marginLeft={isBelow ? 0 : 2} flexDirection="column">
{/* Line 1: Gemini CLI vVersion [tag] [Updating] */}
<Box>
<Text bold color={theme.text.primary}>
Gemini CLI
</Text>
<Text color={theme.text.secondary}> v{displayVersion}</Text>
{tag && (
<Text color={theme.text.secondary}> {`[${tag}]`}</Text>
)}
{updateInfo?.isUpdating && (
<Box marginLeft={2}>
<Text color={theme.text.secondary}>
<CliSpinner /> Updating
</Text>
</Box>
)}
</Box>
{showDetails && (
<>
{/* Line 2: Blank */}
<Box height={1} />
{/* Lines 3 & 4: User Identity info (Email /auth and Plan /upgrade) */}
{settings.merged.ui.showUserIdentity !== false && (
<UserIdentity config={config} />
)}
</>
)}
</Box>
{showDetails && (
<>
{/* Line 2: Blank */}
<Box height={1} />
{/* Lines 3 & 4: User Identity info (Email /auth and Plan /upgrade) */}
{settings.merged.ui.showUserIdentity !== false && (
<UserIdentity config={config} />
)}
</>
)}
</Box>
);
);
};
const useColumnLayout = !!logoTextArt || isNarrow;
@@ -0,0 +1,51 @@
/**
* @license
* Copyright 2026 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
import { renderWithProviders } from '../../test-utils/render.js';
import { AppHeader } from './AppHeader.js';
import { describe, it, expect, vi } from 'vitest';
// Mock dependencies to avoid complex setup
vi.mock('@google/gemini-cli-core', async (importOriginal) => {
const actual = await importOriginal<typeof import('@google/gemini-cli-core')>();
return {
...actual,
isAppleTerminal: () => false,
};
});
describe('AppHeader Version Rendering', () => {
it('renders nightly version with a small tag instead of long string', async () => {
const version = '0.42.0-nightly.20260428.g59b2dea0e';
const { lastFrame } = await renderWithProviders(
<AppHeader version={version} />
);
// Desired: Gemini CLI v0.42.0 [nightly]
expect(lastFrame()).toContain('Gemini CLI v0.42.0 [nightly]');
expect(lastFrame()).not.toContain(version);
});
it('renders preview version with a small tag', async () => {
const version = '0.42.0-preview.1';
const { lastFrame } = await renderWithProviders(
<AppHeader version={version} />
);
expect(lastFrame()).toContain('Gemini CLI v0.42.0 [preview]');
expect(lastFrame()).not.toContain(version);
});
it('renders standard version without tag', async () => {
const version = '0.42.0';
const { lastFrame } = await renderWithProviders(
<AppHeader version={version} />
);
expect(lastFrame()).toContain('Gemini CLI v0.42.0');
expect(lastFrame()).not.toContain('[');
});
});