feat(02-02): add overlay file validation to flynn doctor

- Import resolveOverlayPath from shared.ts
- Add checkOverlayExists check (skip when no FLYNN_ENV, pass/fail for overlay file)
- Insert after checkConfigExists in allChecks array
- All 1087 tests pass, typecheck clean
This commit is contained in:
William Valentin
2026-02-09 21:00:18 -08:00
parent 19287c4cad
commit 6bd372162e
+14 -1
View File
@@ -1,6 +1,6 @@
import type { Command } from 'commander'; import type { Command } from 'commander';
import type { Config } from '../config/index.js'; import type { Config } from '../config/index.js';
import { getConfigPath, getDataDir, formatStatus } from './shared.js'; import { getConfigPath, getDataDir, formatStatus, resolveOverlayPath } from './shared.js';
import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'fs'; import { existsSync, readFileSync, writeFileSync, unlinkSync } from 'fs';
import { resolve, join } from 'path'; import { resolve, join } from 'path';
import { parse } from 'yaml'; import { parse } from 'yaml';
@@ -27,6 +27,18 @@ const checkConfigExists: Check = async (ctx) => {
return { status: 'fail', label: 'Config file exists', detail: `not found at ${ctx.configPath}` }; return { status: 'fail', label: 'Config file exists', detail: `not found at ${ctx.configPath}` };
}; };
const checkOverlayExists: Check = async (ctx) => {
const overlayPath = resolveOverlayPath(ctx.configPath);
if (!overlayPath) {
return { status: 'skip', label: 'Config overlay', detail: '(FLYNN_ENV not set)' };
}
const env = process.env.FLYNN_ENV;
if (existsSync(overlayPath)) {
return { status: 'pass', label: 'Config overlay', detail: `(${env}.yaml found)` };
}
return { status: 'fail', label: 'Config overlay', detail: `FLYNN_ENV=${env} but ${overlayPath} not found` };
};
const checkConfigParses: Check = async (ctx) => { const checkConfigParses: Check = async (ctx) => {
if (!existsSync(ctx.configPath)) { if (!existsSync(ctx.configPath)) {
return { status: 'skip', label: 'Config parses', detail: '(no config file)' }; return { status: 'skip', label: 'Config parses', detail: '(no config file)' };
@@ -203,6 +215,7 @@ const checkTailscale: Check = async (ctx) => {
const allChecks: Check[] = [ const allChecks: Check[] = [
checkConfigExists, checkConfigExists,
checkOverlayExists,
checkConfigParses, checkConfigParses,
checkConfigValidates, checkConfigValidates,
checkEnvVars, checkEnvVars,