fix(config): persist runtime patches to active overlay config path

This commit is contained in:
William Valentin
2026-02-18 19:43:55 -08:00
parent 0a664ddb21
commit 7e480f11fc
5 changed files with 38 additions and 5 deletions
+3 -2
View File
@@ -3,7 +3,7 @@ import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'fs';
import { dirname } from 'path';
import { createInterface } from 'readline/promises';
import { parse } from 'yaml';
import { getConfigPath } from './shared.js';
import { getConfigPath, resolveEffectiveConfigPath } from './shared.js';
import { createPrompter } from './setup/prompts.js';
import { ConfigBuilder } from './setup/config.js';
import { runFirstRunWizard, runMenu } from './setup/orchestrator.js';
@@ -47,7 +47,8 @@ export async function runSetup(configPath: string): Promise<void> {
const { startDaemon } = await import('../daemon/index.js');
const { loadConfig } = await import('../config/index.js');
const config = loadConfig(configPath);
const daemon = await startDaemon(config, { configPath });
const persistConfigPath = resolveEffectiveConfigPath(configPath);
const daemon = await startDaemon(config, { configPath, persistConfigPath });
await new Promise<void>(resolve => daemon.lifecycle.onShutdown(async () => resolve()));
return;
}
+13
View File
@@ -58,6 +58,19 @@ export function resolveOverlayPath(basePath: string): string | undefined {
return join(configDir, `${env}.yaml`);
}
/**
* Resolve the effective config source path for runtime persistence.
* When FLYNN_ENV is set and overlay file exists, persist to the overlay file.
* Otherwise persist to the base config path.
*/
export function resolveEffectiveConfigPath(basePath: string): string {
const overlayPath = resolveOverlayPath(basePath);
if (overlayPath && existsSync(overlayPath)) {
return overlayPath;
}
return basePath;
}
/** Load config without throwing. Returns { config } or { error }. */
export function loadConfigSafe(configPath?: string): { config?: Config; error?: string } {
const path = configPath ?? getConfigPath();
+6 -2
View File
@@ -1,5 +1,5 @@
import type { Command } from 'commander';
import { loadConfigSafe, getConfigPath } from './shared.js';
import { loadConfigSafe, getConfigPath, resolveEffectiveConfigPath } from './shared.js';
import { existsSync } from 'fs';
export function registerStartCommand(program: Command): void {
@@ -9,6 +9,7 @@ export function registerStartCommand(program: Command): void {
.option('-c, --config <path>', 'Config file path')
.action(async (opts: { config?: string }) => {
const configPath = opts.config ?? getConfigPath();
const persistConfigPath = resolveEffectiveConfigPath(configPath);
if (!existsSync(configPath)) {
// Offer setup wizard
@@ -35,6 +36,9 @@ export function registerStartCommand(program: Command): void {
console.log('Flynn starting...');
console.log(`Loading config from: ${configPath}`);
if (persistConfigPath !== configPath) {
console.log(`Runtime config persistence target: ${persistConfigPath}`);
}
const { config, error } = loadConfigSafe(configPath);
if (!config) {
@@ -44,7 +48,7 @@ export function registerStartCommand(program: Command): void {
// Dynamic import to avoid loading daemon code for other commands
const { startDaemon } = await import('../daemon/index.js');
const daemon = await startDaemon(config, { configPath });
const daemon = await startDaemon(config, { configPath, persistConfigPath });
if (config.telegram) {
console.log(`Allowed Telegram chat IDs: ${config.telegram.allowed_chat_ids.join(', ')}`);