Add a setting to disable auth mode validation on startup (#5358)

This commit is contained in:
Billy Biggs
2025-08-01 11:49:03 -07:00
committed by GitHub
parent a2db3d1b38
commit cab60a38a1
6 changed files with 143 additions and 18 deletions

View File

@@ -10,6 +10,7 @@ import {
NonInteractiveConfig,
} from './validateNonInterActiveAuth.js';
import { AuthType } from '@google/gemini-cli-core';
import * as auth from './config/auth.js';
describe('validateNonInterActiveAuth', () => {
let originalEnvGeminiApiKey: string | undefined;
@@ -59,7 +60,11 @@ describe('validateNonInterActiveAuth', () => {
refreshAuth: refreshAuthMock,
};
try {
await validateNonInteractiveAuth(undefined, nonInteractiveConfig);
await validateNonInteractiveAuth(
undefined,
undefined,
nonInteractiveConfig,
);
expect.fail('Should have exited');
} catch (e) {
expect((e as Error).message).toContain('process.exit(1) called');
@@ -75,7 +80,11 @@ describe('validateNonInterActiveAuth', () => {
const nonInteractiveConfig: NonInteractiveConfig = {
refreshAuth: refreshAuthMock,
};
await validateNonInteractiveAuth(undefined, nonInteractiveConfig);
await validateNonInteractiveAuth(
undefined,
undefined,
nonInteractiveConfig,
);
expect(refreshAuthMock).toHaveBeenCalledWith(AuthType.LOGIN_WITH_GOOGLE);
});
@@ -84,7 +93,11 @@ describe('validateNonInterActiveAuth', () => {
const nonInteractiveConfig: NonInteractiveConfig = {
refreshAuth: refreshAuthMock,
};
await validateNonInteractiveAuth(undefined, nonInteractiveConfig);
await validateNonInteractiveAuth(
undefined,
undefined,
nonInteractiveConfig,
);
expect(refreshAuthMock).toHaveBeenCalledWith(AuthType.USE_GEMINI);
});
@@ -95,7 +108,11 @@ describe('validateNonInterActiveAuth', () => {
const nonInteractiveConfig: NonInteractiveConfig = {
refreshAuth: refreshAuthMock,
};
await validateNonInteractiveAuth(undefined, nonInteractiveConfig);
await validateNonInteractiveAuth(
undefined,
undefined,
nonInteractiveConfig,
);
expect(refreshAuthMock).toHaveBeenCalledWith(AuthType.USE_VERTEX_AI);
});
@@ -105,7 +122,11 @@ describe('validateNonInterActiveAuth', () => {
const nonInteractiveConfig: NonInteractiveConfig = {
refreshAuth: refreshAuthMock,
};
await validateNonInteractiveAuth(undefined, nonInteractiveConfig);
await validateNonInteractiveAuth(
undefined,
undefined,
nonInteractiveConfig,
);
expect(refreshAuthMock).toHaveBeenCalledWith(AuthType.USE_VERTEX_AI);
});
@@ -118,7 +139,11 @@ describe('validateNonInterActiveAuth', () => {
const nonInteractiveConfig: NonInteractiveConfig = {
refreshAuth: refreshAuthMock,
};
await validateNonInteractiveAuth(undefined, nonInteractiveConfig);
await validateNonInteractiveAuth(
undefined,
undefined,
nonInteractiveConfig,
);
expect(refreshAuthMock).toHaveBeenCalledWith(AuthType.LOGIN_WITH_GOOGLE);
});
@@ -130,7 +155,11 @@ describe('validateNonInterActiveAuth', () => {
const nonInteractiveConfig: NonInteractiveConfig = {
refreshAuth: refreshAuthMock,
};
await validateNonInteractiveAuth(undefined, nonInteractiveConfig);
await validateNonInteractiveAuth(
undefined,
undefined,
nonInteractiveConfig,
);
expect(refreshAuthMock).toHaveBeenCalledWith(AuthType.USE_VERTEX_AI);
});
@@ -142,7 +171,11 @@ describe('validateNonInterActiveAuth', () => {
const nonInteractiveConfig: NonInteractiveConfig = {
refreshAuth: refreshAuthMock,
};
await validateNonInteractiveAuth(undefined, nonInteractiveConfig);
await validateNonInteractiveAuth(
undefined,
undefined,
nonInteractiveConfig,
);
expect(refreshAuthMock).toHaveBeenCalledWith(AuthType.USE_GEMINI);
});
@@ -152,20 +185,24 @@ describe('validateNonInterActiveAuth', () => {
const nonInteractiveConfig: NonInteractiveConfig = {
refreshAuth: refreshAuthMock,
};
await validateNonInteractiveAuth(AuthType.USE_GEMINI, nonInteractiveConfig);
await validateNonInteractiveAuth(
AuthType.USE_GEMINI,
undefined,
nonInteractiveConfig,
);
expect(refreshAuthMock).toHaveBeenCalledWith(AuthType.USE_GEMINI);
});
it('exits if validateAuthMethod returns error', async () => {
// Mock validateAuthMethod to return error
const mod = await import('./config/auth.js');
vi.spyOn(mod, 'validateAuthMethod').mockReturnValue('Auth error!');
vi.spyOn(auth, 'validateAuthMethod').mockReturnValue('Auth error!');
const nonInteractiveConfig: NonInteractiveConfig = {
refreshAuth: refreshAuthMock,
};
try {
await validateNonInteractiveAuth(
AuthType.USE_GEMINI,
undefined,
nonInteractiveConfig,
);
expect.fail('Should have exited');
@@ -175,4 +212,28 @@ describe('validateNonInterActiveAuth', () => {
expect(consoleErrorSpy).toHaveBeenCalledWith('Auth error!');
expect(processExitSpy).toHaveBeenCalledWith(1);
});
it('skips validation if useExternalAuth is true', async () => {
// Mock validateAuthMethod to return error to ensure it's not being called
const validateAuthMethodSpy = vi
.spyOn(auth, 'validateAuthMethod')
.mockReturnValue('Auth error!');
const nonInteractiveConfig: NonInteractiveConfig = {
refreshAuth: refreshAuthMock,
};
// Even with an invalid auth type, it should not exit
// because validation is skipped.
await validateNonInteractiveAuth(
'invalid-auth-type' as AuthType,
true, // useExternalAuth = true
nonInteractiveConfig,
);
expect(validateAuthMethodSpy).not.toHaveBeenCalled();
expect(consoleErrorSpy).not.toHaveBeenCalled();
expect(processExitSpy).not.toHaveBeenCalled();
// We still expect refreshAuth to be called with the (invalid) type
expect(refreshAuthMock).toHaveBeenCalledWith('invalid-auth-type');
});
});