From 7ff825db88f0e00053896646c623424f444f3c71 Mon Sep 17 00:00:00 2001 From: Rhuan Barreto Date: Fri, 20 Mar 2026 16:13:23 +0100 Subject: [PATCH] fix: treat rule import failures as errors instead of warnings Rule files that fail to import (e.g., missing module resolution) were silently logged as warnings and skipped, causing `archgate check` to report "No rules to check" and exit 0. This masked real configuration errors in CI. Now import failures throw, and the check command catches them and exits with code 1. --- src/commands/check.ts | 10 +++++++++- src/engine/loader.ts | 40 +++++++++++++++++----------------------- 2 files changed, 26 insertions(+), 24 deletions(-) diff --git a/src/commands/check.ts b/src/commands/check.ts index 65821ebc..80c86735 100644 --- a/src/commands/check.ts +++ b/src/commands/check.ts @@ -29,7 +29,15 @@ export function registerCheckCommand(program: Command) { process.exit(1); } - const loadedAdrs = await loadRuleAdrs(projectRoot, opts.adr); + let loadedAdrs; + try { + loadedAdrs = await loadRuleAdrs(projectRoot, opts.adr); + } catch (err) { + logError( + err instanceof Error ? err.message : `Failed to load rules: ${err}` + ); + process.exit(1); + } if (loadedAdrs.length === 0) { if (opts.json) { diff --git a/src/engine/loader.ts b/src/engine/loader.ts index 7b7706ed..c36f2a5e 100644 --- a/src/engine/loader.ts +++ b/src/engine/loader.ts @@ -22,7 +22,7 @@ const RuleSetSchema = z.object({ }) ), }); -import { logDebug, logWarn } from "../helpers/log"; +import { logDebug } from "../helpers/log"; import { projectPaths } from "../helpers/paths"; import { ensureRulesShim } from "../helpers/rules-shim"; @@ -90,30 +90,24 @@ export async function loadRuleAdrs( ); } - try { - // Cache-bust: Bun caches import() per-process, so append a timestamp - // to force re-reading from disk on every call (critical for repeated invocations). - // Use file:// URL to handle Windows backslash paths in import(). - const rulesUrl = `${pathToFileURL(rulesFile).href}?t=${Date.now()}`; - const mod = await import(rulesUrl); - const parsed = RuleSetSchema.safeParse(mod.default); - - if (!parsed.success) { - logWarn( - `ADR ${adr.frontmatter.id}: companion file does not export a valid RuleSet as default` - ); - return null; - } - - const ruleSet: RuleSet = parsed.data; - logDebug( - `Loaded ${Object.keys(ruleSet.rules).length} rules from ${adr.frontmatter.id}` + // Cache-bust: Bun caches import() per-process, so append a timestamp + // to force re-reading from disk on every call (critical for repeated invocations). + // Use file:// URL to handle Windows backslash paths in import(). + const rulesUrl = `${pathToFileURL(rulesFile).href}?t=${Date.now()}`; + const mod = await import(rulesUrl); + const parsed = RuleSetSchema.safeParse(mod.default); + + if (!parsed.success) { + throw new Error( + `ADR ${adr.frontmatter.id}: companion file does not export a valid RuleSet as default` ); - return { adr, ruleSet }; - } catch (err) { - logWarn(`Failed to import rules for ${adr.frontmatter.id}: ${err}`); - return null; } + + const ruleSet: RuleSet = parsed.data; + logDebug( + `Loaded ${Object.keys(ruleSet.rules).length} rules from ${adr.frontmatter.id}` + ); + return { adr, ruleSet }; }) );