@codacy/analysis-runner 0.1.1 → 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 +39 -1
- package/dist/index.js +111 -0
- package/package.json +3 -3
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(/^\.\//, ""));
|
|
@@ -551,6 +639,20 @@ async function analyze(options) {
|
|
|
551
639
|
const globalExclude = codacyConfig?.exclude || [];
|
|
552
640
|
let allFiles = listRepoFiles(options.repositoryRoot);
|
|
553
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
|
+
}
|
|
554
656
|
if (options.files && options.files.length > 0) {
|
|
555
657
|
allFiles = filterByTargetFiles(allFiles, options.files);
|
|
556
658
|
logger.debug("Filtered by target files", { afterFilter: allFiles.length });
|
|
@@ -641,6 +743,12 @@ function normalizeIssues(issues) {
|
|
|
641
743
|
return issue;
|
|
642
744
|
});
|
|
643
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
|
+
}
|
|
644
752
|
function buildResult(startedAt, repositoryRoot, mode, capability, issues, errors, toolResults) {
|
|
645
753
|
const completedAt = /* @__PURE__ */ new Date();
|
|
646
754
|
return {
|
|
@@ -4988,6 +5096,9 @@ function createLogger(options = {}) {
|
|
|
4988
5096
|
initDefaultConfig,
|
|
4989
5097
|
initLocalConfig,
|
|
4990
5098
|
initRemoteConfig,
|
|
5099
|
+
listDiffFiles,
|
|
5100
|
+
listPrFiles,
|
|
5101
|
+
listStagedFiles,
|
|
4991
5102
|
readCodacyConfig,
|
|
4992
5103
|
readCodacyYaml,
|
|
4993
5104
|
registerAdapter,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codacy/analysis-runner",
|
|
3
|
-
"version": "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.
|
|
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.
|
|
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)",
|