()
| 21 | }; |
| 22 | |
| 23 | export const loadConfig = (): void => { |
| 24 | const logger = createLogger("trainloop-config"); |
| 25 | /** |
| 26 | * Load TrainLoop configuration into environment variables. |
| 27 | * |
| 28 | * Priority order: |
| 29 | * 1. Existing environment variables (highest priority) |
| 30 | * 2. Config file values (fallback) |
| 31 | * 3. Fail if critical variables are missing from both sources |
| 32 | * |
| 33 | * Config path resolution: |
| 34 | * 1. TRAINLOOP_CONFIG_PATH environment variable |
| 35 | * 2. Auto-discovery (trainloop/trainloop.config.yaml or ./trainloop.config.yaml) |
| 36 | */ |
| 37 | logger.debug("Starting config load process"); |
| 38 | |
| 39 | // Determine config path - prioritize env var, then auto-discovery |
| 40 | logger.debug(`Config path resolution: TRAINLOOP_CONFIG_PATH=${process.env.TRAINLOOP_CONFIG_PATH || "(not set)"}`); |
| 41 | logger.debug(`Current working directory: ${process.cwd()}`); |
| 42 | |
| 43 | const trainloopSubdirPath = path.join(process.cwd(), "trainloop/trainloop.config.yaml"); |
| 44 | const rootPath = path.join(process.cwd(), "trainloop.config.yaml"); |
| 45 | |
| 46 | logger.debug(`Checking for config at: ${trainloopSubdirPath} - exists: ${fs.existsSync(trainloopSubdirPath)}`); |
| 47 | logger.debug(`Checking for config at: ${rootPath} - exists: ${fs.existsSync(rootPath)}`); |
| 48 | |
| 49 | const configPath = process.env.TRAINLOOP_CONFIG_PATH ?? |
| 50 | (fs.existsSync(trainloopSubdirPath) ? trainloopSubdirPath : rootPath); |
| 51 | |
| 52 | // Check if config path changed - if so, reset environment vars that were set by config |
| 53 | if (lastLoadedConfigPath !== null && lastLoadedConfigPath !== configPath) { |
| 54 | logger.debug(`Config path changed from ${lastLoadedConfigPath} to ${configPath}, resetting config tracking`); |
| 55 | |
| 56 | // Clear environment variables that were set by config and haven't been modified by user |
| 57 | for (const envVar of configSetEnvVars) { |
| 58 | const configValue = configSetValues.get(envVar); |
| 59 | const currentValue = process.env[envVar]; |
| 60 | if (configValue !== undefined && currentValue === configValue) { |
| 61 | // Value hasn't been changed by user, safe to clear |
| 62 | delete process.env[envVar]; |
| 63 | logger.debug(`Cleared config-set env var: ${envVar} (was: ${configValue})`); |
| 64 | } else { |
| 65 | logger.debug(`Preserving user-modified env var: ${envVar} (config: ${configValue}, current: ${currentValue})`); |
| 66 | } |
| 67 | } |
| 68 | |
| 69 | // Clear internal tracking so subsequent config loads can reapply as needed |
| 70 | configSetEnvVars.clear(); |
| 71 | configSetValues.clear(); |
| 72 | } |
| 73 | |
| 74 | // Check which environment variables are already set (excluding those we set from config) |
| 75 | const dataFolderSet = !!process.env.TRAINLOOP_DATA_FOLDER && !configSetEnvVars.has('TRAINLOOP_DATA_FOLDER'); |
| 76 | const hostAllowlistSet = !!process.env.TRAINLOOP_HOST_ALLOWLIST && |
| 77 | !configSetEnvVars.has('TRAINLOOP_HOST_ALLOWLIST') && |
| 78 | process.env.TRAINLOOP_HOST_ALLOWLIST !== DEFAULT_HOST_ALLOWLIST.join(','); |
| 79 | |
| 80 | logger.debug(`Host allowlist check: value="${process.env.TRAINLOOP_HOST_ALLOWLIST}", tracked=${configSetEnvVars.has('TRAINLOOP_HOST_ALLOWLIST')}, default="${DEFAULT_HOST_ALLOWLIST.join(',')}", set=${hostAllowlistSet}`); |
no test coverage detected