@codacy/analysis-runner 0.1.0 → 0.2.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
@@ -34,6 +34,18 @@ interface AnalyzeOptions {
34
34
  /** Target execution environment. "local" = developer machine, "container" = Codacy Docker runner.
35
35
  * Phase 9 implements the actual container path; this field is accepted but currently ignored. */
36
36
  runner?: "local" | "container";
37
+ /**
38
+ * Git-aware file scope. Mutually exclusive options:
39
+ * - `"staged"` — analyze only files in the git staging area
40
+ * - `{ diff: string | true }` — analyze files changed vs a base ref (true = auto-detect)
41
+ * - `"pr"` — analyze files in the current pull request
42
+ *
43
+ * Resolved files are intersected with `files` if both are provided.
44
+ * If the resolved set is empty, analysis returns immediately with zero issues.
45
+ */
46
+ gitScope?: "staged" | {
47
+ diff: string | true;
48
+ } | "pr";
37
49
  /** Logger for pipeline progress messages (install status, etc.). Defaults to no-op. */
38
50
  logger?: Logger;
39
51
  /** Called when a tool starts executing. */
@@ -278,6 +290,32 @@ declare function resolveEngineToAdapter(engineName: string, adapters: Readonly<T
278
290
  */
279
291
  declare function applyCodacyYamlExcludes(config: CodacyConfig, yamlConfig: CodacyYamlConfig, adapters: Readonly<ToolAdapter>[], logger?: Logger): CodacyConfig;
280
292
 
293
+ /**
294
+ * File discovery and routing — finds files in a repository, applies exclusion
295
+ * layers (.gitignore, global exclude, per-tool exclude), and routes files to
296
+ * the appropriate tool adapters based on file patterns.
297
+ */
298
+
299
+ /**
300
+ * Returns files changed in the git staging area (index), excluding deleted files.
301
+ * Used by `--staged` to analyze only what's about to be committed.
302
+ */
303
+ declare function listStagedFiles(repositoryRoot: string): string[];
304
+ /**
305
+ * Returns files changed between a base ref and HEAD, excluding deleted files.
306
+ * Uses the three-dot diff (`base...HEAD`) to show only changes since divergence.
307
+ *
308
+ * If `base` is omitted, auto-detects the default branch via `detectDefaultBranch()`.
309
+ */
310
+ declare function listDiffFiles(repositoryRoot: string, base?: string): string[];
311
+ /**
312
+ * Returns files changed in the current pull request.
313
+ *
314
+ * Tries `gh pr view` first for accuracy (handles renames, squash merges).
315
+ * Falls back to git merge-base diff when gh is unavailable or not in a PR context.
316
+ */
317
+ declare function listPrFiles(repositoryRoot: string): string[];
318
+
281
319
  /**
282
320
  * Codacy API client — thin wrappers around the generated OpenAPI client.
283
321
  *
@@ -361,4 +399,4 @@ declare function rotateLogFiles(logsDir: string, maxFiles: number): void;
361
399
  */
362
400
  declare function createLogger(options?: LoggerOptions): Logger;
363
401
 
364
- export { type AnalyzeOptions, type CodacyYamlConfig, type CodacyYamlEngineConfig, type ExecutionMode, type InitDefaultStats, type InitLocalStats, type InitRemoteStats, type LoggerOptions, analyze, applyCodacyYamlExcludes, buildToolConfig, clearAdapters, configureApiToken, createCodacyConfig, createLogger, detectLanguages, formatOutput, formatTextSummary, getRegisteredAdapters, initContainerConfig, initDefaultConfig, initLocalConfig, initRemoteConfig, readCodacyConfig, readCodacyYaml, registerAdapter, resolveEngineToAdapter, rotateLogFiles, validateApiToken, writeCodacyConfig };
402
+ export { type AnalyzeOptions, type CodacyYamlConfig, type CodacyYamlEngineConfig, type ExecutionMode, type InitDefaultStats, type InitLocalStats, type InitRemoteStats, type LoggerOptions, analyze, applyCodacyYamlExcludes, buildToolConfig, clearAdapters, configureApiToken, createCodacyConfig, createLogger, detectLanguages, formatOutput, formatTextSummary, getRegisteredAdapters, initContainerConfig, initDefaultConfig, initLocalConfig, initRemoteConfig, listDiffFiles, listPrFiles, listStagedFiles, readCodacyConfig, readCodacyYaml, registerAdapter, resolveEngineToAdapter, rotateLogFiles, validateApiToken, writeCodacyConfig };
package/dist/index.js CHANGED
@@ -45,6 +45,9 @@ __export(index_exports, {
45
45
  initDefaultConfig: () => initDefaultConfig,
46
46
  initLocalConfig: () => initLocalConfig,
47
47
  initRemoteConfig: () => initRemoteConfig,
48
+ listDiffFiles: () => listDiffFiles,
49
+ listPrFiles: () => listPrFiles,
50
+ listStagedFiles: () => listStagedFiles,
48
51
  readCodacyConfig: () => readCodacyConfig,
49
52
  readCodacyYaml: () => readCodacyYaml,
50
53
  registerAdapter: () => registerAdapter,
@@ -207,6 +210,91 @@ function routeFilesToTool(files, adapter, toolConfig) {
207
210
  );
208
211
  });
209
212
  }
213
+ function listStagedFiles(repositoryRoot) {
214
+ try {
215
+ const output = (0, import_child_process.execSync)("git diff --cached --name-only --diff-filter=d", {
216
+ cwd: repositoryRoot,
217
+ encoding: "utf-8",
218
+ maxBuffer: 10 * 1024 * 1024
219
+ }).trim();
220
+ return output ? output.split("\n").filter(Boolean).sort() : [];
221
+ } catch {
222
+ throw new Error("Cannot list staged files: not inside a git repository");
223
+ }
224
+ }
225
+ function listDiffFiles(repositoryRoot, base) {
226
+ const baseBranch = base ?? detectDefaultBranch(repositoryRoot);
227
+ try {
228
+ const output = (0, import_child_process.execFileSync)(
229
+ "git",
230
+ ["diff", "--name-only", "--diff-filter=d", `${baseBranch}...HEAD`],
231
+ { cwd: repositoryRoot, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 }
232
+ ).trim();
233
+ return output ? output.split("\n").filter(Boolean).sort() : [];
234
+ } catch {
235
+ throw new Error(
236
+ `Cannot diff against "${baseBranch}": ref not found or not inside a git repository. Specify a base explicitly with --diff <base>.`
237
+ );
238
+ }
239
+ }
240
+ function listPrFiles(repositoryRoot) {
241
+ try {
242
+ const output = (0, import_child_process.execSync)("gh pr view --json files --jq '.files[].path'", {
243
+ cwd: repositoryRoot,
244
+ encoding: "utf-8",
245
+ maxBuffer: 10 * 1024 * 1024,
246
+ timeout: 15e3
247
+ }).trim();
248
+ if (output) {
249
+ return output.split("\n").filter(Boolean).sort();
250
+ }
251
+ } catch {
252
+ }
253
+ const baseBranch = detectDefaultBranch(repositoryRoot);
254
+ try {
255
+ const mergeBase = (0, import_child_process.execFileSync)("git", ["merge-base", "HEAD", baseBranch], {
256
+ cwd: repositoryRoot,
257
+ encoding: "utf-8"
258
+ }).trim();
259
+ const output = (0, import_child_process.execFileSync)(
260
+ "git",
261
+ ["diff", "--name-only", "--diff-filter=d", `${mergeBase}...HEAD`],
262
+ { cwd: repositoryRoot, encoding: "utf-8", maxBuffer: 10 * 1024 * 1024 }
263
+ ).trim();
264
+ return output ? output.split("\n").filter(Boolean).sort() : [];
265
+ } catch {
266
+ throw new Error(
267
+ `Cannot determine PR files: gh CLI unavailable and git merge-base with "${baseBranch}" failed. Use --diff <base> instead.`
268
+ );
269
+ }
270
+ }
271
+ function detectDefaultBranch(repositoryRoot) {
272
+ try {
273
+ const ref = (0, import_child_process.execSync)("git rev-parse --abbrev-ref origin/HEAD", {
274
+ cwd: repositoryRoot,
275
+ encoding: "utf-8",
276
+ stdio: ["pipe", "pipe", "pipe"]
277
+ }).trim();
278
+ if (ref && ref !== "origin/HEAD") {
279
+ return ref;
280
+ }
281
+ } catch {
282
+ }
283
+ for (const branch of ["origin/main", "origin/master"]) {
284
+ try {
285
+ (0, import_child_process.execFileSync)("git", ["rev-parse", "--verify", branch], {
286
+ cwd: repositoryRoot,
287
+ encoding: "utf-8",
288
+ stdio: ["pipe", "pipe", "pipe"]
289
+ });
290
+ return branch;
291
+ } catch {
292
+ }
293
+ }
294
+ throw new Error(
295
+ "Cannot auto-detect default branch: no origin/HEAD, origin/main, or origin/master found. Specify a base explicitly with --diff <base>."
296
+ );
297
+ }
210
298
  function filterByTargetFiles(allFiles, targetPatterns) {
211
299
  if (targetPatterns.length === 0) return allFiles;
212
300
  const normalized = targetPatterns.map((p) => p.replace(/^\.\//, ""));
@@ -225,16 +313,24 @@ function filterByTargetFiles(allFiles, targetPatterns) {
225
313
  // src/executor.ts
226
314
  async function runTool(adapter, ctx, codacyToolConfig, timeoutMs) {
227
315
  const startTime = Date.now();
228
- ctx.logger.debug("runTool started", { toolId: adapter.id, fileCount: ctx.targetFiles.length, timeoutMs });
316
+ ctx.logger.debug("runTool started", {
317
+ toolId: adapter.id,
318
+ fileCount: ctx.targetFiles.length,
319
+ timeoutMs
320
+ });
229
321
  try {
230
322
  const timeoutPromise = new Promise((_resolve, reject) => {
231
- setTimeout(() => reject(new Error(`TIMEOUT: Tool ${adapter.id} exceeded ${timeoutMs}ms`)), timeoutMs);
323
+ setTimeout(
324
+ () => reject(new Error(`TIMEOUT: Tool ${adapter.id} exceeded ${timeoutMs}ms`)),
325
+ timeoutMs
326
+ );
327
+ });
328
+ const result = await Promise.race([adapter.analyze(ctx, codacyToolConfig), timeoutPromise]);
329
+ ctx.logger.debug("runTool completed", {
330
+ toolId: adapter.id,
331
+ issueCount: result.summary.issueCount,
332
+ durationMs: result.summary.durationMs
232
333
  });
233
- const result = await Promise.race([
234
- adapter.analyze(ctx, codacyToolConfig),
235
- timeoutPromise
236
- ]);
237
- ctx.logger.debug("runTool completed", { toolId: adapter.id, issueCount: result.summary.issueCount, durationMs: result.summary.durationMs });
238
334
  return result;
239
335
  } catch (err) {
240
336
  const durationMs = Date.now() - startTime;
@@ -242,7 +338,11 @@ async function runTool(adapter, ctx, codacyToolConfig, timeoutMs) {
242
338
  if (isTimeout) {
243
339
  ctx.logger.error("Tool timed out", { toolId: adapter.id, timeoutMs, elapsedMs: durationMs });
244
340
  } else {
245
- ctx.logger.error("Tool execution failed", { toolId: adapter.id, error: err instanceof Error ? err.message : String(err), durationMs });
341
+ ctx.logger.error("Tool execution failed", {
342
+ toolId: adapter.id,
343
+ error: err instanceof Error ? err.message : String(err),
344
+ durationMs
345
+ });
246
346
  }
247
347
  const now = /* @__PURE__ */ new Date();
248
348
  return {
@@ -277,7 +377,12 @@ async function runToolsSequential(tools, timeoutMs, callbacks) {
277
377
  for (const { adapter, ctx, codacyToolConfig } of tools) {
278
378
  callbacks?.onToolStart?.(adapter.id, adapter.displayName);
279
379
  const result = await runTool(adapter, ctx, codacyToolConfig, timeoutMs);
280
- callbacks?.onToolComplete?.(adapter.id, adapter.displayName, result.summary.issueCount, result.summary.durationMs);
380
+ callbacks?.onToolComplete?.(
381
+ adapter.id,
382
+ adapter.displayName,
383
+ result.summary.issueCount,
384
+ result.summary.durationMs
385
+ );
281
386
  results.push(result);
282
387
  }
283
388
  return results;
@@ -291,7 +396,12 @@ async function runToolsParallel(tools, timeoutMs, concurrency, callbacks) {
291
396
  const { adapter, ctx, codacyToolConfig } = tools[index];
292
397
  callbacks?.onToolStart?.(adapter.id, adapter.displayName);
293
398
  results[index] = await runTool(adapter, ctx, codacyToolConfig, timeoutMs);
294
- callbacks?.onToolComplete?.(adapter.id, adapter.displayName, results[index].summary.issueCount, results[index].summary.durationMs);
399
+ callbacks?.onToolComplete?.(
400
+ adapter.id,
401
+ adapter.displayName,
402
+ results[index].summary.issueCount,
403
+ results[index].summary.durationMs
404
+ );
295
405
  }
296
406
  }
297
407
  const workers = Array.from({ length: Math.min(concurrency, tools.length) }, () => worker());
@@ -337,11 +447,19 @@ async function analyze(options) {
337
447
  const availability = await Promise.race([
338
448
  adapter.checkAvailability(ctx),
339
449
  new Promise(
340
- (_, reject) => setTimeout(() => reject(new Error(`checkAvailability timed out after ${availabilityTimeout}ms`)), availabilityTimeout)
450
+ (_, reject) => setTimeout(
451
+ () => reject(new Error(`checkAvailability timed out after ${availabilityTimeout}ms`)),
452
+ availabilityTimeout
453
+ )
341
454
  )
342
455
  ]);
343
456
  if (availability.available) {
344
- logger.debug("Tool available", { toolId: adapter.id, version: availability.version, installation: availability.installation, durationMs: Date.now() - checkStart });
457
+ logger.debug("Tool available", {
458
+ toolId: adapter.id,
459
+ version: availability.version,
460
+ installation: availability.installation,
461
+ durationMs: Date.now() - checkStart
462
+ });
345
463
  ready.push({
346
464
  toolId: adapter.id,
347
465
  displayName: adapter.displayName,
@@ -350,7 +468,11 @@ async function analyze(options) {
350
468
  runner: "local"
351
469
  });
352
470
  } else {
353
- logger.warn("Tool unavailable", { toolId: adapter.id, reason: availability.reason, durationMs: Date.now() - checkStart });
471
+ logger.warn("Tool unavailable", {
472
+ toolId: adapter.id,
473
+ reason: availability.reason,
474
+ durationMs: Date.now() - checkStart
475
+ });
354
476
  unavailable.push({
355
477
  toolId: adapter.id,
356
478
  displayName: adapter.displayName,
@@ -359,7 +481,11 @@ async function analyze(options) {
359
481
  });
360
482
  }
361
483
  } catch (err) {
362
- logger.warn("Availability check failed", { toolId: adapter.id, error: err instanceof Error ? err.message : String(err), durationMs: Date.now() - checkStart });
484
+ logger.warn("Availability check failed", {
485
+ toolId: adapter.id,
486
+ error: err instanceof Error ? err.message : String(err),
487
+ durationMs: Date.now() - checkStart
488
+ });
363
489
  unavailable.push({
364
490
  toolId: adapter.id,
365
491
  displayName: adapter.displayName,
@@ -378,7 +504,11 @@ async function analyze(options) {
378
504
  const configuredIds = new Set(codacyConfig.tools.map((t) => t.toolId));
379
505
  capability.ready = capability.ready.filter((t) => configuredIds.has(t.toolId));
380
506
  capability.unavailable = capability.unavailable.filter((t) => configuredIds.has(t.toolId));
381
- logger.debug("Filtered by config", { readyBefore, readyAfter: capability.ready.length, configuredToolCount: configuredIds.size });
507
+ logger.debug("Filtered by config", {
508
+ readyBefore,
509
+ readyAfter: capability.ready.length,
510
+ configuredToolCount: configuredIds.size
511
+ });
382
512
  } else {
383
513
  logger.debug("No codacy config found, running all available tools");
384
514
  }
@@ -407,7 +537,9 @@ async function analyze(options) {
407
537
  });
408
538
  capability.unavailable.splice(i, 1);
409
539
  } else {
410
- logger.error(`${adapter.displayName} post-install check failed: ${recheck.reason ?? "unknown"}`);
540
+ logger.error(
541
+ `${adapter.displayName} post-install check failed: ${recheck.reason ?? "unknown"}`
542
+ );
411
543
  installErrors.push({
412
544
  toolId: adapter.id,
413
545
  phase: "toolInstall",
@@ -445,7 +577,15 @@ async function analyze(options) {
445
577
  }
446
578
  }
447
579
  if (installErrors.length > 0) {
448
- return buildResult(startedAt, options.repositoryRoot, mode, capability, [], installErrors, []);
580
+ return buildResult(
581
+ startedAt,
582
+ options.repositoryRoot,
583
+ mode,
584
+ capability,
585
+ [],
586
+ installErrors,
587
+ []
588
+ );
449
589
  }
450
590
  }
451
591
  if (mode === "inspect") {
@@ -478,19 +618,41 @@ async function analyze(options) {
478
618
  }
479
619
  if (mode === "strict" && capability.unavailable.length > 0) {
480
620
  const missingTools = capability.unavailable.map((u) => u.toolId).join(", ");
481
- return buildResult(startedAt, options.repositoryRoot, mode, capability, [], [
482
- {
483
- toolId: "runner",
484
- phase: "requirementCheck",
485
- kind: "UnavailableTools",
486
- message: `Strict mode: the following tools are unavailable: ${missingTools}`,
487
- level: "error"
488
- }
489
- ], []);
621
+ return buildResult(
622
+ startedAt,
623
+ options.repositoryRoot,
624
+ mode,
625
+ capability,
626
+ [],
627
+ [
628
+ {
629
+ toolId: "runner",
630
+ phase: "requirementCheck",
631
+ kind: "UnavailableTools",
632
+ message: `Strict mode: the following tools are unavailable: ${missingTools}`,
633
+ level: "error"
634
+ }
635
+ ],
636
+ []
637
+ );
490
638
  }
491
639
  const globalExclude = codacyConfig?.exclude || [];
492
640
  let allFiles = listRepoFiles(options.repositoryRoot);
493
641
  logger.debug("File discovery", { totalFiles: allFiles.length });
642
+ if (options.gitScope) {
643
+ const scopeFiles = resolveGitScope(options.repositoryRoot, options.gitScope);
644
+ logger.debug("Git scope resolved", {
645
+ scope: typeof options.gitScope === "string" ? options.gitScope : "diff",
646
+ fileCount: scopeFiles.length
647
+ });
648
+ if (scopeFiles.length === 0) {
649
+ logger.info("Git scope resolved to zero files, skipping analysis");
650
+ return buildResult(startedAt, options.repositoryRoot, mode, capability, [], [], []);
651
+ }
652
+ const scopeSet = new Set(scopeFiles);
653
+ allFiles = allFiles.filter((f) => scopeSet.has(f));
654
+ logger.debug("After git scope intersection", { fileCount: allFiles.length });
655
+ }
494
656
  if (options.files && options.files.length > 0) {
495
657
  allFiles = filterByTargetFiles(allFiles, options.files);
496
658
  logger.debug("Filtered by target files", { afterFilter: allFiles.length });
@@ -515,7 +677,11 @@ async function analyze(options) {
515
677
  const ctx = makeToolContext(baseCtx, adapter, toolFiles);
516
678
  const configCheck = await adapter.checkLocalConfigurationFile(ctx);
517
679
  const codacyToolConfig = buildToolConfig(codacyConfig, adapter, configCheck);
518
- logger.debug("Tool config resolved", { toolId: adapter.id, configSource: codacyToolConfig.useLocalConfigurationFile ? "local" : "codacy", patternCount: codacyToolConfig.patterns?.length ?? 0 });
680
+ logger.debug("Tool config resolved", {
681
+ toolId: adapter.id,
682
+ configSource: codacyToolConfig.useLocalConfigurationFile ? "local" : "codacy",
683
+ patternCount: codacyToolConfig.patterns?.length ?? 0
684
+ });
519
685
  const readyEntry = capability.ready.find((r) => r.toolId === adapter.id);
520
686
  if (readyEntry) {
521
687
  if (configCheck.found && codacyToolConfig.useLocalConfigurationFile) {
@@ -527,7 +693,11 @@ async function analyze(options) {
527
693
  }
528
694
  toolRuns.push({ adapter, ctx, codacyToolConfig });
529
695
  }
530
- logger.info("Starting tool execution", { toolCount: toolRuns.length, parallel: parallelTools > 1, parallelTools });
696
+ logger.info("Starting tool execution", {
697
+ toolCount: toolRuns.length,
698
+ parallel: parallelTools > 1,
699
+ parallelTools
700
+ });
531
701
  const callbacks = {
532
702
  onToolStart: options.onToolStart,
533
703
  onToolComplete: options.onToolComplete
@@ -541,8 +711,20 @@ async function analyze(options) {
541
711
  const allIssues = normalizeIssues(results.flatMap((r) => r.issues));
542
712
  const allErrors = results.flatMap((r) => r.errors);
543
713
  const allSummaries = results.map((r) => r.summary);
544
- logger.info("Pipeline complete", { totalIssues: allIssues.length, totalErrors: allErrors.length, durationMs: Date.now() - startedAt.getTime() });
545
- return buildResult(startedAt, options.repositoryRoot, mode, capability, allIssues, allErrors, allSummaries);
714
+ logger.info("Pipeline complete", {
715
+ totalIssues: allIssues.length,
716
+ totalErrors: allErrors.length,
717
+ durationMs: Date.now() - startedAt.getTime()
718
+ });
719
+ return buildResult(
720
+ startedAt,
721
+ options.repositoryRoot,
722
+ mode,
723
+ capability,
724
+ allIssues,
725
+ allErrors,
726
+ allSummaries
727
+ );
546
728
  }
547
729
  function makeToolContext(base, adapter, targetFiles) {
548
730
  return {
@@ -561,6 +743,12 @@ function normalizeIssues(issues) {
561
743
  return issue;
562
744
  });
563
745
  }
746
+ function resolveGitScope(repositoryRoot, scope) {
747
+ if (scope === "staged") return listStagedFiles(repositoryRoot);
748
+ if (scope === "pr") return listPrFiles(repositoryRoot);
749
+ const base = scope.diff === true ? void 0 : scope.diff;
750
+ return listDiffFiles(repositoryRoot, base);
751
+ }
564
752
  function buildResult(startedAt, repositoryRoot, mode, capability, issues, errors, toolResults) {
565
753
  const completedAt = /* @__PURE__ */ new Date();
566
754
  return {
@@ -792,7 +980,14 @@ function formatTextSummary(result, isInspect) {
792
980
  ]);
793
981
  }
794
982
  for (const tool of unavailableTools) {
795
- table.push([import_ansis.default.dim.red(tool.displayName ?? tool.toolId), "-", "-", "-", "-", tool.reason]);
983
+ table.push([
984
+ import_ansis.default.dim.red(tool.displayName ?? tool.toolId),
985
+ "-",
986
+ "-",
987
+ "-",
988
+ "-",
989
+ tool.reason
990
+ ]);
796
991
  }
797
992
  lines.push(table.toString());
798
993
  } else {
@@ -4602,7 +4797,11 @@ async function initLocalConfigBase(repositoryRoot, adapters2) {
4602
4797
  }
4603
4798
  async function initLocalConfig(repositoryRoot, adapters2) {
4604
4799
  const baseConfig = await initLocalConfigBase(repositoryRoot, adapters2);
4605
- const { config, codacyYamlApplied } = await enrichWithCodacyYaml(baseConfig, repositoryRoot, adapters2);
4800
+ const { config, codacyYamlApplied } = await enrichWithCodacyYaml(
4801
+ baseConfig,
4802
+ repositoryRoot,
4803
+ adapters2
4804
+ );
4606
4805
  return { config, stats: { codacyYamlApplied } };
4607
4806
  }
4608
4807
  async function initDefaultConfig(repositoryRoot, adapters2) {
@@ -4618,7 +4817,7 @@ async function initDefaultConfig(repositoryRoot, adapters2) {
4618
4817
  for (const adapter of adapters2) {
4619
4818
  if (toolsWithLocalConfig.has(adapter.id)) continue;
4620
4819
  const apiTool = apiTools.find(
4621
- (t) => t.prefix ? t.prefix.replace(/_$/, "") === adapter.id : t.name === adapter.id
4820
+ (t) => t.prefix ? t.prefix.replace(/_$/, "") === adapter.id : t.shortName === adapter.id
4622
4821
  );
4623
4822
  if (!apiTool) continue;
4624
4823
  if (!apiTool.enabledByDefault) continue;
@@ -4641,8 +4840,16 @@ async function initDefaultConfig(repositoryRoot, adapters2) {
4641
4840
  addedTools++;
4642
4841
  }
4643
4842
  }
4644
- const baseConfig = createCodacyConfig({ source: "default", languages: base.metadata.languages, tools: updatedTools });
4645
- const { config, codacyYamlApplied } = await enrichWithCodacyYaml(baseConfig, repositoryRoot, adapters2);
4843
+ const baseConfig = createCodacyConfig({
4844
+ source: "default",
4845
+ languages: base.metadata.languages,
4846
+ tools: updatedTools
4847
+ });
4848
+ const { config, codacyYamlApplied } = await enrichWithCodacyYaml(
4849
+ baseConfig,
4850
+ repositoryRoot,
4851
+ adapters2
4852
+ );
4646
4853
  return { config, stats: { totalApiTools: apiTools.length, addedTools, codacyYamlApplied } };
4647
4854
  }
4648
4855
  async function initRemoteConfig(repositoryRoot, provider, organization, repositoryName, adapters2, apiToken, onRemoteToolsFound, onToolProcessed) {
@@ -4711,8 +4918,15 @@ async function initRemoteConfig(repositoryRoot, provider, organization, reposito
4711
4918
  repositoryId: repoInfo.repositoryId != null ? String(repoInfo.repositoryId) : void 0,
4712
4919
  repositoryName
4713
4920
  });
4714
- const { config, codacyYamlApplied } = await enrichWithCodacyYaml(baseConfig, repositoryRoot, adapters2);
4715
- return { config, stats: { totalRemoteTools: remoteTools.length, matchedAdapters, codacyYamlApplied } };
4921
+ const { config, codacyYamlApplied } = await enrichWithCodacyYaml(
4922
+ baseConfig,
4923
+ repositoryRoot,
4924
+ adapters2
4925
+ );
4926
+ return {
4927
+ config,
4928
+ stats: { totalRemoteTools: remoteTools.length, matchedAdapters, codacyYamlApplied }
4929
+ };
4716
4930
  }
4717
4931
  async function initContainerConfig(repositoryRoot, adapters2) {
4718
4932
  const codacyrcPath = import_path6.default.join(repositoryRoot, ".codacyrc");
@@ -4787,8 +5001,9 @@ function rotateLogFiles(logsDir, maxFiles) {
4787
5001
  }
4788
5002
  }
4789
5003
  }
5004
+ var fileSeq = 0;
4790
5005
  function fileTimestamp() {
4791
- return (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
5006
+ return `${(/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-")}-${fileSeq++}`;
4792
5007
  }
4793
5008
  function enrichMessage(message, fields) {
4794
5009
  if (!fields) return message;
@@ -4799,10 +5014,13 @@ function enrichMessage(message, fields) {
4799
5014
  if (fields.configSource) parts.push(String(fields.configSource));
4800
5015
  if (typeof fields.fileCount === "number") parts.push(`${fields.fileCount} files`);
4801
5016
  if (typeof fields.issueCount === "number") parts.push(`${fields.issueCount} issues`);
4802
- if (typeof fields.errorCount === "number" && fields.errorCount > 0) parts.push(`${fields.errorCount} errors`);
5017
+ if (typeof fields.errorCount === "number" && fields.errorCount > 0)
5018
+ parts.push(`${fields.errorCount} errors`);
4803
5019
  if (typeof fields.totalIssues === "number") parts.push(`${fields.totalIssues} issues`);
4804
- if (typeof fields.totalErrors === "number" && fields.totalErrors > 0) parts.push(`${fields.totalErrors} errors`);
4805
- if (typeof fields.durationMs === "number") parts.push(`${(fields.durationMs / 1e3).toFixed(1)}s`);
5020
+ if (typeof fields.totalErrors === "number" && fields.totalErrors > 0)
5021
+ parts.push(`${fields.totalErrors} errors`);
5022
+ if (typeof fields.durationMs === "number")
5023
+ parts.push(`${(fields.durationMs / 1e3).toFixed(1)}s`);
4806
5024
  if (fields.reason) parts.push(String(fields.reason));
4807
5025
  if (fields.error) parts.push(String(fields.error));
4808
5026
  if (typeof fields.found === "boolean") parts.push(fields.found ? "found" : "not found");
@@ -4878,6 +5096,9 @@ function createLogger(options = {}) {
4878
5096
  initDefaultConfig,
4879
5097
  initLocalConfig,
4880
5098
  initRemoteConfig,
5099
+ listDiffFiles,
5100
+ listPrFiles,
5101
+ listStagedFiles,
4881
5102
  readCodacyConfig,
4882
5103
  readCodacyYaml,
4883
5104
  registerAdapter,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/analysis-runner",
3
- "version": "0.1.0",
3
+ "version": "0.2.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.1.0"
15
+ "@codacy/tooling": "0.2.0"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@codacy/openapi-typescript-codegen": "0.0.9",
19
- "@codacy/tools-dummy-1": "0.1.0"
19
+ "@codacy/tools-dummy-1": "0.2.0"
20
20
  },
21
21
  "license": "MIT",
22
22
  "author": "Codacy <support@codacy.com> (https://www.codacy.com)",