@codacy/analysis-runner 0.8.0 → 0.9.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 +89 -4
- package/dist/index.js +341 -30
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -46,12 +46,17 @@ interface AnalyzeOptions {
|
|
|
46
46
|
gitScope?: "staged" | {
|
|
47
47
|
diff: string | true;
|
|
48
48
|
} | "pr";
|
|
49
|
+
/** Custom path to the Codacy configuration file. Absolute, or relative to
|
|
50
|
+
* `repositoryRoot`. Defaults to `.codacy/codacy.config.json`. */
|
|
51
|
+
configFile?: string;
|
|
49
52
|
/** Logger for pipeline progress messages (install status, etc.). Defaults to no-op. */
|
|
50
53
|
logger?: Logger;
|
|
51
54
|
/** Called when a tool starts executing. */
|
|
52
55
|
onToolStart?: (toolId: string, displayName: string) => void;
|
|
53
56
|
/** Called when a tool finishes executing. */
|
|
54
57
|
onToolComplete?: (toolId: string, displayName: string, issueCount: number, durationMs: number) => void;
|
|
58
|
+
/** Called when a tool reports mid-execution progress (e.g. "Linting 50/200 files"). */
|
|
59
|
+
onToolProgress?: (toolId: string, displayName: string, message: string) => void;
|
|
55
60
|
}
|
|
56
61
|
/**
|
|
57
62
|
* Runs analysis on the given repository and returns the unified result.
|
|
@@ -148,14 +153,39 @@ declare function formatTextSummary(result: AnalysisResult, isInspect?: boolean):
|
|
|
148
153
|
* 3. Default (empty patterns, no local config)
|
|
149
154
|
*/
|
|
150
155
|
|
|
156
|
+
/**
|
|
157
|
+
* Resolves the absolute path to the Codacy configuration file.
|
|
158
|
+
*
|
|
159
|
+
* A custom `configFile` (absolute, or relative to `repositoryRoot`) overrides the
|
|
160
|
+
* default `.codacy/codacy.config.json` location. This lets callers keep one config
|
|
161
|
+
* (e.g. synced from Codacy Cloud) while testing a variant side-by-side.
|
|
162
|
+
*/
|
|
163
|
+
declare function resolveConfigPath(repositoryRoot: string, configFile?: string): string;
|
|
151
164
|
/**
|
|
152
165
|
* Reads a CodacyConfig from disk.
|
|
153
166
|
* Returns null if the file doesn't exist. Throws on parse/permission errors
|
|
154
167
|
* so callers can distinguish "no config" from "broken config".
|
|
168
|
+
*
|
|
169
|
+
* Pass `configFile` to read from a non-default location.
|
|
170
|
+
*/
|
|
171
|
+
declare function readCodacyConfig(repositoryRoot: string, configFile?: string): Promise<CodacyConfig | null>;
|
|
172
|
+
/**
|
|
173
|
+
* Writes a CodacyConfig to disk at the exact resolved path, creating only the
|
|
174
|
+
* parent directory. Unlike {@link writeCodacyConfig}, this has NO `.codacy/`
|
|
175
|
+
* side effects, so it is safe to write to an arbitrary location (e.g. a scratch
|
|
176
|
+
* config a user is experimenting with).
|
|
177
|
+
*
|
|
178
|
+
* Pass `configFile` to write to a non-default location.
|
|
179
|
+
*/
|
|
180
|
+
declare function writeCodacyConfigFile(repositoryRoot: string, config: CodacyConfig, configFile?: string): Promise<string>;
|
|
181
|
+
/**
|
|
182
|
+
* Writes a CodacyConfig to disk, creating the target directory if needed.
|
|
183
|
+
*
|
|
184
|
+
* Pass `configFile` to write to a non-default location. Regardless of where the
|
|
185
|
+
* main config lives, `.codacy/.gitignore` is always ensured so generated tool
|
|
186
|
+
* configs (which always land under `.codacy/generated/`) stay untracked.
|
|
155
187
|
*/
|
|
156
|
-
declare function
|
|
157
|
-
/** Writes a CodacyConfig to disk, creating the .codacy/ directory if needed. */
|
|
158
|
-
declare function writeCodacyConfig(repositoryRoot: string, config: CodacyConfig): Promise<string>;
|
|
188
|
+
declare function writeCodacyConfig(repositoryRoot: string, config: CodacyConfig, configFile?: string): Promise<string>;
|
|
159
189
|
/**
|
|
160
190
|
* Assembles a CodacyToolConfig from the global CodacyConfig and a local config check.
|
|
161
191
|
*
|
|
@@ -182,6 +212,61 @@ declare function createCodacyConfig(params?: {
|
|
|
182
212
|
autoFilters?: string;
|
|
183
213
|
}): CodacyConfig;
|
|
184
214
|
|
|
215
|
+
/**
|
|
216
|
+
* Set operations on Codacy configuration files.
|
|
217
|
+
*
|
|
218
|
+
* Three operations combine the *tools* and *patterns* of two CodacyConfigs:
|
|
219
|
+
* - `merge` — union of tools, and per-tool union of patterns
|
|
220
|
+
* - `intersect` — tools present in both, and per-tool patterns present in both
|
|
221
|
+
* - `diff` — `dest − source`: tools/patterns in dest that are NOT in source
|
|
222
|
+
*
|
|
223
|
+
* The result is always built from `dest` (its `version`, `metadata`, and
|
|
224
|
+
* top-level `exclude`/`includeFiles` are preserved; only `tools` and
|
|
225
|
+
* `metadata.updatedAt` change), because callers write the result back to the
|
|
226
|
+
* destination file. Inputs are never mutated.
|
|
227
|
+
*
|
|
228
|
+
* Rules that span the operations:
|
|
229
|
+
* - If either side uses a tool's native config file
|
|
230
|
+
* (`useLocalConfigurationFile === true`), the merged/intersected result for
|
|
231
|
+
* that tool also uses a config file (patterns dropped). The path comes from
|
|
232
|
+
* source when source uses the file, otherwise dest.
|
|
233
|
+
* - On `diff`, if the *destination* tool uses a config file and source also has
|
|
234
|
+
* that tool (with or without a config file), the tool is removed entirely — a
|
|
235
|
+
* config file's enabled rules are opaque, so it cannot be subtracted.
|
|
236
|
+
* - When a pattern exists on both sides during merge/intersect, its parameters
|
|
237
|
+
* are taken from source.
|
|
238
|
+
* - On `intersect`/`diff`, a tool left with no patterns and no config file is a
|
|
239
|
+
* no-op and is dropped from the result. `merge` always preserves its inputs.
|
|
240
|
+
*/
|
|
241
|
+
|
|
242
|
+
/** The set operation to apply between two configs. */
|
|
243
|
+
type ConfigOperation = "merge" | "intersect" | "diff";
|
|
244
|
+
/**
|
|
245
|
+
* Union of source and dest at the tool and pattern level.
|
|
246
|
+
* Tools present on only one side are carried over as-is; tools on both sides are
|
|
247
|
+
* combined (config-file rule, then per-tool pattern union with source parameters
|
|
248
|
+
* winning). Never drops tools.
|
|
249
|
+
*/
|
|
250
|
+
declare function mergeConfigs(source: CodacyConfig, dest: CodacyConfig): CodacyConfig;
|
|
251
|
+
/**
|
|
252
|
+
* Intersection of source and dest: only tools present in both, and per-tool only
|
|
253
|
+
* the patterns present in both (config-file rule applies when either side uses a
|
|
254
|
+
* config file). Tools left empty (no patterns, no config file) are dropped.
|
|
255
|
+
*/
|
|
256
|
+
declare function intersectConfigs(source: CodacyConfig, dest: CodacyConfig): CodacyConfig;
|
|
257
|
+
/**
|
|
258
|
+
* `dest − source`: keeps tools/patterns in dest that are not in source.
|
|
259
|
+
* - A tool only in dest is kept whole.
|
|
260
|
+
* - A dest tool that uses a config file and is also present in source is removed
|
|
261
|
+
* entirely (its enabled rules are opaque and cannot be subtracted).
|
|
262
|
+
* - Otherwise dest's inline patterns minus source's patterns are kept (a source
|
|
263
|
+
* tool using a config file enumerates no patterns, so all dest patterns survive).
|
|
264
|
+
* - Tools left empty after subtraction are dropped.
|
|
265
|
+
*/
|
|
266
|
+
declare function diffConfigs(source: CodacyConfig, dest: CodacyConfig): CodacyConfig;
|
|
267
|
+
/** Dispatches to the {@link mergeConfigs}, {@link intersectConfigs}, or {@link diffConfigs}. */
|
|
268
|
+
declare function applyConfigOperation(op: ConfigOperation, source: CodacyConfig, dest: CodacyConfig): CodacyConfig;
|
|
269
|
+
|
|
185
270
|
/**
|
|
186
271
|
* auto-filters.ts — Parses and applies --auto filter syntax.
|
|
187
272
|
*
|
|
@@ -588,4 +673,4 @@ interface DiscoverOptions {
|
|
|
588
673
|
*/
|
|
589
674
|
declare function discover(repositoryRoot: string, options?: DiscoverOptions): Promise<DiscoveryResult>;
|
|
590
675
|
|
|
591
|
-
export { type AdapterFactory, type AnalyzeOptions, type AutoFilters, type CategoryFilter, type CodacyYamlConfig, type CodacyYamlEngineConfig, type DiscoverOptions, type ExecutionMode, type IgnoredFilesResult, type InitAutoStats, type InitDefaultStats, type InitLocalStats, type InitRemoteStats, type LoggerOptions, type PatternMetadataLookup, type SeverityFilter, analyze, applyCodacyYamlExcludes, buildToolConfig, clearAdapters, computePatternSummary, configureApiToken, createCodacyConfig, createLogger, detectLanguages, discover, formatOutput, formatTextSummary, getAdapter, getRegisteredAdapters, getRegisteredDescriptors, initAutoConfig, initContainerConfig, initDefaultConfig, initLocalConfig, initRemoteConfig, listDiffFiles, listIgnoredFiles, listPrFiles, listStagedFiles, parseAutoFilters, readCodacyConfig, readCodacyYaml, registerAdapter, registerLazyAdapter, resolveEngineToAdapter, rotateLogFiles, validateApiToken, writeCodacyConfig };
|
|
676
|
+
export { type AdapterFactory, type AnalyzeOptions, type AutoFilters, type CategoryFilter, type CodacyYamlConfig, type CodacyYamlEngineConfig, type ConfigOperation, type DiscoverOptions, type ExecutionMode, type IgnoredFilesResult, type InitAutoStats, type InitDefaultStats, type InitLocalStats, type InitRemoteStats, type LoggerOptions, type PatternMetadataLookup, type SeverityFilter, analyze, applyCodacyYamlExcludes, applyConfigOperation, buildToolConfig, clearAdapters, computePatternSummary, configureApiToken, createCodacyConfig, createLogger, detectLanguages, diffConfigs, discover, formatOutput, formatTextSummary, getAdapter, getRegisteredAdapters, getRegisteredDescriptors, initAutoConfig, initContainerConfig, initDefaultConfig, initLocalConfig, initRemoteConfig, intersectConfigs, listDiffFiles, listIgnoredFiles, listPrFiles, listStagedFiles, mergeConfigs, parseAutoFilters, readCodacyConfig, readCodacyYaml, registerAdapter, registerLazyAdapter, resolveConfigPath, resolveEngineToAdapter, rotateLogFiles, validateApiToken, writeCodacyConfig, writeCodacyConfigFile };
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ var index_exports = {};
|
|
|
32
32
|
__export(index_exports, {
|
|
33
33
|
analyze: () => analyze,
|
|
34
34
|
applyCodacyYamlExcludes: () => applyCodacyYamlExcludes,
|
|
35
|
+
applyConfigOperation: () => applyConfigOperation,
|
|
35
36
|
buildToolConfig: () => buildToolConfig,
|
|
36
37
|
clearAdapters: () => clearAdapters,
|
|
37
38
|
computePatternSummary: () => computePatternSummary,
|
|
@@ -39,6 +40,7 @@ __export(index_exports, {
|
|
|
39
40
|
createCodacyConfig: () => createCodacyConfig,
|
|
40
41
|
createLogger: () => createLogger,
|
|
41
42
|
detectLanguages: () => detectLanguages,
|
|
43
|
+
diffConfigs: () => diffConfigs,
|
|
42
44
|
discover: () => discover,
|
|
43
45
|
formatOutput: () => formatOutput,
|
|
44
46
|
formatTextSummary: () => formatTextSummary,
|
|
@@ -50,19 +52,23 @@ __export(index_exports, {
|
|
|
50
52
|
initDefaultConfig: () => initDefaultConfig,
|
|
51
53
|
initLocalConfig: () => initLocalConfig,
|
|
52
54
|
initRemoteConfig: () => initRemoteConfig,
|
|
55
|
+
intersectConfigs: () => intersectConfigs,
|
|
53
56
|
listDiffFiles: () => listDiffFiles,
|
|
54
57
|
listIgnoredFiles: () => listIgnoredFiles,
|
|
55
58
|
listPrFiles: () => listPrFiles,
|
|
56
59
|
listStagedFiles: () => listStagedFiles,
|
|
60
|
+
mergeConfigs: () => mergeConfigs,
|
|
57
61
|
parseAutoFilters: () => parseAutoFilters,
|
|
58
62
|
readCodacyConfig: () => readCodacyConfig,
|
|
59
63
|
readCodacyYaml: () => readCodacyYaml,
|
|
60
64
|
registerAdapter: () => registerAdapter,
|
|
61
65
|
registerLazyAdapter: () => registerLazyAdapter,
|
|
66
|
+
resolveConfigPath: () => resolveConfigPath,
|
|
62
67
|
resolveEngineToAdapter: () => resolveEngineToAdapter,
|
|
63
68
|
rotateLogFiles: () => rotateLogFiles,
|
|
64
69
|
validateApiToken: () => validateApiToken,
|
|
65
|
-
writeCodacyConfig: () => writeCodacyConfig
|
|
70
|
+
writeCodacyConfig: () => writeCodacyConfig,
|
|
71
|
+
writeCodacyConfigFile: () => writeCodacyConfigFile
|
|
66
72
|
});
|
|
67
73
|
module.exports = __toCommonJS(index_exports);
|
|
68
74
|
|
|
@@ -127,8 +133,11 @@ var import_promises = __toESM(require("fs/promises"));
|
|
|
127
133
|
var import_path = __toESM(require("path"));
|
|
128
134
|
var CODACY_DIR = ".codacy";
|
|
129
135
|
var CONFIG_FILE = "codacy.config.json";
|
|
130
|
-
|
|
131
|
-
|
|
136
|
+
function resolveConfigPath(repositoryRoot, configFile) {
|
|
137
|
+
return configFile ? import_path.default.resolve(repositoryRoot, configFile) : import_path.default.join(repositoryRoot, CODACY_DIR, CONFIG_FILE);
|
|
138
|
+
}
|
|
139
|
+
async function readCodacyConfig(repositoryRoot, configFile) {
|
|
140
|
+
const configPath = resolveConfigPath(repositoryRoot, configFile);
|
|
132
141
|
let raw;
|
|
133
142
|
try {
|
|
134
143
|
raw = await import_promises.default.readFile(configPath, "utf-8");
|
|
@@ -154,13 +163,17 @@ function coerceParameterValues(config) {
|
|
|
154
163
|
}
|
|
155
164
|
}
|
|
156
165
|
}
|
|
157
|
-
async function
|
|
166
|
+
async function writeCodacyConfigFile(repositoryRoot, config, configFile) {
|
|
167
|
+
const configPath = resolveConfigPath(repositoryRoot, configFile);
|
|
168
|
+
await import_promises.default.mkdir(import_path.default.dirname(configPath), { recursive: true });
|
|
169
|
+
await import_promises.default.writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
170
|
+
return configPath;
|
|
171
|
+
}
|
|
172
|
+
async function writeCodacyConfig(repositoryRoot, config, configFile) {
|
|
158
173
|
const codacyDir = import_path.default.join(repositoryRoot, CODACY_DIR);
|
|
159
174
|
await import_promises.default.mkdir(codacyDir, { recursive: true });
|
|
160
175
|
await ensureGitignore(codacyDir);
|
|
161
|
-
|
|
162
|
-
await import_promises.default.writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
163
|
-
return configPath;
|
|
176
|
+
return writeCodacyConfigFile(repositoryRoot, config, configFile);
|
|
164
177
|
}
|
|
165
178
|
async function ensureGitignore(codacyDir) {
|
|
166
179
|
const gitignorePath = import_path.default.join(codacyDir, ".gitignore");
|
|
@@ -214,8 +227,10 @@ function createCodacyConfig(params = {}) {
|
|
|
214
227
|
|
|
215
228
|
// src/files.ts
|
|
216
229
|
var import_child_process = require("child_process");
|
|
230
|
+
var import_fs = __toESM(require("fs"));
|
|
217
231
|
var import_path2 = __toESM(require("path"));
|
|
218
232
|
var import_minimatch = require("minimatch");
|
|
233
|
+
var MAX_FILE_SIZE_BYTES = 5 * 1024 * 1024;
|
|
219
234
|
function listRepoFiles(repositoryRoot) {
|
|
220
235
|
try {
|
|
221
236
|
const tracked = (0, import_child_process.execSync)("git ls-files", {
|
|
@@ -240,6 +255,30 @@ function listRepoFiles(repositoryRoot) {
|
|
|
240
255
|
return [];
|
|
241
256
|
}
|
|
242
257
|
}
|
|
258
|
+
function filterOversizedFiles(files, repositoryRoot, logger) {
|
|
259
|
+
const result = [];
|
|
260
|
+
let skipped = 0;
|
|
261
|
+
for (const f of files) {
|
|
262
|
+
try {
|
|
263
|
+
const stat = import_fs.default.statSync(import_path2.default.join(repositoryRoot, f));
|
|
264
|
+
if (stat.size > MAX_FILE_SIZE_BYTES) {
|
|
265
|
+
skipped++;
|
|
266
|
+
logger?.debug("Skipping oversized file", {
|
|
267
|
+
file: f,
|
|
268
|
+
sizeKB: Math.round(stat.size / 1024),
|
|
269
|
+
limitKB: MAX_FILE_SIZE_BYTES / 1024
|
|
270
|
+
});
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
} catch {
|
|
274
|
+
}
|
|
275
|
+
result.push(f);
|
|
276
|
+
}
|
|
277
|
+
if (skipped > 0) {
|
|
278
|
+
logger?.info("Filtered oversized files", { skipped, remaining: result.length });
|
|
279
|
+
}
|
|
280
|
+
return result;
|
|
281
|
+
}
|
|
243
282
|
function applyExclusions(files, globalExclude, toolExclude) {
|
|
244
283
|
const allExclusions = [...globalExclude, ...toolExclude];
|
|
245
284
|
if (allExclusions.length === 0) return files;
|
|
@@ -431,6 +470,10 @@ async function runTool(adapter, ctx, codacyToolConfig, timeoutMs) {
|
|
|
431
470
|
async function runToolsSequential(tools, timeoutMs, callbacks) {
|
|
432
471
|
const results = [];
|
|
433
472
|
for (const { adapter, ctx, codacyToolConfig } of tools) {
|
|
473
|
+
if (callbacks?.onToolProgress) {
|
|
474
|
+
const cb = callbacks.onToolProgress;
|
|
475
|
+
ctx.onProgress = (message) => cb(adapter.id, adapter.displayName, message);
|
|
476
|
+
}
|
|
434
477
|
callbacks?.onToolStart?.(adapter.id, adapter.displayName);
|
|
435
478
|
const result = await runTool(adapter, ctx, codacyToolConfig, timeoutMs);
|
|
436
479
|
callbacks?.onToolComplete?.(
|
|
@@ -450,6 +493,10 @@ async function runToolsParallel(tools, timeoutMs, concurrency, callbacks) {
|
|
|
450
493
|
while (nextIndex < tools.length) {
|
|
451
494
|
const index = nextIndex++;
|
|
452
495
|
const { adapter, ctx, codacyToolConfig } = tools[index];
|
|
496
|
+
if (callbacks?.onToolProgress) {
|
|
497
|
+
const cb = callbacks.onToolProgress;
|
|
498
|
+
ctx.onProgress = (message) => cb(adapter.id, adapter.displayName, message);
|
|
499
|
+
}
|
|
453
500
|
callbacks?.onToolStart?.(adapter.id, adapter.displayName);
|
|
454
501
|
results[index] = await runTool(adapter, ctx, codacyToolConfig, timeoutMs);
|
|
455
502
|
callbacks?.onToolComplete?.(
|
|
@@ -593,6 +640,13 @@ async function analyze(options) {
|
|
|
593
640
|
const toolTimeout = options.toolTimeout || 6e5;
|
|
594
641
|
const parallelTools = options.parallelTools || 1;
|
|
595
642
|
const logger = options.logger ?? nullLogger;
|
|
643
|
+
const phaseTimings = {
|
|
644
|
+
availabilityMs: 0,
|
|
645
|
+
fileDiscoveryMs: 0,
|
|
646
|
+
fileRoutingMs: 0,
|
|
647
|
+
toolExecutionMs: 0,
|
|
648
|
+
installMs: 0
|
|
649
|
+
};
|
|
596
650
|
const emptyCapability = {
|
|
597
651
|
ready: [],
|
|
598
652
|
unavailable: [],
|
|
@@ -616,9 +670,10 @@ async function analyze(options) {
|
|
|
616
670
|
[]
|
|
617
671
|
);
|
|
618
672
|
}
|
|
673
|
+
const configLabel = options.configFile ?? ".codacy/codacy.config.json";
|
|
619
674
|
let codacyConfig;
|
|
620
675
|
try {
|
|
621
|
-
codacyConfig = await readCodacyConfig(options.repositoryRoot);
|
|
676
|
+
codacyConfig = await readCodacyConfig(options.repositoryRoot, options.configFile);
|
|
622
677
|
} catch (err) {
|
|
623
678
|
return buildResult(
|
|
624
679
|
startedAt,
|
|
@@ -631,7 +686,7 @@ async function analyze(options) {
|
|
|
631
686
|
toolId: "runner",
|
|
632
687
|
phase: "toolConfig",
|
|
633
688
|
kind: "InvalidConfig",
|
|
634
|
-
message:
|
|
689
|
+
message: `${configLabel} is invalid: ${err instanceof Error ? err.message : String(err)}`,
|
|
635
690
|
level: "error"
|
|
636
691
|
}
|
|
637
692
|
],
|
|
@@ -650,7 +705,7 @@ async function analyze(options) {
|
|
|
650
705
|
toolId: "runner",
|
|
651
706
|
phase: "toolConfig",
|
|
652
707
|
kind: "MissingConfig",
|
|
653
|
-
message:
|
|
708
|
+
message: `No ${configLabel} found. ` + (options.configFile ? `Run \`codacy-analysis init --config-file ${options.configFile}\` to initialize the repository.` : "Run `codacy-analysis init` to initialize the repository."),
|
|
654
709
|
level: "error"
|
|
655
710
|
}
|
|
656
711
|
],
|
|
@@ -671,6 +726,7 @@ async function analyze(options) {
|
|
|
671
726
|
const ready = [];
|
|
672
727
|
const unavailable = [];
|
|
673
728
|
const availabilityTimeout = 6e4;
|
|
729
|
+
const availabilityStartMs = Date.now();
|
|
674
730
|
for (const adapter of adapters) {
|
|
675
731
|
const ctx = makeToolContext(baseCtx, adapter, []);
|
|
676
732
|
const checkStart = Date.now();
|
|
@@ -729,6 +785,7 @@ async function analyze(options) {
|
|
|
729
785
|
});
|
|
730
786
|
}
|
|
731
787
|
}
|
|
788
|
+
phaseTimings.availabilityMs = Date.now() - availabilityStartMs;
|
|
732
789
|
const capability = {
|
|
733
790
|
ready,
|
|
734
791
|
unavailable,
|
|
@@ -744,6 +801,7 @@ async function analyze(options) {
|
|
|
744
801
|
configuredToolCount: configuredIds.size
|
|
745
802
|
});
|
|
746
803
|
if (mode === "auto-install" && capability.unavailable.length > 0) {
|
|
804
|
+
const installStartMs = Date.now();
|
|
747
805
|
const installErrors = [];
|
|
748
806
|
for (let i = capability.unavailable.length - 1; i >= 0; i--) {
|
|
749
807
|
const status = capability.unavailable[i];
|
|
@@ -807,6 +865,7 @@ async function analyze(options) {
|
|
|
807
865
|
});
|
|
808
866
|
}
|
|
809
867
|
}
|
|
868
|
+
phaseTimings.installMs = Date.now() - installStartMs;
|
|
810
869
|
if (installErrors.length > 0) {
|
|
811
870
|
return buildResult(
|
|
812
871
|
startedAt,
|
|
@@ -815,7 +874,9 @@ async function analyze(options) {
|
|
|
815
874
|
capability,
|
|
816
875
|
[],
|
|
817
876
|
installErrors,
|
|
818
|
-
[]
|
|
877
|
+
[],
|
|
878
|
+
void 0,
|
|
879
|
+
phaseTimings
|
|
819
880
|
);
|
|
820
881
|
}
|
|
821
882
|
}
|
|
@@ -867,6 +928,7 @@ async function analyze(options) {
|
|
|
867
928
|
[]
|
|
868
929
|
);
|
|
869
930
|
}
|
|
931
|
+
const fileDiscoveryStartMs = Date.now();
|
|
870
932
|
const globalExclude = codacyConfig.exclude || [];
|
|
871
933
|
let allFiles = listRepoFiles(options.repositoryRoot);
|
|
872
934
|
logger.debug("File discovery", { totalFiles: allFiles.length });
|
|
@@ -888,6 +950,9 @@ async function analyze(options) {
|
|
|
888
950
|
allFiles = filterByTargetFiles(allFiles, options.files);
|
|
889
951
|
logger.debug("Filtered by target files", { afterFilter: allFiles.length });
|
|
890
952
|
}
|
|
953
|
+
allFiles = filterOversizedFiles(allFiles, options.repositoryRoot, logger);
|
|
954
|
+
phaseTimings.fileDiscoveryMs = Date.now() - fileDiscoveryStartMs;
|
|
955
|
+
const fileRoutingStartMs = Date.now();
|
|
891
956
|
const readyAdapters = adapters.filter((a) => capability.ready.some((r) => r.toolId === a.id));
|
|
892
957
|
const toolRuns = [];
|
|
893
958
|
for (const adapter of readyAdapters) {
|
|
@@ -928,6 +993,8 @@ async function analyze(options) {
|
|
|
928
993
|
});
|
|
929
994
|
toolRuns.push({ adapter, ctx: configCtx, codacyToolConfig });
|
|
930
995
|
}
|
|
996
|
+
phaseTimings.fileRoutingMs = Date.now() - fileRoutingStartMs;
|
|
997
|
+
const toolExecStartMs = Date.now();
|
|
931
998
|
logger.info("Starting tool execution", {
|
|
932
999
|
toolCount: toolRuns.length,
|
|
933
1000
|
parallel: parallelTools > 1,
|
|
@@ -935,7 +1002,8 @@ async function analyze(options) {
|
|
|
935
1002
|
});
|
|
936
1003
|
const callbacks = {
|
|
937
1004
|
onToolStart: options.onToolStart,
|
|
938
|
-
onToolComplete: options.onToolComplete
|
|
1005
|
+
onToolComplete: options.onToolComplete,
|
|
1006
|
+
onToolProgress: options.onToolProgress
|
|
939
1007
|
};
|
|
940
1008
|
let results;
|
|
941
1009
|
if (parallelTools > 1 && toolRuns.length > 1) {
|
|
@@ -943,6 +1011,7 @@ async function analyze(options) {
|
|
|
943
1011
|
} else {
|
|
944
1012
|
results = await runToolsSequential(toolRuns, toolTimeout, callbacks);
|
|
945
1013
|
}
|
|
1014
|
+
phaseTimings.toolExecutionMs = Date.now() - toolExecStartMs;
|
|
946
1015
|
const allIssues = normalizeIssues(results.flatMap((r) => r.issues));
|
|
947
1016
|
const allErrors = results.flatMap((r) => r.errors);
|
|
948
1017
|
const allSummaries = results.map((r) => r.summary);
|
|
@@ -961,7 +1030,8 @@ async function analyze(options) {
|
|
|
961
1030
|
logger.info("Pipeline complete", {
|
|
962
1031
|
totalIssues: allIssues.length,
|
|
963
1032
|
totalErrors: allErrors.length,
|
|
964
|
-
durationMs: Date.now() - startedAt.getTime()
|
|
1033
|
+
durationMs: Date.now() - startedAt.getTime(),
|
|
1034
|
+
phaseTimings
|
|
965
1035
|
});
|
|
966
1036
|
return buildResult(
|
|
967
1037
|
startedAt,
|
|
@@ -971,7 +1041,8 @@ async function analyze(options) {
|
|
|
971
1041
|
allIssues,
|
|
972
1042
|
allErrors,
|
|
973
1043
|
allSummaries,
|
|
974
|
-
patternSummary
|
|
1044
|
+
patternSummary,
|
|
1045
|
+
phaseTimings
|
|
975
1046
|
);
|
|
976
1047
|
}
|
|
977
1048
|
function makeToolContext(base, adapter, targetFiles) {
|
|
@@ -997,7 +1068,7 @@ function resolveGitScope(repositoryRoot, scope) {
|
|
|
997
1068
|
const base = scope.diff === true ? void 0 : scope.diff;
|
|
998
1069
|
return listDiffFiles(repositoryRoot, base);
|
|
999
1070
|
}
|
|
1000
|
-
function buildResult(startedAt, repositoryRoot, mode, capability, issues, errors, toolResults, patternSummary) {
|
|
1071
|
+
function buildResult(startedAt, repositoryRoot, mode, capability, issues, errors, toolResults, patternSummary, phaseTimings) {
|
|
1001
1072
|
const completedAt = /* @__PURE__ */ new Date();
|
|
1002
1073
|
return {
|
|
1003
1074
|
metadata: {
|
|
@@ -1005,7 +1076,8 @@ function buildResult(startedAt, repositoryRoot, mode, capability, issues, errors
|
|
|
1005
1076
|
completedAt: completedAt.toISOString(),
|
|
1006
1077
|
durationMs: completedAt.getTime() - startedAt.getTime(),
|
|
1007
1078
|
repositoryRoot,
|
|
1008
|
-
executionMode: mode
|
|
1079
|
+
executionMode: mode,
|
|
1080
|
+
...phaseTimings ? { phaseTimings } : {}
|
|
1009
1081
|
},
|
|
1010
1082
|
capability,
|
|
1011
1083
|
issues,
|
|
@@ -1174,11 +1246,7 @@ function formatText(result) {
|
|
|
1174
1246
|
if (result.errors.length > 0) {
|
|
1175
1247
|
lines.push("");
|
|
1176
1248
|
lines.push("Errors:");
|
|
1177
|
-
|
|
1178
|
-
const prefix = `[${error.toolId}/${error.phase}]`;
|
|
1179
|
-
const location = error.filePath ? ` ${error.filePath}:` : "";
|
|
1180
|
-
lines.push(import_ansis.default.red(` ${prefix}${location} ${error.message}`));
|
|
1181
|
-
}
|
|
1249
|
+
lines.push(...formatErrorSection(result));
|
|
1182
1250
|
lines.push("");
|
|
1183
1251
|
}
|
|
1184
1252
|
lines.push(formatTextSummary(result, isInspect));
|
|
@@ -1277,6 +1345,33 @@ function formatTextSummary(result, isInspect) {
|
|
|
1277
1345
|
lines.push(table.toString());
|
|
1278
1346
|
}
|
|
1279
1347
|
}
|
|
1348
|
+
if (!inspect && result.metadata.phaseTimings) {
|
|
1349
|
+
const pt = result.metadata.phaseTimings;
|
|
1350
|
+
const totalMs = result.metadata.durationMs;
|
|
1351
|
+
const toolSumMs = pt.toolExecutionMs;
|
|
1352
|
+
const overheadMs = totalMs - toolSumMs;
|
|
1353
|
+
if (overheadMs > 2e3 && overheadMs / totalMs > 0.2) {
|
|
1354
|
+
lines.push("");
|
|
1355
|
+
lines.push(import_ansis.default.bold("Pipeline timing:"));
|
|
1356
|
+
const entries2 = [
|
|
1357
|
+
["Availability checks", pt.availabilityMs],
|
|
1358
|
+
["File discovery", pt.fileDiscoveryMs],
|
|
1359
|
+
["File routing & config", pt.fileRoutingMs]
|
|
1360
|
+
];
|
|
1361
|
+
if (pt.installMs > 0) {
|
|
1362
|
+
entries2.push(["Install", pt.installMs]);
|
|
1363
|
+
}
|
|
1364
|
+
entries2.push(["Tool execution", pt.toolExecutionMs]);
|
|
1365
|
+
const accounted = entries2.reduce((sum, [, ms]) => sum + ms, 0);
|
|
1366
|
+
const other = totalMs - accounted;
|
|
1367
|
+
if (other > 500) {
|
|
1368
|
+
entries2.push(["Other", other]);
|
|
1369
|
+
}
|
|
1370
|
+
for (const [label, ms] of entries2) {
|
|
1371
|
+
lines.push(` ${label.padEnd(22)} ${(0, import_tooling4.formatDuration)(ms)}`);
|
|
1372
|
+
}
|
|
1373
|
+
}
|
|
1374
|
+
}
|
|
1280
1375
|
const toolsWithHints = result.capability.unavailable.filter((t) => t.remediation);
|
|
1281
1376
|
if (toolsWithHints.length > 0) {
|
|
1282
1377
|
lines.push("");
|
|
@@ -1295,6 +1390,51 @@ function formatTextSummary(result, isInspect) {
|
|
|
1295
1390
|
}
|
|
1296
1391
|
return lines.join("\n");
|
|
1297
1392
|
}
|
|
1393
|
+
var MAX_ERRORS_PER_GROUP = 5;
|
|
1394
|
+
function formatErrorSection(result) {
|
|
1395
|
+
const lines = [];
|
|
1396
|
+
const displayNameMap = /* @__PURE__ */ new Map();
|
|
1397
|
+
for (const t of result.capability.ready) {
|
|
1398
|
+
displayNameMap.set(t.toolId, t.displayName ?? t.toolId);
|
|
1399
|
+
}
|
|
1400
|
+
for (const t of result.capability.unavailable) {
|
|
1401
|
+
displayNameMap.set(t.toolId, t.displayName ?? t.toolId);
|
|
1402
|
+
}
|
|
1403
|
+
const displayName = (toolId) => displayNameMap.get(toolId) ?? toolId;
|
|
1404
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1405
|
+
for (const error of result.errors) {
|
|
1406
|
+
const key = `${displayName(error.toolId)}/${error.phase}`;
|
|
1407
|
+
const list = groups.get(key) ?? [];
|
|
1408
|
+
list.push(error);
|
|
1409
|
+
groups.set(key, list);
|
|
1410
|
+
}
|
|
1411
|
+
for (const [groupKey, groupErrors] of groups) {
|
|
1412
|
+
const deduped = [];
|
|
1413
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1414
|
+
for (const err of groupErrors) {
|
|
1415
|
+
const dedupKey = `${err.filePath ?? ""}|||${err.message}`;
|
|
1416
|
+
const idx = seen.get(dedupKey);
|
|
1417
|
+
if (idx !== void 0) {
|
|
1418
|
+
deduped[idx].count++;
|
|
1419
|
+
} else {
|
|
1420
|
+
seen.set(dedupKey, deduped.length);
|
|
1421
|
+
deduped.push({ filePath: err.filePath, message: err.message, count: 1 });
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
const shown = deduped.slice(0, MAX_ERRORS_PER_GROUP);
|
|
1425
|
+
const overflowCount = deduped.length - shown.length;
|
|
1426
|
+
for (const entry of shown) {
|
|
1427
|
+
const prefix = `[${groupKey}]`;
|
|
1428
|
+
const location = entry.filePath ? ` ${entry.filePath}:` : "";
|
|
1429
|
+
const suffix = entry.count > 1 ? ` (x${entry.count})` : "";
|
|
1430
|
+
lines.push(import_ansis.default.red(` ${prefix}${location} ${entry.message}${suffix}`));
|
|
1431
|
+
}
|
|
1432
|
+
if (overflowCount > 0) {
|
|
1433
|
+
lines.push(import_ansis.default.dim(` ... and ${overflowCount} more ${groupKey} errors`));
|
|
1434
|
+
}
|
|
1435
|
+
}
|
|
1436
|
+
return lines;
|
|
1437
|
+
}
|
|
1298
1438
|
var MAX_LINE_LENGTH = 100;
|
|
1299
1439
|
var MAX_MULTILINE_DISPLAY = 10;
|
|
1300
1440
|
function formatMultilineIssue(output, issue) {
|
|
@@ -1437,6 +1577,171 @@ function formatPatternSummary(summary) {
|
|
|
1437
1577
|
return lines.join("\n");
|
|
1438
1578
|
}
|
|
1439
1579
|
|
|
1580
|
+
// src/config-ops.ts
|
|
1581
|
+
function usesConfigFile(tool) {
|
|
1582
|
+
return tool.useLocalConfigurationFile === true;
|
|
1583
|
+
}
|
|
1584
|
+
function isEmptyTool(tool) {
|
|
1585
|
+
return !usesConfigFile(tool) && tool.patterns.length === 0;
|
|
1586
|
+
}
|
|
1587
|
+
function indexByToolId(tools) {
|
|
1588
|
+
return new Map(tools.map((t) => [t.toolId, t]));
|
|
1589
|
+
}
|
|
1590
|
+
function indexByPatternId(patterns) {
|
|
1591
|
+
return new Map(patterns.map((p) => [p.patternId, p]));
|
|
1592
|
+
}
|
|
1593
|
+
function unionList(dest, source) {
|
|
1594
|
+
const result = [.../* @__PURE__ */ new Set([...dest ?? [], ...source ?? []])];
|
|
1595
|
+
return result.length > 0 ? result : void 0;
|
|
1596
|
+
}
|
|
1597
|
+
function intersectList(dest, source) {
|
|
1598
|
+
if (!dest || !source) return void 0;
|
|
1599
|
+
const sourceSet = new Set(source);
|
|
1600
|
+
const result = dest.filter((x) => sourceSet.has(x));
|
|
1601
|
+
return result.length > 0 ? result : void 0;
|
|
1602
|
+
}
|
|
1603
|
+
function clonePattern(pattern) {
|
|
1604
|
+
const result = { patternId: pattern.patternId };
|
|
1605
|
+
if (pattern.parameters !== void 0) result.parameters = { ...pattern.parameters };
|
|
1606
|
+
return result;
|
|
1607
|
+
}
|
|
1608
|
+
function cloneTool(tool) {
|
|
1609
|
+
return structuredClone(tool);
|
|
1610
|
+
}
|
|
1611
|
+
function applyToolLevelLists(tool, source, dest, listFn) {
|
|
1612
|
+
const exclude = listFn(dest.exclude, source.exclude);
|
|
1613
|
+
if (exclude) tool.exclude = exclude;
|
|
1614
|
+
const extraFilePatterns = listFn(dest.extraFilePatterns, source.extraFilePatterns);
|
|
1615
|
+
if (extraFilePatterns) tool.extraFilePatterns = extraFilePatterns;
|
|
1616
|
+
}
|
|
1617
|
+
function buildConfigFileTool(toolId, source, dest, listFn) {
|
|
1618
|
+
const localConfigurationFile = (usesConfigFile(source) ? source.localConfigurationFile : void 0) ?? dest.localConfigurationFile;
|
|
1619
|
+
const tool = {
|
|
1620
|
+
toolId,
|
|
1621
|
+
...localConfigurationFile !== void 0 ? { localConfigurationFile } : {},
|
|
1622
|
+
useLocalConfigurationFile: true,
|
|
1623
|
+
patterns: []
|
|
1624
|
+
};
|
|
1625
|
+
applyToolLevelLists(tool, source, dest, listFn);
|
|
1626
|
+
return tool;
|
|
1627
|
+
}
|
|
1628
|
+
function mergePatterns(source, dest) {
|
|
1629
|
+
const sourceMap = indexByPatternId(source);
|
|
1630
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1631
|
+
const result = [];
|
|
1632
|
+
for (const dp of dest) {
|
|
1633
|
+
const sp = sourceMap.get(dp.patternId);
|
|
1634
|
+
result.push(clonePattern(sp ?? dp));
|
|
1635
|
+
seen.add(dp.patternId);
|
|
1636
|
+
}
|
|
1637
|
+
for (const sp of source) {
|
|
1638
|
+
if (!seen.has(sp.patternId)) result.push(clonePattern(sp));
|
|
1639
|
+
}
|
|
1640
|
+
return result;
|
|
1641
|
+
}
|
|
1642
|
+
function intersectPatterns(source, dest) {
|
|
1643
|
+
const sourceMap = indexByPatternId(source);
|
|
1644
|
+
const result = [];
|
|
1645
|
+
for (const dp of dest) {
|
|
1646
|
+
const sp = sourceMap.get(dp.patternId);
|
|
1647
|
+
if (sp) result.push(clonePattern(sp));
|
|
1648
|
+
}
|
|
1649
|
+
return result;
|
|
1650
|
+
}
|
|
1651
|
+
function diffPatterns(source, dest) {
|
|
1652
|
+
const sourceIds = new Set(source.map((p) => p.patternId));
|
|
1653
|
+
return dest.filter((dp) => !sourceIds.has(dp.patternId)).map(clonePattern);
|
|
1654
|
+
}
|
|
1655
|
+
function combineTool(op, toolId, source, dest) {
|
|
1656
|
+
const listFn = op === "merge" ? unionList : intersectList;
|
|
1657
|
+
if (usesConfigFile(source) || usesConfigFile(dest)) {
|
|
1658
|
+
return buildConfigFileTool(toolId, source, dest, listFn);
|
|
1659
|
+
}
|
|
1660
|
+
const patterns = op === "merge" ? mergePatterns(source.patterns, dest.patterns) : intersectPatterns(source.patterns, dest.patterns);
|
|
1661
|
+
const tool = { toolId, patterns };
|
|
1662
|
+
if (dest.useLocalConfigurationFile !== void 0) {
|
|
1663
|
+
tool.useLocalConfigurationFile = dest.useLocalConfigurationFile;
|
|
1664
|
+
} else if (source.useLocalConfigurationFile !== void 0) {
|
|
1665
|
+
tool.useLocalConfigurationFile = source.useLocalConfigurationFile;
|
|
1666
|
+
}
|
|
1667
|
+
applyToolLevelLists(tool, source, dest, listFn);
|
|
1668
|
+
return tool;
|
|
1669
|
+
}
|
|
1670
|
+
function buildResultConfig(dest, tools) {
|
|
1671
|
+
const result = {
|
|
1672
|
+
version: dest.version,
|
|
1673
|
+
metadata: { ...structuredClone(dest.metadata), updatedAt: (/* @__PURE__ */ new Date()).toISOString() },
|
|
1674
|
+
tools
|
|
1675
|
+
};
|
|
1676
|
+
if (dest.exclude !== void 0) result.exclude = structuredClone(dest.exclude);
|
|
1677
|
+
if (dest.includeFiles !== void 0) result.includeFiles = structuredClone(dest.includeFiles);
|
|
1678
|
+
return result;
|
|
1679
|
+
}
|
|
1680
|
+
function mergeConfigs(source, dest) {
|
|
1681
|
+
const sourceMap = indexByToolId(source.tools);
|
|
1682
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1683
|
+
const tools = [];
|
|
1684
|
+
for (const d of dest.tools) {
|
|
1685
|
+
const s = sourceMap.get(d.toolId);
|
|
1686
|
+
tools.push(s ? combineTool("merge", d.toolId, s, d) : cloneTool(d));
|
|
1687
|
+
seen.add(d.toolId);
|
|
1688
|
+
}
|
|
1689
|
+
for (const s of source.tools) {
|
|
1690
|
+
if (!seen.has(s.toolId)) tools.push(cloneTool(s));
|
|
1691
|
+
}
|
|
1692
|
+
return buildResultConfig(dest, tools);
|
|
1693
|
+
}
|
|
1694
|
+
function intersectConfigs(source, dest) {
|
|
1695
|
+
const sourceMap = indexByToolId(source.tools);
|
|
1696
|
+
const tools = [];
|
|
1697
|
+
for (const d of dest.tools) {
|
|
1698
|
+
const s = sourceMap.get(d.toolId);
|
|
1699
|
+
if (!s) continue;
|
|
1700
|
+
const tool = combineTool("intersect", d.toolId, s, d);
|
|
1701
|
+
if (isEmptyTool(tool)) continue;
|
|
1702
|
+
tools.push(tool);
|
|
1703
|
+
}
|
|
1704
|
+
return buildResultConfig(dest, tools);
|
|
1705
|
+
}
|
|
1706
|
+
function diffConfigs(source, dest) {
|
|
1707
|
+
const sourceMap = indexByToolId(source.tools);
|
|
1708
|
+
const tools = [];
|
|
1709
|
+
for (const d of dest.tools) {
|
|
1710
|
+
const s = sourceMap.get(d.toolId);
|
|
1711
|
+
if (!s) {
|
|
1712
|
+
tools.push(cloneTool(d));
|
|
1713
|
+
continue;
|
|
1714
|
+
}
|
|
1715
|
+
if (usesConfigFile(d)) continue;
|
|
1716
|
+
const tool = {
|
|
1717
|
+
toolId: d.toolId,
|
|
1718
|
+
patterns: diffPatterns(s.patterns, d.patterns)
|
|
1719
|
+
};
|
|
1720
|
+
if (d.useLocalConfigurationFile !== void 0) {
|
|
1721
|
+
tool.useLocalConfigurationFile = d.useLocalConfigurationFile;
|
|
1722
|
+
}
|
|
1723
|
+
if (d.exclude !== void 0) tool.exclude = [...d.exclude];
|
|
1724
|
+
if (d.extraFilePatterns !== void 0) tool.extraFilePatterns = [...d.extraFilePatterns];
|
|
1725
|
+
if (isEmptyTool(tool)) continue;
|
|
1726
|
+
tools.push(tool);
|
|
1727
|
+
}
|
|
1728
|
+
return buildResultConfig(dest, tools);
|
|
1729
|
+
}
|
|
1730
|
+
function applyConfigOperation(op, source, dest) {
|
|
1731
|
+
switch (op) {
|
|
1732
|
+
case "merge":
|
|
1733
|
+
return mergeConfigs(source, dest);
|
|
1734
|
+
case "intersect":
|
|
1735
|
+
return intersectConfigs(source, dest);
|
|
1736
|
+
case "diff":
|
|
1737
|
+
return diffConfigs(source, dest);
|
|
1738
|
+
default: {
|
|
1739
|
+
const exhaustive = op;
|
|
1740
|
+
throw new Error(`Unknown config operation: ${String(exhaustive)}`);
|
|
1741
|
+
}
|
|
1742
|
+
}
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1440
1745
|
// src/init.ts
|
|
1441
1746
|
var import_promises4 = __toESM(require("fs/promises"));
|
|
1442
1747
|
var import_path7 = __toESM(require("path"));
|
|
@@ -6315,7 +6620,7 @@ function parseAutoFilters(raw) {
|
|
|
6315
6620
|
}
|
|
6316
6621
|
|
|
6317
6622
|
// src/logger.ts
|
|
6318
|
-
var
|
|
6623
|
+
var import_fs2 = __toESM(require("fs"));
|
|
6319
6624
|
var import_path8 = __toESM(require("path"));
|
|
6320
6625
|
var import_os2 = __toESM(require("os"));
|
|
6321
6626
|
var LEVEL_ORDER = {
|
|
@@ -6327,7 +6632,7 @@ var LEVEL_ORDER = {
|
|
|
6327
6632
|
function rotateLogFiles(logsDir, maxFiles) {
|
|
6328
6633
|
let entries2;
|
|
6329
6634
|
try {
|
|
6330
|
-
entries2 =
|
|
6635
|
+
entries2 = import_fs2.default.readdirSync(logsDir).filter((f) => f.startsWith("analysis-") && f.endsWith(".log"));
|
|
6331
6636
|
} catch {
|
|
6332
6637
|
return;
|
|
6333
6638
|
}
|
|
@@ -6336,7 +6641,7 @@ function rotateLogFiles(logsDir, maxFiles) {
|
|
|
6336
6641
|
const toRemove = entries2.slice(0, entries2.length - maxFiles);
|
|
6337
6642
|
for (const f of toRemove) {
|
|
6338
6643
|
try {
|
|
6339
|
-
|
|
6644
|
+
import_fs2.default.unlinkSync(import_path8.default.join(logsDir, f));
|
|
6340
6645
|
} catch {
|
|
6341
6646
|
}
|
|
6342
6647
|
}
|
|
@@ -6378,10 +6683,10 @@ function createLogger(options = {}) {
|
|
|
6378
6683
|
let logFd = null;
|
|
6379
6684
|
let bytesWritten = 0;
|
|
6380
6685
|
if (fileEnabled) {
|
|
6381
|
-
|
|
6686
|
+
import_fs2.default.mkdirSync(logsDir, { recursive: true });
|
|
6382
6687
|
rotateLogFiles(logsDir, maxFiles);
|
|
6383
6688
|
const logFilePath = import_path8.default.join(logsDir, `analysis-${fileTimestamp()}.log`);
|
|
6384
|
-
logFd =
|
|
6689
|
+
logFd = import_fs2.default.openSync(logFilePath, "a");
|
|
6385
6690
|
}
|
|
6386
6691
|
function log(level, message, fields) {
|
|
6387
6692
|
const numLevel = LEVEL_ORDER[level];
|
|
@@ -6394,13 +6699,13 @@ function createLogger(options = {}) {
|
|
|
6394
6699
|
...fields
|
|
6395
6700
|
});
|
|
6396
6701
|
const buf = Buffer.from(entry + "\n", "utf-8");
|
|
6397
|
-
|
|
6702
|
+
import_fs2.default.writeSync(logFd, buf);
|
|
6398
6703
|
bytesWritten += buf.length;
|
|
6399
6704
|
if (bytesWritten >= maxFileSize) {
|
|
6400
|
-
|
|
6705
|
+
import_fs2.default.closeSync(logFd);
|
|
6401
6706
|
rotateLogFiles(logsDir, maxFiles);
|
|
6402
6707
|
const newPath = import_path8.default.join(logsDir, `analysis-${fileTimestamp()}.log`);
|
|
6403
|
-
logFd =
|
|
6708
|
+
logFd = import_fs2.default.openSync(newPath, "a");
|
|
6404
6709
|
bytesWritten = 0;
|
|
6405
6710
|
}
|
|
6406
6711
|
}
|
|
@@ -6423,6 +6728,7 @@ function createLogger(options = {}) {
|
|
|
6423
6728
|
0 && (module.exports = {
|
|
6424
6729
|
analyze,
|
|
6425
6730
|
applyCodacyYamlExcludes,
|
|
6731
|
+
applyConfigOperation,
|
|
6426
6732
|
buildToolConfig,
|
|
6427
6733
|
clearAdapters,
|
|
6428
6734
|
computePatternSummary,
|
|
@@ -6430,6 +6736,7 @@ function createLogger(options = {}) {
|
|
|
6430
6736
|
createCodacyConfig,
|
|
6431
6737
|
createLogger,
|
|
6432
6738
|
detectLanguages,
|
|
6739
|
+
diffConfigs,
|
|
6433
6740
|
discover,
|
|
6434
6741
|
formatOutput,
|
|
6435
6742
|
formatTextSummary,
|
|
@@ -6441,17 +6748,21 @@ function createLogger(options = {}) {
|
|
|
6441
6748
|
initDefaultConfig,
|
|
6442
6749
|
initLocalConfig,
|
|
6443
6750
|
initRemoteConfig,
|
|
6751
|
+
intersectConfigs,
|
|
6444
6752
|
listDiffFiles,
|
|
6445
6753
|
listIgnoredFiles,
|
|
6446
6754
|
listPrFiles,
|
|
6447
6755
|
listStagedFiles,
|
|
6756
|
+
mergeConfigs,
|
|
6448
6757
|
parseAutoFilters,
|
|
6449
6758
|
readCodacyConfig,
|
|
6450
6759
|
readCodacyYaml,
|
|
6451
6760
|
registerAdapter,
|
|
6452
6761
|
registerLazyAdapter,
|
|
6762
|
+
resolveConfigPath,
|
|
6453
6763
|
resolveEngineToAdapter,
|
|
6454
6764
|
rotateLogFiles,
|
|
6455
6765
|
validateApiToken,
|
|
6456
|
-
writeCodacyConfig
|
|
6766
|
+
writeCodacyConfig,
|
|
6767
|
+
writeCodacyConfigFile
|
|
6457
6768
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codacy/analysis-runner",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.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.
|
|
15
|
+
"@codacy/tooling": "0.9.0"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@codacy/openapi-typescript-codegen": "0.0.9",
|
|
19
|
-
"@codacy/tools-dummy-1": "0.
|
|
19
|
+
"@codacy/tools-dummy-1": "0.9.0"
|
|
20
20
|
},
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"author": "Codacy <support@codacy.com> (https://www.codacy.com)",
|