@codacy/analysis-runner 0.2.2 → 0.3.0

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/index.d.ts CHANGED
@@ -109,7 +109,11 @@ declare function formatTextSummary(result: AnalysisResult, isInspect?: boolean):
109
109
  * 3. Default (empty patterns, no local config)
110
110
  */
111
111
 
112
- /** Reads a CodacyConfig from disk. Returns null if the file doesn't exist. */
112
+ /**
113
+ * Reads a CodacyConfig from disk.
114
+ * Returns null if the file doesn't exist. Throws on parse/permission errors
115
+ * so callers can distinguish "no config" from "broken config".
116
+ */
113
117
  declare function readCodacyConfig(repositoryRoot: string): Promise<CodacyConfig | null>;
114
118
  /** Writes a CodacyConfig to disk, creating the .codacy/ directory if needed. */
115
119
  declare function writeCodacyConfig(repositoryRoot: string, config: CodacyConfig): Promise<string>;
package/dist/index.js CHANGED
@@ -61,6 +61,7 @@ module.exports = __toCommonJS(index_exports);
61
61
  // src/analyze.ts
62
62
  var import_os = __toESM(require("os"));
63
63
  var import_path3 = __toESM(require("path"));
64
+ var import_child_process2 = require("child_process");
64
65
 
65
66
  // src/registry.ts
66
67
  var adapters = /* @__PURE__ */ new Map();
@@ -93,14 +94,18 @@ var CODACY_DIR = ".codacy";
93
94
  var CONFIG_FILE = "codacy.config.json";
94
95
  async function readCodacyConfig(repositoryRoot) {
95
96
  const configPath = import_path.default.join(repositoryRoot, CODACY_DIR, CONFIG_FILE);
97
+ let raw;
96
98
  try {
97
- const raw = await import_promises.default.readFile(configPath, "utf-8");
98
- const config = JSON.parse(raw);
99
- coerceParameterValues(config);
100
- return config;
101
- } catch {
102
- return null;
99
+ raw = await import_promises.default.readFile(configPath, "utf-8");
100
+ } catch (err) {
101
+ if (err instanceof Error && "code" in err && err.code === "ENOENT") {
102
+ return null;
103
+ }
104
+ throw err;
103
105
  }
106
+ const config = JSON.parse(raw);
107
+ coerceParameterValues(config);
108
+ return config;
104
109
  }
105
110
  function coerceParameterValues(config) {
106
111
  for (const tool of config.tools) {
@@ -440,6 +445,76 @@ async function analyze(options) {
440
445
  const toolTimeout = options.toolTimeout || 3e5;
441
446
  const parallelTools = options.parallelTools || 1;
442
447
  const logger = options.logger ?? nullLogger;
448
+ const emptyCapability = {
449
+ ready: [],
450
+ unavailable: [],
451
+ checkedAt: (/* @__PURE__ */ new Date()).toISOString()
452
+ };
453
+ try {
454
+ (0, import_child_process2.execSync)("git rev-parse --is-inside-work-tree", {
455
+ cwd: options.repositoryRoot,
456
+ stdio: "pipe"
457
+ });
458
+ } catch {
459
+ return buildResult(
460
+ startedAt,
461
+ options.repositoryRoot,
462
+ mode,
463
+ emptyCapability,
464
+ [],
465
+ [
466
+ {
467
+ toolId: "runner",
468
+ phase: "requirementCheck",
469
+ kind: "NotAGitRepository",
470
+ message: `${options.repositoryRoot} is not a git repository. Codacy analysis requires a git repository for file discovery. Run \`git init\` to initialize one.`,
471
+ level: "error"
472
+ }
473
+ ],
474
+ []
475
+ );
476
+ }
477
+ let codacyConfig;
478
+ try {
479
+ codacyConfig = await readCodacyConfig(options.repositoryRoot);
480
+ } catch (err) {
481
+ return buildResult(
482
+ startedAt,
483
+ options.repositoryRoot,
484
+ mode,
485
+ emptyCapability,
486
+ [],
487
+ [
488
+ {
489
+ toolId: "runner",
490
+ phase: "toolConfig",
491
+ kind: "InvalidConfig",
492
+ message: `.codacy/codacy.config.json is invalid: ${err instanceof Error ? err.message : String(err)}`,
493
+ level: "error"
494
+ }
495
+ ],
496
+ []
497
+ );
498
+ }
499
+ if (!codacyConfig) {
500
+ return buildResult(
501
+ startedAt,
502
+ options.repositoryRoot,
503
+ mode,
504
+ emptyCapability,
505
+ [],
506
+ [
507
+ {
508
+ toolId: "runner",
509
+ phase: "toolConfig",
510
+ kind: "MissingConfig",
511
+ message: "No .codacy/codacy.config.json found. Run `codacy-analysis init` to initialize the repository.",
512
+ level: "error"
513
+ }
514
+ ],
515
+ []
516
+ );
517
+ }
443
518
  const adapters2 = getRegisteredAdapters(options.tools);
444
519
  logger.info("Pipeline started", { mode, toolCount: adapters2.length, parallelTools, toolTimeout });
445
520
  const globalDir = import_path3.default.join(import_os.default.homedir(), ".codacy");
@@ -512,20 +587,15 @@ async function analyze(options) {
512
587
  unavailable,
513
588
  checkedAt: (/* @__PURE__ */ new Date()).toISOString()
514
589
  };
515
- const codacyConfig = await readCodacyConfig(options.repositoryRoot);
516
- if (codacyConfig) {
517
- const readyBefore = capability.ready.length;
518
- const configuredIds = new Set(codacyConfig.tools.map((t) => t.toolId));
519
- capability.ready = capability.ready.filter((t) => configuredIds.has(t.toolId));
520
- capability.unavailable = capability.unavailable.filter((t) => configuredIds.has(t.toolId));
521
- logger.debug("Filtered by config", {
522
- readyBefore,
523
- readyAfter: capability.ready.length,
524
- configuredToolCount: configuredIds.size
525
- });
526
- } else {
527
- logger.debug("No codacy config found, running all available tools");
528
- }
590
+ const readyBefore = capability.ready.length;
591
+ const configuredIds = new Set(codacyConfig.tools.map((t) => t.toolId));
592
+ capability.ready = capability.ready.filter((t) => configuredIds.has(t.toolId));
593
+ capability.unavailable = capability.unavailable.filter((t) => configuredIds.has(t.toolId));
594
+ logger.debug("Filtered by config", {
595
+ readyBefore,
596
+ readyAfter: capability.ready.length,
597
+ configuredToolCount: configuredIds.size
598
+ });
529
599
  if (mode === "auto-install" && capability.unavailable.length > 0) {
530
600
  const installErrors = [];
531
601
  for (let i = capability.unavailable.length - 1; i >= 0; i--) {
@@ -650,7 +720,7 @@ async function analyze(options) {
650
720
  []
651
721
  );
652
722
  }
653
- const globalExclude = codacyConfig?.exclude || [];
723
+ const globalExclude = codacyConfig.exclude || [];
654
724
  let allFiles = listRepoFiles(options.repositoryRoot);
655
725
  logger.debug("File discovery", { totalFiles: allFiles.length });
656
726
  if (options.gitScope) {
@@ -675,7 +745,7 @@ async function analyze(options) {
675
745
  const toolRuns = [];
676
746
  for (const adapter of readyAdapters) {
677
747
  const toolConfig = getToolConfig(codacyConfig, adapter.id);
678
- if (codacyConfig && !toolConfig) continue;
748
+ if (!toolConfig) continue;
679
749
  const toolExclude = toolConfig?.exclude || [];
680
750
  const filesAfterExclusion = applyExclusions(allFiles, globalExclude, toolExclude);
681
751
  const toolFiles = routeFilesToTool(filesAfterExclusion, adapter, toolConfig);
@@ -683,19 +753,9 @@ async function analyze(options) {
683
753
  if (readyEntryForFiles) {
684
754
  readyEntryForFiles.filesRouted = toolFiles.length;
685
755
  }
686
- if (toolFiles.length === 0) {
687
- logger.debug("No files routed, skipping", { toolId: adapter.id });
688
- continue;
689
- }
690
- logger.debug("Files routed to tool", { toolId: adapter.id, fileCount: toolFiles.length });
691
- const ctx = makeToolContext(baseCtx, adapter, toolFiles);
692
- const configCheck = await adapter.checkLocalConfigurationFile(ctx);
756
+ const configCtx = makeToolContext(baseCtx, adapter, toolFiles);
757
+ const configCheck = await adapter.checkLocalConfigurationFile(configCtx);
693
758
  const codacyToolConfig = buildToolConfig(codacyConfig, adapter, configCheck);
694
- logger.debug("Tool config resolved", {
695
- toolId: adapter.id,
696
- configSource: codacyToolConfig.useLocalConfigurationFile ? "local" : "codacy",
697
- patternCount: codacyToolConfig.patterns?.length ?? 0
698
- });
699
759
  const readyEntry = capability.ready.find((r) => r.toolId === adapter.id);
700
760
  if (readyEntry) {
701
761
  if (configCheck.found && codacyToolConfig.useLocalConfigurationFile) {
@@ -705,7 +765,17 @@ async function analyze(options) {
705
765
  readyEntry.configSource = "codacy";
706
766
  }
707
767
  }
708
- toolRuns.push({ adapter, ctx, codacyToolConfig });
768
+ if (toolFiles.length === 0) {
769
+ logger.debug("No files routed, skipping", { toolId: adapter.id });
770
+ continue;
771
+ }
772
+ logger.debug("Files routed to tool", { toolId: adapter.id, fileCount: toolFiles.length });
773
+ logger.debug("Tool config resolved", {
774
+ toolId: adapter.id,
775
+ configSource: codacyToolConfig.useLocalConfigurationFile ? "local" : "codacy",
776
+ patternCount: codacyToolConfig.patterns?.length ?? 0
777
+ });
778
+ toolRuns.push({ adapter, ctx: configCtx, codacyToolConfig });
709
779
  }
710
780
  logger.info("Starting tool execution", {
711
781
  toolCount: toolRuns.length,
@@ -1135,7 +1205,7 @@ function colorSeverity(severity) {
1135
1205
  // src/init.ts
1136
1206
  var import_promises3 = __toESM(require("fs/promises"));
1137
1207
  var import_path6 = __toESM(require("path"));
1138
- var import_child_process2 = require("child_process");
1208
+ var import_child_process3 = require("child_process");
1139
1209
  var import_tooling = require("@codacy/tooling");
1140
1210
 
1141
1211
  // src/codacy-yaml.ts
@@ -4730,7 +4800,7 @@ async function listRepositoryToolPatterns(provider, org, repo, toolUuid) {
4730
4800
  async function detectLanguages(repositoryRoot) {
4731
4801
  let files = [];
4732
4802
  try {
4733
- const output = (0, import_child_process2.execSync)("git ls-files", {
4803
+ const output = (0, import_child_process3.execSync)("git ls-files", {
4734
4804
  cwd: repositoryRoot,
4735
4805
  encoding: "utf-8",
4736
4806
  maxBuffer: 50 * 1024 * 1024
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/analysis-runner",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "Core orchestration engine for Codacy analysis",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -12,11 +12,11 @@
12
12
  "cli-table3": "^0.6",
13
13
  "minimatch": "10.2.4",
14
14
  "yaml": "^2.6.0",
15
- "@codacy/tooling": "0.2.2"
15
+ "@codacy/tooling": "0.3.0"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@codacy/openapi-typescript-codegen": "0.0.9",
19
- "@codacy/tools-dummy-1": "0.2.2"
19
+ "@codacy/tools-dummy-1": "0.3.0"
20
20
  },
21
21
  "license": "MIT",
22
22
  "author": "Codacy <support@codacy.com> (https://www.codacy.com)",