Skip to content

Commit 0412c1a

Browse files
authored
fix: resolve DATAPROC_CONFIG_PATH environment variable handling (#29)
Merge PR #29: DATAPROC_CONFIG_PATH fix Enhanced config diagnostic system with proper environment variable detection and improved error messaging for configuration path issues.
2 parents 85cac66 + 425f79f commit 0412c1a

File tree

2 files changed

+147
-6
lines changed

2 files changed

+147
-6
lines changed

src/config/server.ts

Lines changed: 75 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,13 +122,34 @@ export async function getServerConfig(configPath?: string): Promise<ServerConfig
122122
}
123123
}
124124

125+
// Add comprehensive diagnostic logging for configuration path resolution
126+
console.error(`[DIAGNOSTIC] ===== Configuration Path Resolution =====`);
127+
console.error(
128+
`[DIAGNOSTIC] configPath parameter: ${configPath ? `"${configPath}"` : 'undefined'}`
129+
);
130+
console.error(
131+
`[DIAGNOSTIC] DATAPROC_CONFIG_PATH env var: ${process.env.DATAPROC_CONFIG_PATH ? `"${process.env.DATAPROC_CONFIG_PATH}"` : 'undefined'}`
132+
);
133+
console.error(`[DIAGNOSTIC] Default config path: "${path.join(APP_ROOT, 'config/server.json')}"`);
134+
125135
// Use config path from environment variable, parameter, or default (now absolute)
126136
const filePath =
127137
configPath || process.env.DATAPROC_CONFIG_PATH || path.join(APP_ROOT, 'config/server.json');
128138

129-
// Log the current working directory and absolute config path for debugging
130-
console.error(`[DIAGNOSTIC] Server Config: Current working directory: ${process.cwd()}`);
131-
console.error(`[DIAGNOSTIC] Server Config: Absolute config path: ${filePath}`);
139+
// Determine which configuration source is being used
140+
let configSource: string;
141+
if (configPath) {
142+
configSource = 'direct parameter';
143+
} else if (process.env.DATAPROC_CONFIG_PATH) {
144+
configSource = 'DATAPROC_CONFIG_PATH environment variable';
145+
} else {
146+
configSource = 'default path';
147+
}
148+
149+
console.error(`[DIAGNOSTIC] Configuration source: ${configSource}`);
150+
console.error(`[DIAGNOSTIC] Final config file path: "${filePath}"`);
151+
console.error(`[DIAGNOSTIC] Current working directory: ${process.cwd()}`);
152+
console.error(`[DIAGNOSTIC] Config path is absolute: ${path.isAbsolute(filePath)}`);
132153

133154
// Store the config directory for other modules to use
134155
// eslint-disable-next-line no-undef
@@ -137,10 +158,24 @@ export async function getServerConfig(configPath?: string): Promise<ServerConfig
137158
console.error(`[DIAGNOSTIC] Server Config: Config directory: ${global.DATAPROC_CONFIG_DIR}`);
138159

139160
try {
140-
// Check if the config file exists
161+
// Check if the config file exists and is readable
162+
console.error(`[DIAGNOSTIC] ===== Config File Accessibility Check =====`);
141163
try {
142-
await fs.access(filePath);
164+
await fs.access(filePath, fs.constants.F_OK);
165+
console.error(`[DIAGNOSTIC] Config file exists: YES`);
166+
167+
try {
168+
await fs.access(filePath, fs.constants.R_OK);
169+
console.error(`[DIAGNOSTIC] Config file is readable: YES`);
170+
} catch (readError) {
171+
const errorMessage = readError instanceof Error ? readError.message : String(readError);
172+
console.error(`[DIAGNOSTIC] Config file is readable: NO - ${errorMessage}`);
173+
throw readError;
174+
}
143175
} catch (error) {
176+
const errorMessage = error instanceof Error ? error.message : String(error);
177+
console.error(`[DIAGNOSTIC] Config file exists: NO - ${errorMessage}`);
178+
console.error(`[DIAGNOSTIC] Will use default configuration with MCP overrides`);
144179
// Config file doesn't exist, use defaults with MCP overrides (don't auto-create)
145180
const defaultWithMcp = {
146181
profileManager: {
@@ -162,8 +197,14 @@ export async function getServerConfig(configPath?: string): Promise<ServerConfig
162197
}
163198

164199
// Read the config file
200+
console.error(`[DIAGNOSTIC] ===== Loading Config File =====`);
201+
console.error(`[DIAGNOSTIC] Reading config from: "${filePath}"`);
165202
const configJson = await fs.readFile(filePath, 'utf8');
203+
console.error(`[DIAGNOSTIC] Config file size: ${configJson.length} bytes`);
204+
166205
const config = JSON.parse(configJson) as Partial<ServerConfig>;
206+
console.error(`[DIAGNOSTIC] Successfully parsed config file`);
207+
console.error(`[DIAGNOSTIC] Config contains keys: [${Object.keys(config).join(', ')}]`);
167208

168209
// Merge with default config, then MCP config, then file config (priority order)
169210
const mergedConfig = {
@@ -184,6 +225,28 @@ export async function getServerConfig(configPath?: string): Promise<ServerConfig
184225
},
185226
};
186227

228+
console.error(`[DIAGNOSTIC] ===== Configuration Resolution Summary =====`);
229+
console.error(`[DIAGNOSTIC] Configuration loaded successfully from: ${configSource}`);
230+
console.error(`[DIAGNOSTIC] Final config file used: "${filePath}"`);
231+
console.error(
232+
`[DIAGNOSTIC] Profile manager root: "${mergedConfig.profileManager.rootConfigPath}"`
233+
);
234+
console.error(
235+
`[DIAGNOSTIC] Cluster tracker state file: "${mergedConfig.clusterTracker.stateFilePath}"`
236+
);
237+
if (mergedConfig.authentication?.impersonateServiceAccount) {
238+
console.error(
239+
`[DIAGNOSTIC] Service account impersonation: "${mergedConfig.authentication.impersonateServiceAccount}"`
240+
);
241+
}
242+
if (mergedConfig.authentication?.projectId) {
243+
console.error(`[DIAGNOSTIC] Default project ID: "${mergedConfig.authentication.projectId}"`);
244+
}
245+
if (mergedConfig.authentication?.region) {
246+
console.error(`[DIAGNOSTIC] Default region: "${mergedConfig.authentication.region}"`);
247+
}
248+
console.error(`[DIAGNOSTIC] ================================================`);
249+
187250
if (process.env.LOG_LEVEL === 'debug') {
188251
console.error(
189252
'[DEBUG] Server Config: Final merged configuration:',
@@ -193,7 +256,13 @@ export async function getServerConfig(configPath?: string): Promise<ServerConfig
193256

194257
return mergedConfig;
195258
} catch (error) {
196-
console.error(`[ERROR] Error loading server config from ${filePath}:`, error);
259+
const errorMessage = error instanceof Error ? error.message : String(error);
260+
console.error(`[ERROR] Error loading server config from ${filePath}: ${errorMessage}`);
261+
console.error(`[DIAGNOSTIC] ===== Configuration Error Fallback =====`);
262+
console.error(`[DIAGNOSTIC] Failed to load config from: "${filePath}"`);
263+
console.error(`[DIAGNOSTIC] Falling back to default configuration with MCP overrides`);
264+
console.error(`[DIAGNOSTIC] ================================================`);
265+
197266
if (process.env.LOG_LEVEL === 'debug')
198267
console.error('[DEBUG] Using default server config with MCP overrides');
199268
return {
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
#!/usr/bin/env node
2+
3+
/**
4+
* Test script to demonstrate the diagnostic logging for configuration loading
5+
* This test helps identify why DATAPROC_CONFIG_PATH environment variable might be ignored
6+
*
7+
* CI/CD Safe: Uses repo config files that exist in all environments
8+
*/
9+
10+
import { getServerConfig } from '../../build/config/server.js';
11+
import { fileURLToPath } from 'url';
12+
import { dirname, join } from 'path';
13+
14+
const __filename = fileURLToPath(import.meta.url);
15+
const __dirname = dirname(__filename);
16+
17+
console.log('='.repeat(80));
18+
console.log('TESTING CONFIGURATION DIAGNOSTIC LOGGING');
19+
console.log('This test demonstrates the configuration path resolution logic');
20+
console.log('='.repeat(80));
21+
22+
async function runTest(testName, testFn) {
23+
console.log(`\n${testName}`);
24+
console.log('-'.repeat(testName.length));
25+
try {
26+
await testFn();
27+
} catch (error) {
28+
console.error('Test error:', error.message);
29+
}
30+
console.log(''); // Add spacing between tests
31+
}
32+
33+
// Test 1: Default configuration (no parameters)
34+
await runTest('1. Testing with no parameters (should use default config path):', async () => {
35+
// Clear environment variable for this test
36+
delete process.env.DATAPROC_CONFIG_PATH;
37+
await getServerConfig();
38+
});
39+
40+
// Test 2: Direct configPath parameter
41+
await runTest('2. Testing with direct configPath parameter (should override everything):', async () => {
42+
process.env.DATAPROC_CONFIG_PATH = join(__dirname, '../../config/server.json');
43+
await getServerConfig('/nonexistent/direct-config.json');
44+
});
45+
46+
// Test 3: Environment variable only
47+
await runTest('3. Testing with DATAPROC_CONFIG_PATH environment variable only:', async () => {
48+
process.env.DATAPROC_CONFIG_PATH = join(__dirname, '../../config/server.json');
49+
await getServerConfig(); // No direct parameter
50+
});
51+
52+
// Test 4: Both parameter and environment variable (parameter should win)
53+
await runTest('4. Testing precedence: configPath parameter vs environment variable:', async () => {
54+
process.env.DATAPROC_CONFIG_PATH = join(__dirname, '../../config/server.json');
55+
await getServerConfig('/another/nonexistent/config.json');
56+
});
57+
58+
// Test 5: Test with a valid config file path (if it exists)
59+
await runTest('5. Testing with user\'s actual config file (if accessible):', async () => {
60+
delete process.env.DATAPROC_CONFIG_PATH;
61+
await getServerConfig(join(__dirname, '../../config/server.json'));
62+
});
63+
64+
console.log('='.repeat(80));
65+
console.log('DIAGNOSTIC LOGGING TEST COMPLETE');
66+
console.log('');
67+
console.log('KEY INSIGHTS FROM THIS TEST:');
68+
console.log('- Check which configuration source is being used in the diagnostic output');
69+
console.log('- If DATAPROC_CONFIG_PATH is being ignored, look for a direct configPath parameter');
70+
console.log('- The precedence is: configPath parameter > DATAPROC_CONFIG_PATH > default');
71+
console.log('- File accessibility issues will be clearly shown in the diagnostic output');
72+
console.log('='.repeat(80));

0 commit comments

Comments
 (0)