fix: exclude DEBUG and DEBUG_MODE from project .env files by default (#5289)

Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
Oleksandr Gotgelf
2025-08-03 20:44:15 +02:00
committed by GitHub
parent ae8a8f6062
commit c0b4fc9506
7 changed files with 305 additions and 11 deletions

View File

@@ -24,6 +24,7 @@ import { CustomTheme } from '../ui/themes/theme.js';
export const SETTINGS_DIRECTORY_NAME = '.gemini';
export const USER_SETTINGS_DIR = path.join(homedir(), SETTINGS_DIRECTORY_NAME);
export const USER_SETTINGS_PATH = path.join(USER_SETTINGS_DIR, 'settings.json');
export const DEFAULT_EXCLUDED_ENV_VARS = ['DEBUG', 'DEBUG_MODE'];
export function getSystemSettingsPath(): string {
if (process.env.GEMINI_CLI_SYSTEM_SETTINGS_PATH) {
@@ -38,6 +39,10 @@ export function getSystemSettingsPath(): string {
}
}
export function getWorkspaceSettingsPath(workspaceDir: string): string {
return path.join(workspaceDir, SETTINGS_DIRECTORY_NAME, 'settings.json');
}
export type DnsResolutionOrder = 'ipv4first' | 'verbatim';
export enum SettingScope {
@@ -115,6 +120,9 @@ export interface Settings {
disableUpdateNag?: boolean;
memoryDiscoveryMaxDirs?: number;
// Environment variables to exclude from project .env files
excludedProjectEnvVars?: string[];
dnsResolutionOrder?: DnsResolutionOrder;
}
@@ -292,15 +300,61 @@ export function setUpCloudShellEnvironment(envFilePath: string | null): void {
}
}
export function loadEnvironment(): void {
export function loadEnvironment(settings?: Settings): void {
const envFilePath = findEnvFile(process.cwd());
// Cloud Shell environment variable handling
if (process.env.CLOUD_SHELL === 'true') {
setUpCloudShellEnvironment(envFilePath);
}
// If no settings provided, try to load workspace settings for exclusions
let resolvedSettings = settings;
if (!resolvedSettings) {
const workspaceSettingsPath = getWorkspaceSettingsPath(process.cwd());
try {
if (fs.existsSync(workspaceSettingsPath)) {
const workspaceContent = fs.readFileSync(
workspaceSettingsPath,
'utf-8',
);
const parsedWorkspaceSettings = JSON.parse(
stripJsonComments(workspaceContent),
) as Settings;
resolvedSettings = resolveEnvVarsInObject(parsedWorkspaceSettings);
}
} catch (_e) {
// Ignore errors loading workspace settings
}
}
if (envFilePath) {
dotenv.config({ path: envFilePath, quiet: true });
// Manually parse and load environment variables to handle exclusions correctly.
// This avoids modifying environment variables that were already set from the shell.
try {
const envFileContent = fs.readFileSync(envFilePath, 'utf-8');
const parsedEnv = dotenv.parse(envFileContent);
const excludedVars =
resolvedSettings?.excludedProjectEnvVars || DEFAULT_EXCLUDED_ENV_VARS;
const isProjectEnvFile = !envFilePath.includes(GEMINI_DIR);
for (const key in parsedEnv) {
if (Object.hasOwn(parsedEnv, key)) {
// If it's a project .env file, skip loading excluded variables.
if (isProjectEnvFile && excludedVars.includes(key)) {
continue;
}
// Load variable only if it's not already set in the environment.
if (!Object.hasOwn(process.env, key)) {
process.env[key] = parsedEnv[key];
}
}
}
} catch (_e) {
// Errors are ignored to match the behavior of `dotenv.config({ quiet: true })`.
}
}
}
@@ -309,7 +363,6 @@ export function loadEnvironment(): void {
* Project settings override user settings.
*/
export function loadSettings(workspaceDir: string): LoadedSettings {
loadEnvironment();
let systemSettings: Settings = {};
let userSettings: Settings = {};
let workspaceSettings: Settings = {};
@@ -331,6 +384,8 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
// We expect homedir to always exist and be resolvable.
const realHomeDir = fs.realpathSync(resolvedHomeDir);
const workspaceSettingsPath = getWorkspaceSettingsPath(workspaceDir);
// Load system settings
try {
if (fs.existsSync(systemSettingsPath)) {
@@ -369,12 +424,6 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
});
}
const workspaceSettingsPath = path.join(
workspaceDir,
SETTINGS_DIRECTORY_NAME,
'settings.json',
);
// This comparison is now much more reliable.
if (realWorkspaceDir !== realHomeDir) {
// Load workspace settings
@@ -402,7 +451,8 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
}
}
return new LoadedSettings(
// Create LoadedSettings first
const loadedSettings = new LoadedSettings(
{
path: systemSettingsPath,
settings: systemSettings,
@@ -417,6 +467,11 @@ export function loadSettings(workspaceDir: string): LoadedSettings {
},
settingsErrors,
);
// Load environment with merged settings
loadEnvironment(loadedSettings.merged);
return loadedSettings;
}
export function saveSettings(settingsFile: SettingsFile): void {