@codacy/analysis-runner 0.23.1 → 0.25.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.
Files changed (3) hide show
  1. package/dist/index.d.ts +492 -12
  2. package/dist/index.js +1503 -256
  3. package/package.json +4 -4
package/dist/index.d.ts CHANGED
@@ -1,6 +1,222 @@
1
- import { OutputFormat, Logger, ProxyConfig, AnalysisResult, ToolAdapter, AdapterDescriptor, CodacyConfig, ConfigurationFileCheckResult, CodacyToolConfig, IssueSeverity, IssueCategory, Language, DiscoveryResult, PatternEntry, Issue, PatternSummary, LogLevel } from '@codacy/tooling';
1
+ import { AdapterDescriptor, ToolAdapter, CodacyConfig, CodacyToolConfig, Logger, OutputFormat, ProxyConfig, AnalysisResult, InstallationSource, AnalysisError, PatternEntry, ConfigurationFileCheckResult, IssueSeverity, IssueCategory, Language, DiscoveryResult, Issue, PatternSummary, LogLevel, ImageScanPkgType, ImageScanSeverity, SbomFormat } from '@codacy/tooling';
2
2
  export { AnalysisResult, OutputFormat, ProxyConfig, configureProxy, resolveProxyConfig } from '@codacy/tooling';
3
3
 
4
+ /**
5
+ * `.codacyrc` — the analysis configuration Codacy's cloud runners bind-mount
6
+ * into a tool container at `/`.
7
+ *
8
+ * This module owns the whole ingestion path, so the production entry point
9
+ * (`analyze --codacyrc`) and the debugging one (`init --container`) cannot drift
10
+ * apart. The wire format is the one the four engine seeds implement and
11
+ * `codacy-plugins-api` defines — **not** our own `codacy.config.json` shape,
12
+ * which is what the previous implementation mistakenly parsed:
13
+ *
14
+ * ```jsonc
15
+ * {
16
+ * "files": ["src/a.py"], // relative to /src
17
+ * "tools": [{
18
+ * "name": "ruff", // Codacy short-name, not our adapter id
19
+ * "patterns": [{
20
+ * "patternId": "S102_exec-builtin", // unprefixed
21
+ * "parameters": [{ "name": "threshold", "value": 10 }] // array, not a map
22
+ * }]
23
+ * }],
24
+ * "options": { }
25
+ * }
26
+ * ```
27
+ *
28
+ * See `docs/container-run.md` for how this was established and why each
29
+ * difference matters.
30
+ */
31
+
32
+ /** A pattern parameter as `.codacyrc` writes it: a named value, not a map entry. */
33
+ interface CodacyrcParameter {
34
+ name: string;
35
+ /** Any JSON scalar. `Parameter.Value` is an open trait in plugins-api. */
36
+ value: unknown;
37
+ }
38
+ /** One configured pattern. `parameters` absent means "the spec defaults". */
39
+ interface CodacyrcPattern {
40
+ patternId: string;
41
+ parameters?: CodacyrcParameter[];
42
+ }
43
+ /**
44
+ * One tool's configuration.
45
+ *
46
+ * `patterns` **absent** is not the same as `[]` in the seeds — absent means "use
47
+ * your own configuration file, or your defaults". We treat both as "no Codacy
48
+ * patterns", which leaves the tool running only if it finds its own native
49
+ * config file; see {@link resolveCodacyrc}.
50
+ */
51
+ interface CodacyrcTool {
52
+ name: string;
53
+ patterns?: CodacyrcPattern[];
54
+ }
55
+ /** The parsed `.codacyrc` document. */
56
+ interface Codacyrc {
57
+ /**
58
+ * Tri-state. Absent ⇒ discover normally; `[]` ⇒ analyze nothing; non-empty ⇒
59
+ * exactly these. Never collapse the first two — they are opposites.
60
+ */
61
+ files?: string[];
62
+ tools?: CodacyrcTool[];
63
+ /** Tool-level options. Parsed so an unknown key is never fatal; unused today. */
64
+ options?: Record<string, unknown>;
65
+ }
66
+ /** How {@link resolveCodacyrc} finds adapters. Injectable so tests need no registry. */
67
+ interface AdapterLookup {
68
+ descriptors: readonly AdapterDescriptor[];
69
+ load(toolId: string): Promise<Readonly<ToolAdapter> | undefined>;
70
+ }
71
+ /** The default lookup, over the process-wide adapter registry. */
72
+ declare function registryLookup(): AdapterLookup;
73
+ /** What {@link resolveCodacyrc} produced, and what it could not make sense of. */
74
+ interface CodacyrcResolution {
75
+ /** The in-memory config to hand to `analyze()`. Never written to disk. */
76
+ config: CodacyConfig;
77
+ /** Adapter ids configured from the file, in `.codacyrc` order. */
78
+ matchedToolIds: string[];
79
+ /** `tools[].name` values that named no local adapter (cloud-only, or unknown). */
80
+ unmatchedToolNames: string[];
81
+ /** Pattern ids the adapter's catalogue does not contain. Passed through anyway. */
82
+ unknownPatterns: Array<{
83
+ toolId: string;
84
+ patternId: string;
85
+ }>;
86
+ /** `options`, parsed and carried so a caller can log it. Not applied. */
87
+ options: Record<string, unknown>;
88
+ }
89
+ /**
90
+ * Parses `.codacyrc` content.
91
+ *
92
+ * Accepts base64-encoded JSON as a fallback. No seed documents this and Codacy
93
+ * does not send it, but the previous implementation accepted it and it costs
94
+ * nothing to keep; it is not a supported part of the contract.
95
+ *
96
+ * Throws on content that is neither — a malformed configuration must fail loudly
97
+ * rather than silently degrade to "analyze nothing", which is indistinguishable
98
+ * from a clean run.
99
+ */
100
+ declare function parseCodacyrc(raw: string, label?: string): Codacyrc;
101
+ /**
102
+ * Reads and parses a `.codacyrc`, or returns `null` when there is none.
103
+ *
104
+ * A missing file is not an error — every seed treats it as "no configuration
105
+ * supplied". Any other read failure (a directory, a permission problem) is
106
+ * rethrown, since it means the caller pointed us somewhere wrong.
107
+ */
108
+ declare function readCodacyrc(filePath: string): Promise<Codacyrc | null>;
109
+ /**
110
+ * Resolves a `.codacyrc` `tools[].name` to a registered adapter.
111
+ *
112
+ * Tries exact `shortName`, then case-insensitive `shortName`, then the same on
113
+ * the adapter id — the id fallback is what lets a hand-written debugging
114
+ * `.codacyrc` name `Ruff`, and what covers an adapter with no catalog entry at
115
+ * all (`dummy-1`).
116
+ *
117
+ * Deliberately **not** the registry's `resolveEntry`: that matches by
118
+ * case-insensitive *substring*, so `"pmd"` is ambiguous between `PMD` and `PMD7`
119
+ * and `"eslint-8"` matches nothing. Cloud-only descriptors are skipped — they
120
+ * have no analyzer, so resolving to one would configure a tool that can never run.
121
+ */
122
+ declare function resolveToolName(name: string, descriptors: readonly AdapterDescriptor[]): AdapterDescriptor | undefined;
123
+ /**
124
+ * Turns a parsed `.codacyrc` into the `CodacyConfig` `analyze()` consumes.
125
+ *
126
+ * ## What is configured
127
+ *
128
+ * **Only tools `.codacyrc` actually names.** There is no "run with your defaults"
129
+ * fallback: no `tools`, or no entry this container recognizes, means nothing is
130
+ * configured and nothing runs. A named tool with no patterns gets an entry with
131
+ * an empty pattern list, which `buildToolConfig` still pairs with the tool's own
132
+ * native config file if the repository has one — so "run with your own config"
133
+ * works, while "run with a pattern set we guessed" does not. That is a deliberate
134
+ * deviation from the seeds, chosen because the outcome is predictable rather than
135
+ * depending on which patterns our committed catalogue happens to mark `enabled`.
136
+ *
137
+ * `toolIds`, when given, restricts resolution to this container's own tool(s), so
138
+ * a `.codacyrc` listing several tools configures only the one this image is.
139
+ *
140
+ * ## What is translated
141
+ *
142
+ * Pattern ids come in unprefixed and go out in our vocabulary; parameters come in
143
+ * as `[{name, value}]` and go out as a string map, with the pattern's declared
144
+ * defaults filled in. An id the adapter's catalogue does not contain is **passed
145
+ * through and reported**, never dropped — `patterns.json` is a committed snapshot
146
+ * and a newer tool binary can legitimately know rules it does not.
147
+ */
148
+ declare function resolveCodacyrc(codacyrc: Codacyrc | null, opts?: {
149
+ toolIds?: string[];
150
+ lookup?: AdapterLookup;
151
+ logger?: Logger;
152
+ }): Promise<CodacyrcResolution>;
153
+ /**
154
+ * One tool's contribution to an emitted `.codacyrc`, as `analyze()` resolved it.
155
+ *
156
+ * Both halves come from the same point in the run — the routed file list and the
157
+ * tool config that was actually handed to the adapter — which is what makes the
158
+ * emitted file describe the run rather than re-derive it.
159
+ */
160
+ interface CodacyrcToolInput {
161
+ /** The adapter that ran. `shortName` becomes `tools[].name`; the catalogue re-types parameters. */
162
+ adapter: Pick<ToolAdapter, "id" | "shortName" | "patternsMetadata">;
163
+ /** The config `buildToolConfig` produced: our prefixed pattern ids, string parameters. */
164
+ toolConfig: CodacyToolConfig;
165
+ /** What `routeFilesToTool` handed this adapter, relative to the repository root. */
166
+ files: readonly string[];
167
+ }
168
+ /**
169
+ * Builds the `.codacyrc` describing a run — the inverse of {@link resolveCodacyrc}.
170
+ *
171
+ * Lives beside the parser so the two halves of one wire format cannot drift; a
172
+ * round-trip test pins `resolveCodacyrc(parse(serialize(build(x))))` against the
173
+ * config `x` came from.
174
+ *
175
+ * Three things are inverted, each mirroring something the ingestion path does:
176
+ *
177
+ * - `toolId` → `tools[].name`, via the adapter's Codacy short-name. Falls back to
178
+ * the adapter id (which {@link resolveToolName} also accepts) and warns, since
179
+ * a name the engine does not recognize makes it silently run nothing.
180
+ * - Our prefixed pattern ids → the engine's vocabulary, via `toEnginePatternId`.
181
+ * Conditional on the prefix, so the unprefixed tools (Brakeman, detekt, Reek,
182
+ * RuboCop) pass through rather than gaining one they have never heard of.
183
+ * - The `Record<string, string>` parameter map → `[{name, value}]` with the
184
+ * pattern's declared defaults filled in and JSON types restored. Defaults are
185
+ * written out explicitly on purpose: if our catalogue and the engine image's
186
+ * `docs/patterns.json` disagree about one, that shows up as a visible parameter
187
+ * instead of a silent behavioural difference.
188
+ *
189
+ * `files` is the **union** of the per-tool routed lists. `.codacyrc` has one file
190
+ * list shared by every entry in `tools[]`, so a multi-tool emit is a superset for
191
+ * each of them individually — every consumer, ours included, routes within it.
192
+ * Emit for a single tool when the list needs to be exact.
193
+ *
194
+ * A tool running from its own native config file emits `"patterns": []`, which the
195
+ * contract reads as "use your own configuration file" — and that is what actually
196
+ * happened, so it is what the file must say. `buildToolConfig` leaves the config's
197
+ * `patterns` array intact when it finds a native config (`config.ts`, which spreads
198
+ * `existing` and then sets `useLocalConfigurationFile`), while adapters ignore those
199
+ * patterns entirely in that case (`eslint-9/src/adapter.ts`: `if (usingLocalConfig)
200
+ * … else if (codacyConfig.patterns.length > 0)`). Emitting them anyway would
201
+ * describe a pattern set that did not drive the run, and an engine image — which
202
+ * sees the same bind-mounted config file but reads `.codacyrc` first — could then
203
+ * legitimately analyze against the patterns while we analyzed against the file.
204
+ * That is precisely the divergence this flag exists to rule out.
205
+ *
206
+ * Pure: no I/O, and `options` is not emitted, since nothing carries it through a
207
+ * run to reproduce.
208
+ */
209
+ declare function buildCodacyrc(tools: readonly CodacyrcToolInput[], opts?: {
210
+ logger?: Logger;
211
+ }): Codacyrc;
212
+ /**
213
+ * Serializes a `.codacyrc` for writing.
214
+ *
215
+ * Indented with a trailing newline: unlike the JSONL on stdout, this file is read
216
+ * by people and diffed, and it is what gets bind-mounted into an engine image.
217
+ */
218
+ declare function serializeCodacyrc(codacyrc: Codacyrc): string;
219
+
4
220
  /**
5
221
  * Main analysis entry point — orchestrates the full analysis pipeline.
6
222
  *
@@ -31,9 +247,27 @@ interface AnalyzeOptions {
31
247
  toolTimeout?: number;
32
248
  /** Maximum number of tools to run in parallel. 1 = sequential. Defaults to 1. */
33
249
  parallelTools?: number;
34
- /** Target execution environment. "local" = developer machine, "container" = Codacy Docker runner.
35
- * Phase 9 implements the actual container path; this field is accepted but currently ignored. */
250
+ /**
251
+ * Target execution environment. `"local"` = developer machine, `"container"` =
252
+ * Codacy Docker runner.
253
+ *
254
+ * Under `"container"` the runner refuses to install anything, keeps its
255
+ * generated tool configs out of the (read-only, bind-mounted) source directory,
256
+ * and skips managed-install repair — an image ships its tools pinned and must
257
+ * not reach the network mid-analysis.
258
+ */
36
259
  runner?: "local" | "container";
260
+ /**
261
+ * Pre-resolved configuration, used **instead of** reading one from disk. When
262
+ * set, `configFile` is ignored and nothing under `.codacy/` is read.
263
+ *
264
+ * This is how `analyze --codacyrc` runs without writing into the mounted source
265
+ * directory. The caller owns validation: unlike `readCodacyConfig`, no shape
266
+ * assertion, parameter coercion or `localConfigurationFile` resolution is
267
+ * applied — `resolveCodacyrc` already produces strings and absolute paths are
268
+ * filled in later by `buildToolConfig`.
269
+ */
270
+ config?: CodacyConfig;
37
271
  /**
38
272
  * Git-aware file scope. Mutually exclusive options:
39
273
  * - `"staged"` — analyze only files in the git staging area
@@ -66,6 +300,20 @@ interface AnalyzeOptions {
66
300
  onToolComplete?: (toolId: string, displayName: string, issueCount: number, durationMs: number) => void;
67
301
  /** Called when a tool reports mid-execution progress (e.g. "Linting 50/200 files"). */
68
302
  onToolProgress?: (toolId: string, displayName: string, message: string) => void;
303
+ /**
304
+ * Called once with the `.codacyrc` describing this run — after file routing and
305
+ * pattern resolution, before any tool executes.
306
+ *
307
+ * A callback rather than a path so the runner performs no write of its own: a
308
+ * container run must not touch the bind-mounted `/src`, and where the file goes
309
+ * is the caller's policy. Awaited, and a throw propagates: nothing has run yet,
310
+ * so failing loudly is cheaper than handing back a file that silently was not
311
+ * written.
312
+ *
313
+ * Not called when the run returns before routing (`inspect` mode, an unavailable
314
+ * tool under `strict`, a fatal config error) or when no tool has anything to run.
315
+ */
316
+ onCodacyrc?: (codacyrc: Codacyrc) => void | Promise<void>;
69
317
  /**
70
318
  * Optional proxy/TLS configuration for outbound HTTP (API calls and tool
71
319
  * downloads). When provided, it is applied via `configureProxy` at the start of
@@ -82,6 +330,65 @@ interface AnalyzeOptions {
82
330
  */
83
331
  declare function analyze(options: AnalyzeOptions): Promise<AnalysisResult>;
84
332
 
333
+ /**
334
+ * Installs tools without analysing anything — the library half of the
335
+ * `install` command.
336
+ *
337
+ * Its main consumer is an image build: the per-tool container contract runs
338
+ * with no network, so an image must carry its tools ahead of time, and running
339
+ * the very install `analyze --install-dependencies` would have run writes them
340
+ * to the same managed layout the analysis later resolves from. Reusing
341
+ * {@link installMissingTool} keeps the failure shapes identical to `analyze`.
342
+ */
343
+
344
+ /** Options for {@link installTools}. */
345
+ interface InstallToolsOptions {
346
+ /** Tool IDs (fuzzy-matched like `analyze --tool`). Ignored when `all` is set. */
347
+ tools?: string[];
348
+ /** Install every registered tool that has a local analyzer and supports this platform. */
349
+ all?: boolean;
350
+ logger?: Logger;
351
+ /** Progress callback forwarded to each adapter's install. */
352
+ onProgress?: (message: string) => void;
353
+ }
354
+ /** What happened to one tool. */
355
+ type ToolInstallStatus =
356
+ /** Already usable; nothing was installed. */
357
+ "present"
358
+ /** Installed and verified. */
359
+ | "installed"
360
+ /** The tool cannot self-install (e.g. a system package the user must provide). */
361
+ | "notSupported"
362
+ /** The tool does not run on this OS/architecture. */
363
+ | "unsupportedPlatform"
364
+ /** Install or verification failed. */
365
+ | "failed";
366
+ /** Per-tool outcome of {@link installTools}. */
367
+ interface ToolInstallReport {
368
+ toolId: string;
369
+ displayName: string;
370
+ status: ToolInstallStatus;
371
+ version?: string;
372
+ installation?: InstallationSource;
373
+ /** Failure or skip explanation. */
374
+ message?: string;
375
+ }
376
+ /** Result of {@link installTools}. */
377
+ interface InstallToolsResult {
378
+ tools: ToolInstallReport[];
379
+ /** Requested IDs that matched no registered local tool. */
380
+ unknown: string[];
381
+ }
382
+ /**
383
+ * Makes each selected tool available, installing it into the managed layout
384
+ * when `checkAvailability` says it is missing. Always runs with a `local`
385
+ * runner context: installing is exactly what container mode forbids, and an
386
+ * image build is not a container *run*. Sequential, like every other install
387
+ * path, because installs mutate `~/.codacy`. Never throws for a tool failure —
388
+ * each one is reported in the result.
389
+ */
390
+ declare function installTools(options: InstallToolsOptions): Promise<InstallToolsResult>;
391
+
85
392
  /**
86
393
  * Tool adapter registry — stores adapters for discovery by the runner.
87
394
  *
@@ -165,6 +472,25 @@ declare function clearAdapters(): void;
165
472
  * This function never throws — format errors are returned as descriptive strings.
166
473
  */
167
474
  declare function formatOutput(result: AnalysisResult, format: OutputFormat): string;
475
+ /**
476
+ * Splits errors into the ones `container` output can carry and the ones it
477
+ * cannot.
478
+ *
479
+ * `fileErrors` are the errors that mean *this file was not analysed*
480
+ * ({@link AnalysisError.fileNotAnalyzed}) — the only ones that may become a
481
+ * `FileError` line. Presence of a `filePath` alone is deliberately not enough:
482
+ * markdownlint and stylelint attach one to a finding whose rule they could not
483
+ * name, and promoting those would tell Codacy a perfectly healthy file is
484
+ * unanalysed, discarding the findings we did report for it.
485
+ *
486
+ * `otherErrors` have nowhere to go in this format. The CLI logs them to stderr;
487
+ * dropping them silently is what this split exists to prevent. Exported because
488
+ * `formatOutput` is pure and has no logger.
489
+ */
490
+ declare function partitionContainerErrors(errors: readonly AnalysisError[]): {
491
+ fileErrors: AnalysisError[];
492
+ otherErrors: AnalysisError[];
493
+ };
168
494
  /**
169
495
  * Builds the summary portion of the text output: header line, tools table,
170
496
  * and install hints. Exported separately so the CLI can print it to stdout
@@ -172,6 +498,78 @@ declare function formatOutput(result: AnalysisResult, format: OutputFormat): str
172
498
  */
173
499
  declare function formatTextSummary(result: AnalysisResult, isInspect?: boolean): string;
174
500
 
501
+ /**
502
+ * Pattern-ID translation between our vocabulary and the Codacy engine's.
503
+ *
504
+ * Codacy's cloud runners speak the vocabulary of the per-tool Docker images:
505
+ * `docs/patterns.json` inside a container lists **unprefixed** rule ids
506
+ * (`S102_exec-builtin`). Our own `patterns.json` files come from the v3 API,
507
+ * which returns them **tool-prefixed** (`Ruff_S102_exec-builtin`). The two
508
+ * container seams — `.codacyrc` ingestion and `container` output — are the only
509
+ * places that translation happens; adapters keep speaking prefixed ids and
510
+ * nothing else in the CLI changes.
511
+ *
512
+ * Both directions live here so they cannot drift apart.
513
+ *
514
+ * ## Not every tool is prefixed
515
+ *
516
+ * A tool with no `prefix` in the Codacy API (detekt, Reek, Brakeman, RuboCop)
517
+ * ships **bare** rule ids in our `patterns.json` too — `Attribute`, not
518
+ * `Reek_Attribute`. So translation is conditional, never a blind strip or
519
+ * prepend. Verified across all 33 committed catalogues (17 871 patterns):
520
+ * adoption is all-or-nothing per tool — 29 fully prefixed, 4 fully unprefixed,
521
+ * none mixed, and no unprefixed id starts with its own tool id even
522
+ * case-insensitively. `packages/runner/test/pattern-id.test.ts` pins that
523
+ * invariant, which is what licenses the cheap `startsWith` test below.
524
+ */
525
+
526
+ /**
527
+ * Our prefixed pattern id → the engine's unprefixed one.
528
+ *
529
+ * Needs no data beyond the tool id, which every `Issue` already carries, so the
530
+ * `container` formatter can translate without loading any adapter.
531
+ *
532
+ * Strips **exactly once**: `Checkov_Checkov_FOO` → `Checkov_FOO`, because the
533
+ * trailing half is a real rule name. Never use a global regex, `replaceAll`, or
534
+ * a loop here.
535
+ */
536
+ declare function toEnginePatternId(patternId: string, toolId: string): string;
537
+ /** Translates the engine's pattern ids into ours for one tool. */
538
+ interface PatternIdTranslator {
539
+ readonly toolId: string;
540
+ /**
541
+ * The engine's id → ours. Always answers: an id the catalogue does not contain
542
+ * is translated by the tool's own naming convention rather than rejected, so
543
+ * catalog lag cannot turn into lost findings. Use {@link isKnown} to decide
544
+ * whether that is worth reporting.
545
+ */
546
+ toInternal(enginePatternId: string): string;
547
+ /**
548
+ * Whether the catalogue actually contains this id. Always `true` when the
549
+ * adapter ships no catalogue — with nothing to check against, an unmatched id
550
+ * is not evidence of anything.
551
+ */
552
+ isKnown(enginePatternId: string): boolean;
553
+ /** Whether this tool ships a pattern catalogue at all. */
554
+ readonly hasCatalogue: boolean;
555
+ }
556
+ /**
557
+ * Builds the engine → ours direction for one tool.
558
+ *
559
+ * Driven by the adapter's own `patternsMetadata` when it has one: that is a
560
+ * lookup table rather than a guess, so it is exact for prefixed and unprefixed
561
+ * tools alike, and it also accepts an id already written in our vocabulary — a
562
+ * hand-written debugging `.codacyrc` carrying `Ruff_S102_exec-builtin` still
563
+ * resolves.
564
+ *
565
+ * For an id the catalogue lacks — and for adapters with no catalogue at all, like
566
+ * the `dummy-1` reference tool — it falls back to the tool's observed convention:
567
+ * prepend `{toolId}_` only if the tool's own patterns are prefixed. Prepending
568
+ * for an unprefixed tool would invent `Reek_Attribute`, a pattern Reek has never
569
+ * heard of.
570
+ */
571
+ declare function buildPatternTranslator(toolId: string, patternsMetadata?: readonly PatternEntry[]): PatternIdTranslator;
572
+
175
573
  /**
176
574
  * Configuration resolution — manages the .codacy/ directory structure and
177
575
  * assembles per-tool CodacyToolConfig from config + local config checks.
@@ -653,16 +1051,18 @@ declare function initRemoteConfig(repositoryRoot: string, provider: string, orga
653
1051
  stats: InitRemoteStats;
654
1052
  }>;
655
1053
  /**
656
- * `--container` mode.
657
- * Reads `.codacyrc` from the repository root (the container run input file).
658
- * Parses the `files` list into `includeFiles` and maps `tools` entries to adapters.
1054
+ * `--container` mode — the debugging counterpart of `analyze --codacyrc`.
659
1055
  *
660
- * `.codacyrc` format (from codacy-engine-typescript-seed):
661
- * ```json
662
- * { "tools": [...], "files": ["src/main.rs", "src/lib.rs"], "options": {...} }
663
- * ```
1056
+ * Materializes the configuration a container *would* run with, so it can be
1057
+ * inspected before analysis. The production path never calls this: it builds the
1058
+ * same config in memory and never writes into the mounted source directory.
1059
+ *
1060
+ * Both go through {@link resolveCodacyrc}, so the two cannot drift apart.
1061
+ *
1062
+ * A missing `.codacyrc` yields a config with no tools rather than an error —
1063
+ * every seed treats an absent file as "no configuration supplied".
664
1064
  */
665
- declare function initContainerConfig(repositoryRoot: string, adapters: Readonly<ToolAdapter>[]): Promise<CodacyConfig>;
1065
+ declare function initContainerConfig(repositoryRoot: string, adapters: Readonly<ToolAdapter>[], codacyrcPath?: string): Promise<CodacyConfig>;
666
1066
  /** Stats returned alongside the config from `initAutoConfig`. */
667
1067
  interface InitAutoStats {
668
1068
  /** Number of languages detected by discover. */
@@ -1224,4 +1624,84 @@ declare function buildPayloads(issues: NormalizedIssue[], resolveShortName: (too
1224
1624
  */
1225
1625
  declare function uploadReport(options: UploadOptions): Promise<UploadResult>;
1226
1626
 
1227
- export { type AdapterFactory, type AnalyzeOptions, type AutoFilters, type CategoryFilter, type CodacyYamlConfig, type CodacyYamlEngineConfig, type ConfigOperation, type DiscoverOptions, type DiscoveryExcludes, type ExecutionMode, type IgnoredFilesResult, type InitAutoStats, type InitDefaultStats, type InitDiscoveryOptions, type InitLocalStats, type InitRemoteStats, type LoggerOptions, type MergeOptions, type NormalizedIssue, type PatternMetadataLookup, type RemoteAuth, type SeverityFilter, type UploadAuth, type UploadOptions, type UploadResult, analyze, applyCodacyYamlExcludes, applyConfigOperation, buildPayloads, buildToolConfig, clearAdapters, computePatternSummary, configureApiToken, createCodacyConfig, createLogger, createNullLogger, deleteCredentials, detectLanguages, diffConfigs, discover, formatOutput, formatTextSummary, getAdapter, getKnownDisplayNames, getRegisteredAdapters, getRegisteredDescriptors, initAutoConfig, initContainerConfig, initDefaultConfig, initLocalConfig, initRemoteConfig, intersectConfigs, listDiffFiles, listIgnoredFiles, listPrFiles, listStagedFiles, loadCredentials, mergeConfigs, parseAutoFilters, parseReport, pruneEmptyTools, readBaselineConfig, readCodacyConfig, readCodacyYaml, registerAdapter, registerLazyAdapter, registerUnsupportedTool, relativizeLocalConfigPaths, resolveApiToken, resolveBaselinePath, resolveConfigPath, resolveDiscoveryExcludes, resolveEngineToAdapter, resolveHeadCommit, resolveLocalConfigPaths, resolveRemoteAuth, resolveRepositoryRoot, resolveResultsApiBaseUrl, rotateLogFiles, saveCredentials, updateConfigIncremental, uploadReport, validateApiToken, writeBaselineConfig, writeCodacyConfig, writeCodacyConfigFile };
1627
+ /**
1628
+ * Container-image operations: vulnerability scanning (`container-scan`) and
1629
+ * SBOM generation + upload (`upload-sbom`), the two cli-v2 commands that work
1630
+ * on an image rather than a repository working tree.
1631
+ *
1632
+ * The runner stays tool-agnostic here as everywhere else: it looks for a
1633
+ * registered adapter whose descriptor declares `scansContainerImages` (today,
1634
+ * Trivy) and drives it through `ToolAdapter.containerImage`. Validation of every
1635
+ * user-supplied value happens **before** any tool is installed or spawned.
1636
+ */
1637
+
1638
+ /** cli-v2's defaults, kept so migrated CI pipelines report exactly what they did. */
1639
+ declare const DEFAULT_IMAGE_SCAN_SEVERITIES: readonly ImageScanSeverity[];
1640
+ /** cli-v2's default: OS packages only. */
1641
+ declare const DEFAULT_IMAGE_SCAN_PKG_TYPES: readonly ImageScanPkgType[];
1642
+ /** Options for {@link scanContainerImage}. */
1643
+ interface ScanContainerImageOptions {
1644
+ /** Image reference, e.g. `nginx:1.25`, `ghcr.io/org/app:v1`, `app@sha256:…`. */
1645
+ image: string;
1646
+ /** Severities to report. Defaults to {@link DEFAULT_IMAGE_SCAN_SEVERITIES}. */
1647
+ severities?: readonly string[];
1648
+ /** Package classes to inspect. Defaults to {@link DEFAULT_IMAGE_SCAN_PKG_TYPES}. */
1649
+ pkgTypes?: readonly string[];
1650
+ /** Skip vulnerabilities with no released fix. Defaults to `true`, as in cli-v2. */
1651
+ ignoreUnfixed?: boolean;
1652
+ logger?: Logger;
1653
+ signal?: AbortSignal;
1654
+ }
1655
+ /**
1656
+ * Scans a container image for vulnerabilities and returns an ordinary
1657
+ * {@link AnalysisResult}, so `formatOutput` renders it in every format and
1658
+ * `localExitCode` maps it to 0 (clean) / 1 (findings) / 2 (failure).
1659
+ *
1660
+ * Throws — before installing or spawning anything — for an invalid image
1661
+ * reference or an unknown severity / package type, and when no image-capable
1662
+ * adapter is registered (`registerBuiltinAdapters()` not called). Everything
1663
+ * after that, including a failed install or a failed scan, is reported inside
1664
+ * the result rather than thrown — as is caller cancellation through `signal`,
1665
+ * which yields a `Cancelled` error exactly like `analyze()`.
1666
+ */
1667
+ declare function scanContainerImage(options: ScanContainerImageOptions): Promise<AnalysisResult>;
1668
+ /** Options for {@link uploadImageSbom}. */
1669
+ interface UploadImageSbomOptions {
1670
+ /** Image reference. A digest reference cannot be combined with `tag`. */
1671
+ image: string;
1672
+ /** Tag to record; defaults to the reference's own tag, then `latest`. */
1673
+ tag?: string;
1674
+ /** SBOM document format. Defaults to `cyclonedx` (smaller output). */
1675
+ format?: string;
1676
+ /** Git provider: `gh`, `gl` or `bb`. */
1677
+ provider: string;
1678
+ organization: string;
1679
+ /** Codacy repository to associate the image with. */
1680
+ repositoryName?: string;
1681
+ /** Where the image is deployed, e.g. `production`. */
1682
+ environment?: string;
1683
+ /** Account API token. The endpoint has no repository-token mode. */
1684
+ apiToken: string;
1685
+ logger?: Logger;
1686
+ signal?: AbortSignal;
1687
+ /** Progress lines for the caller to display (e.g. on stderr). */
1688
+ onProgress?: (message: string) => void;
1689
+ }
1690
+ /** What {@link uploadImageSbom} uploaded. */
1691
+ interface UploadImageSbomResult {
1692
+ imageName: string;
1693
+ tag: string;
1694
+ format: SbomFormat;
1695
+ }
1696
+ /**
1697
+ * Generates an SBOM for a container image and uploads it to the organization's
1698
+ * image-SBOM endpoint — one step, as cli-v2's `upload-sbom` was.
1699
+ *
1700
+ * Every input is validated before anything is installed or spawned. The SBOM
1701
+ * is written to a private temp directory that is removed on success and on
1702
+ * every failure path. Throws on any failure, with a message naming the stage
1703
+ * (validation, install, generation or upload) that failed.
1704
+ */
1705
+ declare function uploadImageSbom(options: UploadImageSbomOptions): Promise<UploadImageSbomResult>;
1706
+
1707
+ export { type AdapterFactory, type AdapterLookup, type AnalyzeOptions, type AutoFilters, type CategoryFilter, type CodacyYamlConfig, type CodacyYamlEngineConfig, type Codacyrc, type CodacyrcParameter, type CodacyrcPattern, type CodacyrcResolution, type CodacyrcTool, type CodacyrcToolInput, type ConfigOperation, DEFAULT_IMAGE_SCAN_PKG_TYPES, DEFAULT_IMAGE_SCAN_SEVERITIES, type DiscoverOptions, type DiscoveryExcludes, type ExecutionMode, type IgnoredFilesResult, type InitAutoStats, type InitDefaultStats, type InitDiscoveryOptions, type InitLocalStats, type InitRemoteStats, type InstallToolsOptions, type InstallToolsResult, type LoggerOptions, type MergeOptions, type NormalizedIssue, type PatternIdTranslator, type PatternMetadataLookup, type RemoteAuth, type ScanContainerImageOptions, type SeverityFilter, type ToolInstallReport, type ToolInstallStatus, type UploadAuth, type UploadImageSbomOptions, type UploadImageSbomResult, type UploadOptions, type UploadResult, analyze, applyCodacyYamlExcludes, applyConfigOperation, buildCodacyrc, buildPatternTranslator, buildPayloads, buildToolConfig, clearAdapters, computePatternSummary, configureApiToken, createCodacyConfig, createLogger, createNullLogger, deleteCredentials, detectLanguages, diffConfigs, discover, formatOutput, formatTextSummary, getAdapter, getKnownDisplayNames, getRegisteredAdapters, getRegisteredDescriptors, initAutoConfig, initContainerConfig, initDefaultConfig, initLocalConfig, initRemoteConfig, installTools, intersectConfigs, listDiffFiles, listIgnoredFiles, listPrFiles, listStagedFiles, loadCredentials, mergeConfigs, parseAutoFilters, parseCodacyrc, parseReport, partitionContainerErrors, pruneEmptyTools, readBaselineConfig, readCodacyConfig, readCodacyYaml, readCodacyrc, registerAdapter, registerLazyAdapter, registerUnsupportedTool, registryLookup, relativizeLocalConfigPaths, resolveApiToken, resolveBaselinePath, resolveCodacyrc, resolveConfigPath, resolveDiscoveryExcludes, resolveEngineToAdapter, resolveHeadCommit, resolveLocalConfigPaths, resolveRemoteAuth, resolveRepositoryRoot, resolveResultsApiBaseUrl, resolveToolName, rotateLogFiles, saveCredentials, scanContainerImage, serializeCodacyrc, toEnginePatternId, updateConfigIncremental, uploadImageSbom, uploadReport, validateApiToken, writeBaselineConfig, writeCodacyConfig, writeCodacyConfigFile };