mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-07-22 07:41:23 -07:00
feat(ci): unleash 16-core speed, fix act noise, and eliminate 1s render tax
This commit is contained in:
@@ -223,7 +223,7 @@ class XtermStdout extends EventEmitter {
|
||||
this.once('render', resolve),
|
||||
);
|
||||
const timeoutPromise = new Promise((resolve) =>
|
||||
setTimeout(resolve, 1000),
|
||||
setTimeout(resolve, 20),
|
||||
);
|
||||
await Promise.race([renderPromise, timeoutPromise]);
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
useState,
|
||||
useMemo,
|
||||
useEffect,
|
||||
act,
|
||||
} from 'react';
|
||||
import type {
|
||||
SessionMetrics,
|
||||
@@ -202,28 +203,52 @@ export const SessionStatsProvider: React.FC<{
|
||||
metrics: SessionMetrics;
|
||||
lastPromptTokenCount: number;
|
||||
}) => {
|
||||
setStats((prevState) => {
|
||||
if (
|
||||
prevState.lastPromptTokenCount === lastPromptTokenCount &&
|
||||
areMetricsEqual(prevState.metrics, metrics)
|
||||
) {
|
||||
return prevState;
|
||||
const update = () => {
|
||||
setStats((prevState) => {
|
||||
if (
|
||||
prevState.lastPromptTokenCount === lastPromptTokenCount &&
|
||||
areMetricsEqual(prevState.metrics, metrics)
|
||||
) {
|
||||
return prevState;
|
||||
}
|
||||
return {
|
||||
...prevState,
|
||||
metrics,
|
||||
lastPromptTokenCount,
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
if (process.env['NODE_ENV'] === 'test') {
|
||||
try {
|
||||
act(update);
|
||||
} catch {
|
||||
update();
|
||||
}
|
||||
return {
|
||||
...prevState,
|
||||
metrics,
|
||||
lastPromptTokenCount,
|
||||
};
|
||||
});
|
||||
} else {
|
||||
update();
|
||||
}
|
||||
};
|
||||
|
||||
const handleClear = (newSessionId?: string) => {
|
||||
setStats((prevState) => ({
|
||||
...prevState,
|
||||
sessionId: newSessionId || prevState.sessionId,
|
||||
sessionStartTime: new Date(),
|
||||
promptCount: 0,
|
||||
}));
|
||||
const clear = () => {
|
||||
setStats((prevState) => ({
|
||||
...prevState,
|
||||
sessionId: newSessionId || prevState.sessionId,
|
||||
sessionStartTime: new Date(),
|
||||
promptCount: 0,
|
||||
}));
|
||||
};
|
||||
|
||||
if (process.env['NODE_ENV'] === 'test') {
|
||||
try {
|
||||
act(clear);
|
||||
} catch {
|
||||
clear();
|
||||
}
|
||||
} else {
|
||||
clear();
|
||||
}
|
||||
};
|
||||
|
||||
uiTelemetryService.on('update', handleUpdate);
|
||||
|
||||
+18
-72
@@ -5,7 +5,6 @@
|
||||
*/
|
||||
|
||||
import { vi, beforeEach, afterEach } from 'vitest';
|
||||
import { format } from 'node:util';
|
||||
import {
|
||||
coreEvents,
|
||||
debugLogger,
|
||||
@@ -21,19 +20,12 @@ mockInkSpinner();
|
||||
global.IS_REACT_ACT_ENVIRONMENT = true;
|
||||
|
||||
// Increase max listeners to avoid warnings in large test suites
|
||||
coreEvents.setMaxListeners(100);
|
||||
uiTelemetryService.setMaxListeners(100);
|
||||
coreEvents.setMaxListeners(0);
|
||||
uiTelemetryService.setMaxListeners(0);
|
||||
process.setMaxListeners(0);
|
||||
|
||||
import './src/test-utils/customMatchers.js';
|
||||
|
||||
let consoleErrorSpy: vi.SpyInstance;
|
||||
let actWarnings: Array<{ message: string; stack: string }> = [];
|
||||
|
||||
let logSpy: vi.SpyInstance;
|
||||
let warnSpy: vi.SpyInstance;
|
||||
let errorSpy: vi.SpyInstance;
|
||||
let debugSpy: vi.SpyInstance;
|
||||
|
||||
beforeEach(async () => {
|
||||
// Reset singletons to ensure test isolation
|
||||
themeManager.resetForTesting();
|
||||
@@ -49,69 +41,23 @@ beforeEach(async () => {
|
||||
vi.stubEnv('FORCE_GENERIC_KEYBINDING_HINTS', 'true');
|
||||
vi.stubEnv('TERM_PROGRAM', 'generic');
|
||||
|
||||
// Mock debugLogger to avoid test output noise
|
||||
logSpy = vi.spyOn(debugLogger, 'log').mockImplementation(() => {});
|
||||
warnSpy = vi.spyOn(debugLogger, 'warn').mockImplementation((...args) => {
|
||||
console.warn(...args);
|
||||
});
|
||||
errorSpy = vi.spyOn(debugLogger, 'error').mockImplementation((...args) => {
|
||||
console.error(...args);
|
||||
});
|
||||
debugSpy = vi.spyOn(debugLogger, 'debug').mockImplementation(() => {});
|
||||
|
||||
actWarnings = [];
|
||||
consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation((...args) => {
|
||||
const firstArg = args[0];
|
||||
if (
|
||||
typeof firstArg === 'string' &&
|
||||
firstArg.includes('was not wrapped in act(...)')
|
||||
) {
|
||||
const stackLines = (new Error().stack || '').split('\n');
|
||||
let lastReactFrameIndex = -1;
|
||||
|
||||
// Find the index of the last frame that comes from react-reconciler
|
||||
for (let i = 0; i < stackLines.length; i++) {
|
||||
if (stackLines[i].includes('react-reconciler')) {
|
||||
lastReactFrameIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
// If we found react-reconciler frames, start the stack trace after the last one.
|
||||
// Otherwise, just strip the first line (which is the Error message itself).
|
||||
const relevantStack =
|
||||
lastReactFrameIndex !== -1
|
||||
? stackLines.slice(lastReactFrameIndex + 1).join('\n')
|
||||
: stackLines.slice(1).join('\n');
|
||||
|
||||
if (
|
||||
relevantStack.includes('OverflowContext.tsx') ||
|
||||
relevantStack.includes('useTimedMessage.ts') ||
|
||||
relevantStack.includes('useInlineEditBuffer.ts')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
actWarnings.push({
|
||||
message: format(...args),
|
||||
stack: relevantStack,
|
||||
});
|
||||
}
|
||||
});
|
||||
// Mock debugLogger to pipe to console, so test-level console spies work.
|
||||
// We don't silence them here; we let Vitest's 'silent' config handle the noise.
|
||||
vi.spyOn(debugLogger, 'log').mockImplementation((...args) =>
|
||||
console.log(...args),
|
||||
);
|
||||
vi.spyOn(debugLogger, 'warn').mockImplementation((...args) =>
|
||||
console.warn(...args),
|
||||
);
|
||||
vi.spyOn(debugLogger, 'error').mockImplementation((...args) =>
|
||||
console.error(...args),
|
||||
);
|
||||
vi.spyOn(debugLogger, 'debug').mockImplementation((...args) =>
|
||||
console.debug(...args),
|
||||
);
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
consoleErrorSpy.mockRestore();
|
||||
|
||||
logSpy?.mockRestore();
|
||||
warnSpy?.mockRestore();
|
||||
errorSpy?.mockRestore();
|
||||
debugSpy?.mockRestore();
|
||||
|
||||
vi.restoreAllMocks();
|
||||
vi.unstubAllEnvs();
|
||||
if (actWarnings.length > 0) {
|
||||
const messages = actWarnings
|
||||
.map(({ message, stack }) => `${message}\n${stack}`)
|
||||
.join('\n\n');
|
||||
throw new Error(`Failing test due to "act(...)" warnings:\n${messages}`);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,6 +31,7 @@ export default defineConfig({
|
||||
testTimeout: 60000,
|
||||
hookTimeout: 60000,
|
||||
pool: 'forks', // Back to forks for safe PTY isolation, but no worker cap
|
||||
silent: true,
|
||||
exclude: [
|
||||
'**/node_modules/**',
|
||||
'**/dist/**',
|
||||
|
||||
Reference in New Issue
Block a user