@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 +9 -4
- package/dist/index.js +24 -32
- package/dist/metadata.js +1 -1
- package/package.json +2 -2
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
|
|
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
|
|
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\
|
|
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
|
|
31114
|
-
* platform/arch/libc → asset mapping mirrors opengrep's
|
|
31115
|
-
* (see {@link opengrepAssetName}). The
|
|
31116
|
-
* `ctx.toolInstallDir/opengrep
|
|
31117
|
-
*
|
|
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
|
|
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
|
|
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
|
-
*
|
|
31194
|
-
*
|
|
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 =
|
|
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.
|
|
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.
|
|
13
|
+
"@codacy/tooling": "0.25.0"
|
|
14
14
|
},
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"author": "Codacy <support@codacy.com> (https://www.codacy.com)",
|