summaryrefslogtreecommitdiff
path: root/packages/cli/src
diff options
context:
space:
mode:
authorMarat Boshernitsan <[email protected]>2025-07-07 15:02:13 -0700
committerGitHub <[email protected]>2025-07-07 22:02:13 +0000
commit48c2aa296a7ed8b17e861d54682b0ea71695ca66 (patch)
treeaf686139688bfca8e2fd9c7fedb944d012d52ff6 /packages/cli/src
parent357546a2aac918702f6ebfa4a97bd95ccd614e5d (diff)
Enable Gemini CLI to reuse user's auth in Cloud Shell (#3070)
Diffstat (limited to 'packages/cli/src')
-rw-r--r--packages/cli/src/config/auth.ts2
-rw-r--r--packages/cli/src/config/settings.ts27
-rw-r--r--packages/cli/src/gemini.tsx23
-rw-r--r--packages/cli/src/ui/components/AuthDialog.tsx18
4 files changed, 59 insertions, 11 deletions
diff --git a/packages/cli/src/config/auth.ts b/packages/cli/src/config/auth.ts
index 439bd36b..4561f5d6 100644
--- a/packages/cli/src/config/auth.ts
+++ b/packages/cli/src/config/auth.ts
@@ -9,7 +9,7 @@ import { loadEnvironment } from './settings.js';
export const validateAuthMethod = (authMethod: string): string | null => {
loadEnvironment();
- if (authMethod === AuthType.LOGIN_WITH_GOOGLE) {
+ if (authMethod === AuthType.LOGIN_WITH_GOOGLE || AuthType.CLOUD_SHELL) {
return null;
}
diff --git a/packages/cli/src/config/settings.ts b/packages/cli/src/config/settings.ts
index 93f042aa..c2d03167 100644
--- a/packages/cli/src/config/settings.ts
+++ b/packages/cli/src/config/settings.ts
@@ -203,8 +203,35 @@ function findEnvFile(startDir: string): string | null {
}
}
+export function setUpCloudShellEnvironment(envFilePath: string | null): void {
+ // Special handling for GOOGLE_CLOUD_PROJECT in Cloud Shell:
+ // Because GOOGLE_CLOUD_PROJECT in Cloud Shell tracks the project
+ // set by the user using "gcloud config set project" we do not want to
+ // use its value. So, unless the user overrides GOOGLE_CLOUD_PROJECT in
+ // one of the .env files, we set the Cloud Shell-specific default here.
+ if (envFilePath && fs.existsSync(envFilePath)) {
+ const envFileContent = fs.readFileSync(envFilePath);
+ const parsedEnv = dotenv.parse(envFileContent);
+ if (parsedEnv.GOOGLE_CLOUD_PROJECT) {
+ // .env file takes precedence in Cloud Shell
+ process.env.GOOGLE_CLOUD_PROJECT = parsedEnv.GOOGLE_CLOUD_PROJECT;
+ } else {
+ // If not in .env, set to default and override global
+ process.env.GOOGLE_CLOUD_PROJECT = 'cloudshell-gca';
+ }
+ } else {
+ // If no .env file, set to default and override global
+ process.env.GOOGLE_CLOUD_PROJECT = 'cloudshell-gca';
+ }
+}
+
export function loadEnvironment(): void {
const envFilePath = findEnvFile(process.cwd());
+
+ if (process.env.CLOUD_SHELL === 'true') {
+ setUpCloudShellEnvironment(envFilePath);
+ }
+
if (envFilePath) {
dotenv.config({ path: envFilePath, quiet: true });
}
diff --git a/packages/cli/src/gemini.tsx b/packages/cli/src/gemini.tsx
index 39d3bbe3..7e86a8ca 100644
--- a/packages/cli/src/gemini.tsx
+++ b/packages/cli/src/gemini.tsx
@@ -103,14 +103,21 @@ export async function main() {
const extensions = loadExtensions(workspaceRoot);
const config = await loadCliConfig(settings.merged, extensions, sessionId);
- // set default fallback to gemini api key
- // this has to go after load cli because that's where the env is set
- if (!settings.merged.selectedAuthType && process.env.GEMINI_API_KEY) {
- settings.setValue(
- SettingScope.User,
- 'selectedAuthType',
- AuthType.USE_GEMINI,
- );
+ // Set a default auth type if one isn't set for a couple of known cases.
+ if (!settings.merged.selectedAuthType) {
+ if (process.env.GEMINI_API_KEY) {
+ settings.setValue(
+ SettingScope.User,
+ 'selectedAuthType',
+ AuthType.USE_GEMINI,
+ );
+ } else if (process.env.CLOUD_SHELL === 'true') {
+ settings.setValue(
+ SettingScope.User,
+ 'selectedAuthType',
+ AuthType.CLOUD_SHELL,
+ );
+ }
}
setMaxSizedBoxDebugging(config.getDebugMode());
diff --git a/packages/cli/src/ui/components/AuthDialog.tsx b/packages/cli/src/ui/components/AuthDialog.tsx
index d0601dc1..cea6727f 100644
--- a/packages/cli/src/ui/components/AuthDialog.tsx
+++ b/packages/cli/src/ui/components/AuthDialog.tsx
@@ -27,8 +27,22 @@ export function AuthDialog({
initialErrorMessage || null,
);
const items = [
- { label: 'Login with Google', value: AuthType.LOGIN_WITH_GOOGLE },
- { label: 'Gemini API Key (AI Studio)', value: AuthType.USE_GEMINI },
+ {
+ label: 'Login with Google',
+ value: AuthType.LOGIN_WITH_GOOGLE,
+ },
+ ...(process.env.CLOUD_SHELL === 'true'
+ ? [
+ {
+ label: 'Use Cloud Shell user credentials',
+ value: AuthType.CLOUD_SHELL,
+ },
+ ]
+ : []),
+ {
+ label: 'Use Gemini API Key',
+ value: AuthType.USE_GEMINI,
+ },
{ label: 'Vertex AI', value: AuthType.USE_VERTEX_AI },
];