@codacy/analysis-runner 0.16.0 → 0.17.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
@@ -586,7 +586,12 @@ interface InitAutoStats {
586
586
  *
587
587
  * Severity and category filters are ANDed across dimensions, ORed within.
588
588
  *
589
- * **Known limitation (v1):** When both TypeScript and JavaScript are detected,
589
+ * Tool-level overlap (two *different* tools that lint the same stack, e.g.
590
+ * ESLint and Biome) is resolved by `deduplicateToolFamilies` via each
591
+ * descriptor's `alternativeGroup` — only one member of a group is selected.
592
+ *
593
+ * **Known limitation (v1):** *Pattern*-level overlap within a single tool is
594
+ * not yet resolved — e.g. when both TypeScript and JavaScript are detected,
590
595
  * ESLint core rules and their `@typescript-eslint` equivalents may both be
591
596
  * enabled, potentially causing duplicate findings. This will be addressed in v2
592
597
  * via conflict-resolution metadata in the mapping files.
package/dist/index.js CHANGED
@@ -2320,6 +2320,7 @@ function updateConfigIncremental(base, current, next) {
2320
2320
 
2321
2321
  // src/init.ts
2322
2322
  var import_promises4 = __toESM(require("fs/promises"));
2323
+ var import_os3 = __toESM(require("os"));
2323
2324
  var import_path8 = __toESM(require("path"));
2324
2325
  var import_child_process4 = require("child_process");
2325
2326
  var import_tooling5 = require("@codacy/tooling");
@@ -7368,21 +7369,25 @@ async function initAutoConfig(repositoryRoot, adapters, descriptors, filters, on
7368
7369
  filters
7369
7370
  );
7370
7371
  if (selectedPatterns.length > 0) {
7371
- tools.push({
7372
+ const toolEntry = {
7372
7373
  toolId: adapter.id,
7373
7374
  patterns: selectedPatterns.map((p) => ({ patternId: p.id }))
7374
- });
7375
+ };
7376
+ tools.push(toolEntry);
7377
+ await applyAdapterParameterSuggestions(adapter, toolEntry, repositoryRoot, repoFiles);
7375
7378
  }
7376
7379
  }
7377
7380
  let selectedUnsupported = 0;
7378
- const selectedFamilies = new Set(tools.map((t) => toolFamily(t.toolId)));
7381
+ const selectedFamilies = new Set(
7382
+ tools.map((t) => toolGroupKey(t.toolId, descriptorMap.get(t.toolId)?.alternativeGroup))
7383
+ );
7379
7384
  for (const desc of descriptors) {
7380
7385
  if (!desc.unsupported) continue;
7381
7386
  if (!loadUnsupportedPatterns) break;
7382
7387
  if (!desc.languages.includes("*") && desc.languages.length > 0 && repoLanguages.size > 0 && !desc.languages.some((lang) => repoLanguages.has(lang))) {
7383
7388
  continue;
7384
7389
  }
7385
- const family = toolFamily(desc.id);
7390
+ const family = toolGroupKey(desc.id, desc.alternativeGroup);
7386
7391
  if (selectedFamilies.has(family)) continue;
7387
7392
  if (!hasMatchingFiles(repoFiles, desc.filePatterns)) continue;
7388
7393
  const patternsMetadata = loadUnsupportedPatterns(desc.id);
@@ -7426,16 +7431,58 @@ async function initAutoConfig(repositoryRoot, adapters, descriptors, filters, on
7426
7431
  }
7427
7432
  };
7428
7433
  }
7434
+ async function applyAdapterParameterSuggestions(adapter, toolEntry, repositoryRoot, repoFiles) {
7435
+ if (!adapter.suggestParameters) return;
7436
+ const logger = {
7437
+ debug() {
7438
+ },
7439
+ info() {
7440
+ },
7441
+ warn(message, fields) {
7442
+ console.error(`[init --auto] ${adapter.id}: ${message}`, fields ?? "");
7443
+ },
7444
+ error(message, fields) {
7445
+ console.error(`[init --auto] ${adapter.id}: ${message}`, fields ?? "");
7446
+ }
7447
+ };
7448
+ try {
7449
+ const globalDir = import_path8.default.join(import_os3.default.homedir(), ".codacy");
7450
+ const ctx = {
7451
+ repositoryRoot,
7452
+ generatedConfigDir: import_path8.default.join(repositoryRoot, ".codacy", "generated", adapter.id),
7453
+ globalDir,
7454
+ toolInstallDir: import_path8.default.join(globalDir, "tools", adapter.id),
7455
+ targetFiles: routeFilesToTool(repoFiles, adapter, toolEntry),
7456
+ platform: { os: process.platform, arch: process.arch },
7457
+ logger,
7458
+ runner: "local"
7459
+ };
7460
+ const suggestions = await adapter.suggestParameters(ctx);
7461
+ if (!suggestions) return;
7462
+ for (const pattern of toolEntry.patterns) {
7463
+ const params = suggestions[pattern.patternId];
7464
+ if (!params) continue;
7465
+ pattern.parameters = { ...pattern.parameters, ...params };
7466
+ }
7467
+ } catch (err) {
7468
+ logger.error("suggestParameters failed", {
7469
+ error: err instanceof Error ? err.message : String(err)
7470
+ });
7471
+ }
7472
+ }
7429
7473
  function toolFamily(id) {
7430
7474
  return id.replace(/\d+$/, "");
7431
7475
  }
7476
+ function toolGroupKey(id, alternativeGroup) {
7477
+ return alternativeGroup ?? toolFamily(id);
7478
+ }
7432
7479
  function deduplicateToolFamilies(candidates, localConfigs) {
7433
7480
  const families = /* @__PURE__ */ new Map();
7434
7481
  for (const adapter of candidates) {
7435
- const family = toolFamily(adapter.id);
7436
- const group = families.get(family) ?? [];
7482
+ const key = toolGroupKey(adapter.id, adapter.alternativeGroup);
7483
+ const group = families.get(key) ?? [];
7437
7484
  group.push(adapter);
7438
- families.set(family, group);
7485
+ families.set(key, group);
7439
7486
  }
7440
7487
  const result = [];
7441
7488
  for (const group of families.values()) {
@@ -7444,16 +7491,28 @@ function deduplicateToolFamilies(candidates, localConfigs) {
7444
7491
  continue;
7445
7492
  }
7446
7493
  const withConfig = group.filter((a) => localConfigs.has(a.id));
7447
- if (withConfig.length === 1) {
7448
- result.push(withConfig[0]);
7494
+ const pool = withConfig.length > 0 ? withConfig : group;
7495
+ if (pool.length === 1) {
7496
+ result.push(pool[0]);
7449
7497
  continue;
7450
7498
  }
7451
- group.sort((a, b) => {
7452
- const majorA = parseInt(a.preferredVersion.split(".")[0], 10) || 0;
7453
- const majorB = parseInt(b.preferredVersion.split(".")[0], 10) || 0;
7454
- return majorB - majorA;
7455
- });
7456
- result.push(group[0]);
7499
+ const preferred = pool.filter((a) => a.alternativeGroupDefault);
7500
+ if (preferred.length === 1) {
7501
+ result.push(preferred[0]);
7502
+ continue;
7503
+ }
7504
+ const defaultFamilies = new Set(
7505
+ group.filter((a) => a.alternativeGroupDefault).map((a) => toolFamily(a.id))
7506
+ );
7507
+ const defaultFamilyMembers = defaultFamilies.size === 1 ? pool.filter((a) => defaultFamilies.has(toolFamily(a.id))) : [];
7508
+ const ranked = [...defaultFamilyMembers.length > 0 ? defaultFamilyMembers : pool].sort(
7509
+ (a, b) => {
7510
+ const majorA = parseInt(a.preferredVersion.split(".")[0], 10) || 0;
7511
+ const majorB = parseInt(b.preferredVersion.split(".")[0], 10) || 0;
7512
+ return majorB - majorA;
7513
+ }
7514
+ );
7515
+ result.push(ranked[0]);
7457
7516
  }
7458
7517
  return result;
7459
7518
  }
@@ -7609,14 +7668,14 @@ var import_tooling6 = require("@codacy/tooling");
7609
7668
  // src/credentials.ts
7610
7669
  var import_crypto = __toESM(require("crypto"));
7611
7670
  var import_promises5 = __toESM(require("fs/promises"));
7612
- var import_os3 = __toESM(require("os"));
7671
+ var import_os4 = __toESM(require("os"));
7613
7672
  var import_path9 = __toESM(require("path"));
7614
7673
  function credentialsPath() {
7615
- return import_path9.default.join(import_os3.default.homedir(), ".codacy", "credentials");
7674
+ return import_path9.default.join(import_os4.default.homedir(), ".codacy", "credentials");
7616
7675
  }
7617
7676
  function deriveKey(salt) {
7618
- const info = import_os3.default.userInfo();
7619
- const machineKey = [import_os3.default.hostname(), info.username, import_os3.default.homedir(), import_os3.default.platform()].join("|");
7677
+ const info = import_os4.default.userInfo();
7678
+ const machineKey = [import_os4.default.hostname(), info.username, import_os4.default.homedir(), import_os4.default.platform()].join("|");
7620
7679
  return import_crypto.default.pbkdf2Sync(machineKey, salt, 1e5, 32, "sha512");
7621
7680
  }
7622
7681
  async function saveCredentials(token) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/analysis-runner",
3
- "version": "0.16.0",
3
+ "version": "0.17.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.16.0"
15
+ "@codacy/tooling": "0.17.0"
16
16
  },
17
17
  "devDependencies": {
18
18
  "@codacy/openapi-typescript-codegen": "0.0.9",
19
- "@codacy/tools-dummy-1": "0.16.0"
19
+ "@codacy/tools-dummy-1": "0.17.0"
20
20
  },
21
21
  "license": "MIT",
22
22
  "author": "Codacy <support@codacy.com> (https://www.codacy.com)",