@docker-doctor/cli 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- const require_src = require('./src-DYLANvt2.cjs');
2
+ const require_src = require('./src-D3jzc3GX.cjs');
3
3
  let node_fs_promises = require("node:fs/promises");
4
4
  node_fs_promises = require_src.__toESM(node_fs_promises, 1);
5
5
  let node_path = require("node:path");
@@ -581,9 +581,17 @@ const writeDiagnosticsDirectory = async (diagnostics, report, rootDir) => {
581
581
  recursive: true
582
582
  });
583
583
  await node_fs_promises.default.mkdir(dir, { recursive: true });
584
+ const sanitizedReport = {
585
+ ...report,
586
+ diagnostics: report.diagnostics.map((d) => ({
587
+ ...d,
588
+ file: sanitizePath(d.file),
589
+ message: sanitizeMessage(d.message)
590
+ }))
591
+ };
584
592
  await node_fs_promises.default.writeFile(node_path.default.join(dir, "diagnostics.json"), JSON.stringify({
585
593
  note: TRUST_BOUNDARY_NOTE,
586
- ...report
594
+ ...sanitizedReport
587
595
  }, null, 2), "utf-8");
588
596
  const writes = [];
589
597
  for (const [rule, ruleDiagnostics] of groupDiagnosticsByRule(diagnostics)) {
@@ -656,7 +664,7 @@ const buildHandoffPayload = (input) => {
656
664
  ];
657
665
  for (const [index, [rule, ruleDiagnostics]] of groups.entries()) {
658
666
  const [first] = ruleDiagnostics;
659
- const category = require_src.findRule(rule)?.category ?? "General";
667
+ const category = first.category ?? require_src.findRule(rule)?.category ?? "General";
660
668
  const countBadge = ruleDiagnostics.length > 1 ? ` (×${ruleDiagnostics.length})` : "";
661
669
  lines.push(`${index + 1}. ${SEVERITY_LABEL[first.severity]} ${category}: ${sanitizeMessage(first.message)} [${rule}]${countBadge}`, ` Fix: ${first.help}`);
662
670
  const files = [...new Set(ruleDiagnostics.map((d) => d.file))];
@@ -791,7 +799,7 @@ const printDiagnostics = (diagnostics, verbose, fileContents, categoryIssueCount
791
799
  console.log(`\n Run ${chalk.cyan("docker-doctor --verbose")} to list every error and warning`);
792
800
  const ruleCounts = {};
793
801
  for (const d of diagnostics) ruleCounts[d.rule] = (ruleCounts[d.rule] || 0) + 1;
794
- const migrationRules = Object.entries(ruleCounts).filter(([_, count]) => count >= 5);
802
+ const migrationRules = Object.entries(ruleCounts).filter(([, count]) => count >= 5);
795
803
  if (migrationRules.length > 0) {
796
804
  console.log();
797
805
  console.log(` ${chalk.yellow("⚠ Migration-scale change: sample before you sweep")}`);
@@ -918,7 +926,7 @@ const formatTerminal = async (diagnostics, score, label, project, verbose = fals
918
926
  let warningsCount = 0;
919
927
  let errorsCount = 0;
920
928
  for (const d of diagnostics) {
921
- const category = require_src.findRule(d.rule)?.category || "Best Practices";
929
+ const category = d.category ?? require_src.findRule(d.rule)?.category ?? "Best Practices";
922
930
  categoryIssueCounts[category] = (categoryIssueCounts[category] || 0) + 1;
923
931
  if (d.severity === "warning") warningsCount += 1;
924
932
  else if (d.severity === "error") errorsCount += 1;
@@ -1183,9 +1191,14 @@ const runInteractiveWizard = async (context) => {
1183
1191
  console.log(` Inputs and gating: ${chalk.cyan("https://docker-doctor.vercel.app/docs/guides/github-actions")}`);
1184
1192
  }
1185
1193
  }
1186
- if (context.diagnostics.length === 0) return;
1194
+ if (context.diagnostics.length === 0) return true;
1187
1195
  await runAgentHandoff(context);
1188
- } catch {}
1196
+ return true;
1197
+ } catch (error) {
1198
+ const msg = error instanceof Error ? error.message : String(error);
1199
+ console.error(`\n ${chalk.yellow("⚠")} Post-scan step failed: ${msg}`);
1200
+ return false;
1201
+ }
1189
1202
  };
1190
1203
  const runRulesEngine = async (rootDir, project, rulesConfig, categoriesConfig, projectFilesList, fileContents, options, setStatus) => {
1191
1204
  const diagnostics = [];
@@ -1200,7 +1213,7 @@ const runRulesEngine = async (rootDir, project, rulesConfig, categoriesConfig, p
1200
1213
  try {
1201
1214
  const content = await node_fs_promises.default.readFile(fullPath, "utf-8");
1202
1215
  fileContents[df] = content;
1203
- const instructions = require_src.parseDockerfile(content);
1216
+ const instructions = require_src.parseDockerfile(content, df);
1204
1217
  return require_src.runDockerfileRules(instructions, df, projectFilesList, rulesConfig, categoriesConfig);
1205
1218
  } catch (error) {
1206
1219
  const msg = error instanceof Error ? error.message : String(error);
@@ -1241,6 +1254,7 @@ const runRulesEngine = async (rootDir, project, rulesConfig, categoriesConfig, p
1241
1254
  };
1242
1255
  };
1243
1256
  const SCAN_FAILURE_EXIT_CODE = 2;
1257
+ const POST_SCAN_FAILURE_EXIT_CODE = 1;
1244
1258
  const WHITESPACE_RUN = /\s+/gu;
1245
1259
  const flattenMessage = (message) => message.replaceAll(WHITESPACE_RUN, " ").trim();
1246
1260
  const scanExitCode = (scanIncomplete, failing) => {
@@ -1336,12 +1350,14 @@ program.argument("[dir]", "directory to scan", ".").option("-v, --verbose", "sho
1336
1350
  return;
1337
1351
  }
1338
1352
  await formatTerminal(diagnostics, score, label, project, options.verbose, fileContents);
1339
- if (process.stdout.isTTY && process.stdin.isTTY) await runInteractiveWizard({
1353
+ let wizardOk = true;
1354
+ if (process.stdout.isTTY && process.stdin.isTTY) wizardOk = await runInteractiveWizard({
1340
1355
  diagnostics,
1341
1356
  report: require_src.toJsonReport(diagnostics, score, label, project),
1342
1357
  rootDir
1343
1358
  });
1344
- process.exitCode = scanExitCode(scanIncomplete, hasErrors);
1359
+ const exitCode = scanExitCode(scanIncomplete, hasErrors);
1360
+ process.exitCode = wizardOk ? exitCode : Math.max(POST_SCAN_FAILURE_EXIT_CODE, exitCode);
1345
1361
  } finally {
1346
1362
  if (spinnerInterval !== null) {
1347
1363
  clearInterval(spinnerInterval);
@@ -1351,7 +1367,7 @@ program.argument("[dir]", "directory to scan", ".").option("-v, --verbose", "sho
1351
1367
  } catch (error) {
1352
1368
  const msg = error instanceof Error ? error.message : String(error);
1353
1369
  console.error(`Error: ${msg}`);
1354
- process.exit(1);
1370
+ process.exitCode = 1;
1355
1371
  }
1356
1372
  });
1357
1373
  const CURATED_INSTALL_AGENTS = [
@@ -1385,10 +1401,14 @@ const resolveInstallAgents = async (requested) => {
1385
1401
  program.command("install").description("install the Docker Doctor agent skill for your coding agents").option("-a, --agent <agents...>", "agent id(s) to install for (e.g. claude-code codex cursor)").option("-g, --global", "install into each agent's global skills directory (e.g. ~/.claude/skills) instead of the current project").action(async (options) => {
1386
1402
  if (!getSkillSourceDirectory()) {
1387
1403
  console.error("Bundled skill not found — this looks like a broken installation.");
1388
- process.exit(1);
1404
+ process.exitCode = 1;
1405
+ return;
1389
1406
  }
1390
1407
  const agents = await resolveInstallAgents(options.agent);
1391
- if (agents === null) process.exit(1);
1408
+ if (agents === null) {
1409
+ process.exitCode = 1;
1410
+ return;
1411
+ }
1392
1412
  if (agents.length === 0) {
1393
1413
  console.log("Nothing selected — skipped.");
1394
1414
  return;
@@ -1399,7 +1419,8 @@ program.command("install").description("install the Docker Doctor agent skill fo
1399
1419
  });
1400
1420
  if (!result) {
1401
1421
  console.error("Failed to install the skill.");
1402
- process.exit(1);
1422
+ process.exitCode = 1;
1423
+ return;
1403
1424
  }
1404
1425
  for (const installed of result.installed) console.log(` ${chalk.green("✔")} ${agentDisplayName(installed.agent)} → ${installed.path}`);
1405
1426
  for (const failed of result.failed) console.log(` ${chalk.red("✖")} ${agentDisplayName(failed.agent)}: ${failed.error}`);
@@ -1423,7 +1444,8 @@ rules.command("explain <rule>").description("explain a specific rule in detail")
1423
1444
  const rule = require_src.findRule(ruleKey);
1424
1445
  if (!rule) {
1425
1446
  console.error(`Rule '${ruleKey}' not found.`);
1426
- process.exit(1);
1447
+ process.exitCode = 1;
1448
+ return;
1427
1449
  }
1428
1450
  console.log(`\nRule: ${rule.key}`);
1429
1451
  console.log(`Category: ${rule.category}`);