@codacy/tools-opengrep-1 0.24.0 → 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.
package/README.md CHANGED
@@ -127,8 +127,9 @@ codacy-analysis analyze . --tool opengrep --install-dependencies
127
127
  ```
128
128
 
129
129
  `install()` downloads the matching statically-linked binary from GitHub releases
130
- (no archive to unpack) and `chmod +x`es it. The platform/arch/libc → asset
131
- mapping mirrors opengrep's official `install.sh`:
130
+ (no archive to unpack) and `chmod +x`es it (not on Windows). The
131
+ platform/arch/libc → asset mapping mirrors opengrep's official `install.sh` and
132
+ `install.ps1`:
132
133
 
133
134
  | Platform | Asset |
134
135
  | ------------------------- | ---------------------------- |
@@ -138,11 +139,15 @@ mapping mirrors opengrep's official `install.sh`:
138
139
  | Linux arm64 (glibc) | `opengrep_manylinux_aarch64` |
139
140
  | Linux x64 (musl/Alpine) | `opengrep_musllinux_x86` |
140
141
  | Linux arm64 (musl/Alpine) | `opengrep_musllinux_aarch64` |
142
+ | Windows x64 | `opengrep_windows_x86.exe` |
143
+ | Windows arm64 (emulated) | `opengrep_windows_x86.exe` |
141
144
 
142
145
  To install manually instead:
143
146
 
144
147
  ```bash
145
148
  curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install.sh | bash
149
+ # Windows (PowerShell)
150
+ irm https://raw.githubusercontent.com/opengrep/opengrep/main/install.ps1 | iex
146
151
  ```
147
152
 
148
153
  ## Notes for maintainers
@@ -180,11 +185,11 @@ curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install.sh |
180
185
 
181
186
  - **Tool ID is `Semgrep`** for legacy compatibility with the Codacy platform. The `displayName` is set to `Opengrep` for CLI display. Never change the tool ID without coordinating with the Codacy platform team.
182
187
  - **Config materialization**: When Codacy patterns are specified, the adapter loads `src/rules.yaml`, filters to enabled rules, and writes a filtered config to `.codacy/generated/opengrep-rules.yaml`.
183
- - **check_id prefix stripping**: Opengrep prepends a path-based namespace to check_ids derived from the config file path relative to cwd. The adapter computes and strips this prefix (e.g. `codacy.generated.`) plus any `tmp.` legacy prefix.
188
+ - **check_id is the bare rule ID**: every invocation passes `--no-rewrite-rule-ids`. Without it Opengrep prefixes `check_id` with the config file's directory relative to cwd (`.codacy/generated/x.yaml` → `codacy.generated.`), and the adapter used to reproduce that path math to strip the prefix again — never verified on Windows, where a mismatch would silently drop every finding at the enabled-pattern check. With the flag the rule ID maps to a pattern ID directly on every OS.
184
189
  - **Config file search**: `.semgrep.yaml`, `.opengrep.yaml`, `.semgrep.yml`, `.opengrep.yml` (in that order).
185
190
  - **Opengrep errors**: Parse errors (syntax errors, partial parsing) from Opengrep's JSON `errors` array are converted to structured `AnalysisError` objects with `filePath`. Stderr (scan status table) is logged at debug level only.
186
191
  - **Rule ID format**: Semgrep-rules use `{dir}.{filename}.{ruleId}` (dots), GitLab rules use `{dir}_{filename}` (underscores), Codacy custom rules keep their original IDs.
187
- - **Install / binary download**: `install()` downloads the bare per-platform binary from `https://github.com/opengrep/opengrep/releases/download/v{version}/{asset}` and `chmod +x`es it into `~/.codacy/tools/`. The release tag carries a `v` prefix (`v1.26.0`) even though `preferredVersion` does not. On Linux the libc flavour is detected with an `ldd /bin/sh` probe (`musl` → musllinux, else manylinux); detection failures fall back to glibc/manylinux. Unlike install.sh, the Codacy-managed install does **not** verify the cosign `.cert`/`.sig` signatures — if signature verification becomes a requirement, fetch those sibling assets and validate before chmod.
192
+ - **Install / binary download**: `install()` downloads the bare per-platform binary from `https://github.com/opengrep/opengrep/releases/download/v{version}/{asset}` and `chmod +x`es it into `~/.codacy/tools/`. The release tag carries a `v` prefix (`v1.26.0`) even though `preferredVersion` does not. On Linux the libc flavour is detected with an `ldd /bin/sh` probe (`musl` → musllinux, else manylinux); detection failures fall back to glibc/manylinux. On Windows the binary is saved as `opengrep.exe`; upstream builds only x64, which `install.ps1` also installs on ARM64 (emulated), so we do the same. **From opengrep 2.0.0 the Windows asset becomes `opengrep_windows_x86.zip`** (exe + DLLs) — bumping `preferredVersion` past 2.0 needs an extraction step. The argv chunk budget drops to `MAX_ARGV_BYTES` (30,000) on Windows, whose command line is capped at 32,767 characters. Unlike install.sh, the Codacy-managed install does **not** verify the cosign `.cert`/`.sig` signatures — if signature verification becomes a requirement, fetch those sibling assets and validate before chmod.
188
193
  - **Argv-size chunking (no directory walk)**: The adapter always passes Opengrep an **explicit file list** — the runner's already git-ignored, exclude-filtered target set — so Opengrep never walks the repository tree itself. `chunkFilesByArgvBudget()` splits that list into the **fewest, largest** chunks that each fit `ARGV_BYTE_BUDGET` (200 KB, well under `ARG_MAX`), and each chunk is scanned in its own `opengrep scan` invocation; findings and errors are merged across chunks. Chunk by **size, not count**: every invocation re-compiles `rules.yaml`, so fewer/larger chunks amortize that fixed cost. The earlier directory/“root” fallback was removed because on huge repos (a single tracked file at the repo root collapsed the minimal-cover dirs to `.`) it made Opengrep walk the entire tree — re-scanning excluded/generated/vendored files and timing out at the runner's 10-minute limit.
189
194
  - **File-size cap**: invocations pass `--max-target-bytes 1000000` (~1 MB). This restores Opengrep's default size cap — the adapter previously passed `0`, which **disables** the cap, so giant generated/minified bundles were scanned and dominated runtime. The cap applies to explicitly-listed files (verified on v1.16.4). Note: `--exclude-minified-files` is **not** used — that flag is rejected by the bundled binary unless `--experimental` (a different engine) is also passed, so we rely on the size cap instead. (The runner also enforces a tighter 150 KB per-file limit centrally before files reach the adapter, so this `--max-target-bytes` is now a secondary defense.)
190
195
  - **Partial results on timeout**: the per-chunk loop checks `ctx.signal` (the runner's timeout abort) between chunks and passes it to `spawnTool`, so an in-flight scan is killed promptly. On abort the adapter keeps the findings from completed chunks and adds a single `Timeout` error (→ `status: "partial"`) rather than losing everything. This is why chunking matters beyond ARG_MAX: it's the granularity at which a long scan can be stopped with results preserved.
package/dist/index.js CHANGED
@@ -30858,7 +30858,7 @@ var descriptor = {
30858
30858
  "**/Vagrantfile",
30859
30859
  "**/config.ru"
30860
30860
  ],
30861
- supportedOS: ["linux", "darwin"],
30861
+ supportedOS: ["linux", "darwin", "win32"],
30862
30862
  supportedArch: ["x64", "arm64"],
30863
30863
  supportedRunners: ["local", "container"],
30864
30864
  frameworkMappings: pattern_mappings_default
@@ -30903,6 +30903,10 @@ function opengrepAssetName(osName, arch, muslLibc) {
30903
30903
  if (arch === "arm64") return `opengrep_${flavour}_aarch64`;
30904
30904
  return null;
30905
30905
  }
30906
+ if (osName === "win32") {
30907
+ if (arch === "x64" || arch === "arm64") return "opengrep_windows_x86.exe";
30908
+ return null;
30909
+ }
30906
30910
  return null;
30907
30911
  }
30908
30912
  async function isMuslLibc() {
@@ -30928,32 +30932,18 @@ async function getVersionFromBinary(binaryPath) {
30928
30932
  }
30929
30933
  }
30930
30934
  async function resolveBinaryPath(ctx) {
30931
- const codacyBin = import_path.default.join(ctx.toolInstallDir, BINARY);
30935
+ const codacyBin = import_path.default.join(ctx.toolInstallDir, (0, import_tooling.exeName)(BINARY));
30932
30936
  const version = await getVersionFromBinary(codacyBin);
30933
30937
  if (version) return codacyBin;
30934
30938
  return BINARY;
30935
30939
  }
30936
- function computeConfigPrefix(configPath, cwd) {
30937
- const relPath = import_path.default.relative(cwd, configPath);
30938
- const dir = import_path.default.dirname(relPath);
30939
- if (dir === ".") return "";
30940
- const components = dir.split(import_path.default.sep).map((c) => c.replace(/^\.+/, ""));
30941
- return components.filter(Boolean).join(".") + ".";
30942
- }
30943
- function stripCheckIdPrefix(checkId, configPrefix) {
30944
- let stripped = checkId.startsWith("tmp.") ? checkId.slice(4) : checkId;
30945
- if (configPrefix && stripped.startsWith(configPrefix)) {
30946
- stripped = stripped.slice(configPrefix.length);
30947
- }
30948
- return stripped;
30949
- }
30950
30940
  function firstSentence(message) {
30951
30941
  const oneLine = message.replace(/\n/g, " ");
30952
30942
  const match = /(^.*?[a-z]{2,}[.!?])\s+\W*[A-Z]/.exec(oneLine);
30953
30943
  if (match) return match[1];
30954
30944
  return oneLine.length > 500 ? oneLine.slice(0, 500) : oneLine;
30955
30945
  }
30956
- var ARGV_BYTE_BUDGET = 200 * 1024;
30946
+ var ARGV_BYTE_BUDGET = import_tooling.IS_WINDOWS ? import_tooling.MAX_ARGV_BYTES : 200 * 1024;
30957
30947
  function chunkFilesByArgvBudget(files) {
30958
30948
  const chunks = [];
30959
30949
  let current = [];
@@ -31073,7 +31063,7 @@ var adapter = {
31073
31063
  */
31074
31064
  async checkAvailability(ctx) {
31075
31065
  ctx.logger.debug("Checking availability", { toolId: TOOL_ID });
31076
- const codacyBin = import_path.default.join(ctx.toolInstallDir, BINARY);
31066
+ const codacyBin = import_path.default.join(ctx.toolInstallDir, (0, import_tooling.exeName)(BINARY));
31077
31067
  const codacyVersion = await getVersionFromBinary(codacyBin);
31078
31068
  if (codacyVersion) {
31079
31069
  ctx.logger.debug("Found opengrep in codacy install dir", {
@@ -31103,21 +31093,22 @@ var adapter = {
31103
31093
  return {
31104
31094
  available: false,
31105
31095
  reason: "opengrep binary not found in PATH or Codacy install directory",
31106
- installHint: "codacy-analysis analyze . --install-dependencies # auto-install into ~/.codacy\ncurl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install.sh | bash # manual"
31096
+ installHint: "codacy-analysis analyze . --install-dependencies # auto-install into ~/.codacy\n" + (import_tooling.IS_WINDOWS ? "irm https://raw.githubusercontent.com/opengrep/opengrep/main/install.ps1 | iex # manual (PowerShell)" : "curl -fsSL https://raw.githubusercontent.com/opengrep/opengrep/main/install.sh | bash # manual")
31107
31097
  };
31108
31098
  },
31109
31099
  /**
31110
31100
  * Downloads the opengrep binary from GitHub releases into `ctx.toolInstallDir`.
31111
31101
  *
31112
31102
  * Opengrep distributes a single statically-linked executable per platform
31113
- * (no archive), so install is just a download + `chmod +x`. The
31114
- * platform/arch/libc → asset mapping mirrors opengrep's official install.sh
31115
- * (see {@link opengrepAssetName}). The binary lands at
31116
- * `ctx.toolInstallDir/opengrep`, which `checkAvailability` probes first — so
31117
- * the runner's post-install re-check picks up the managed install.
31103
+ * (no archive), so install is just a download + `chmod +x` (no chmod on
31104
+ * Windows). The platform/arch/libc → asset mapping mirrors opengrep's
31105
+ * official install.sh / install.ps1 (see {@link opengrepAssetName}). The
31106
+ * binary lands at `ctx.toolInstallDir/opengrep` (`opengrep.exe` on Windows),
31107
+ * which `checkAvailability` probes first — so the runner's post-install
31108
+ * re-check picks up the managed install.
31118
31109
  *
31119
31110
  * Returns an `UnsupportedPlatform` error for targets opengrep has no binary
31120
- * for (e.g. Windows), and a `DownloadError` if the fetch fails.
31111
+ * for, and a `DownloadError` if the fetch fails.
31121
31112
  */
31122
31113
  async install(ctx) {
31123
31114
  ctx.logger.info("Starting install", { toolId: TOOL_ID });
@@ -31132,17 +31123,17 @@ var adapter = {
31132
31123
  toolId: TOOL_ID,
31133
31124
  phase: "toolInstall",
31134
31125
  kind: "UnsupportedPlatform",
31135
- message: `Unsupported platform: ${platformKey}. Opengrep provides binaries for darwin-x64, darwin-arm64, linux-x64, and linux-arm64.`,
31126
+ message: `Unsupported platform: ${platformKey}. Opengrep provides binaries for darwin-x64, darwin-arm64, linux-x64, linux-arm64, and win32-x64 (also used on win32-arm64).`,
31136
31127
  level: "error"
31137
31128
  }
31138
31129
  };
31139
31130
  }
31140
31131
  const url = `https://github.com/opengrep/opengrep/releases/download/v${version}/${assetName}`;
31141
- const destPath = import_path.default.join(ctx.toolInstallDir, BINARY);
31132
+ const destPath = import_path.default.join(ctx.toolInstallDir, (0, import_tooling.exeName)(BINARY));
31142
31133
  try {
31143
31134
  ctx.logger.info(`Downloading Opengrep v${version} for ${platformKey}...`);
31144
31135
  await (0, import_tooling.downloadFile)(url, destPath, ctx.logger);
31145
- await import_promises.default.chmod(destPath, 493);
31136
+ if (!import_tooling.IS_WINDOWS) await import_promises.default.chmod(destPath, 493);
31146
31137
  ctx.logger.info(`Installed opengrep v${version} to ${destPath}`);
31147
31138
  return { success: true, installedPath: destPath, installedVersion: version };
31148
31139
  } catch (err) {
@@ -31190,8 +31181,9 @@ var adapter = {
31190
31181
  * the enabled rules and write a generated config.
31191
31182
  * 3. If no patterns and no local config, use the full bundled rules.yaml.
31192
31183
  *
31193
- * The `tmp.` prefix that opengrep adds to check IDs when using inline
31194
- * configs is stripped before building pattern IDs.
31184
+ * Every invocation passes `--no-rewrite-rule-ids`, so `check_id` is the rule
31185
+ * ID exactly as written in the config and maps to a pattern ID directly (see
31186
+ * the note on `baseArgs`).
31195
31187
  *
31196
31188
  * Exit codes:
31197
31189
  * - 0: success (findings may or may not exist)
@@ -31264,6 +31256,7 @@ var adapter = {
31264
31256
  "--json",
31265
31257
  "--config",
31266
31258
  configFile,
31259
+ "--no-rewrite-rule-ids",
31267
31260
  "--timeout",
31268
31261
  "5",
31269
31262
  "--timeout-threshold",
@@ -31332,7 +31325,6 @@ var adapter = {
31332
31325
  }
31333
31326
  }
31334
31327
  const enabledPatterns = new Set(codacyConfig.patterns.map((p) => p.patternId));
31335
- const configPrefix = configFile ? computeConfigPrefix(configFile, ctx.repositoryRoot) : "";
31336
31328
  const findingsByFile = /* @__PURE__ */ new Map();
31337
31329
  for (const finding of allFindings) {
31338
31330
  if (finding.extra.is_ignored) continue;
@@ -31350,7 +31342,7 @@ var adapter = {
31350
31342
  const lines = await (0, import_tooling.readFileLines)(absoluteFilePath);
31351
31343
  const relPath = import_path.default.relative(ctx.repositoryRoot, absoluteFilePath);
31352
31344
  for (const finding of fileFindings) {
31353
- const ruleId = stripCheckIdPrefix(finding.check_id, configPrefix);
31345
+ const ruleId = finding.check_id;
31354
31346
  const patternId = `${TOOL_ID}_${ruleId}`;
31355
31347
  if (enabledPatterns.size > 0 && !enabledPatterns.has(patternId)) {
31356
31348
  continue;
package/dist/metadata.js CHANGED
@@ -391,7 +391,7 @@ var descriptor = {
391
391
  "**/Vagrantfile",
392
392
  "**/config.ru"
393
393
  ],
394
- supportedOS: ["linux", "darwin"],
394
+ supportedOS: ["linux", "darwin", "win32"],
395
395
  supportedArch: ["x64", "arm64"],
396
396
  supportedRunners: ["local", "container"],
397
397
  frameworkMappings: pattern_mappings_default
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codacy/tools-opengrep-1",
3
- "version": "0.24.0",
3
+ "version": "0.25.0",
4
4
  "description": "Opengrep adapter — CLI-mode multi-language SAST scanner",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -10,7 +10,7 @@
10
10
  ],
11
11
  "dependencies": {
12
12
  "yaml": "^2.6.0",
13
- "@codacy/tooling": "0.24.0"
13
+ "@codacy/tooling": "0.25.0"
14
14
  },
15
15
  "license": "MIT",
16
16
  "author": "Codacy <support@codacy.com> (https://www.codacy.com)",