@vyuhlabs/dxkit 2.4.5 → 2.4.6
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/CHANGELOG.md +137 -0
- package/README.md +31 -21
- package/dist/analyzers/tests/index.d.ts.map +1 -1
- package/dist/analyzers/tests/index.js +2 -0
- package/dist/analyzers/tests/index.js.map +1 -1
- package/dist/analyzers/tools/coverage.d.ts +1 -1
- package/dist/analyzers/tools/coverage.d.ts.map +1 -1
- package/dist/analyzers/tools/coverage.js.map +1 -1
- package/dist/analyzers/tools/osv-scanner-deps.d.ts +47 -0
- package/dist/analyzers/tools/osv-scanner-deps.d.ts.map +1 -0
- package/dist/analyzers/tools/{osv-scanner-maven.js → osv-scanner-deps.js} +49 -35
- package/dist/analyzers/tools/osv-scanner-deps.js.map +1 -0
- package/dist/analyzers/tools/tool-registry.d.ts +10 -0
- package/dist/analyzers/tools/tool-registry.d.ts.map +1 -1
- package/dist/analyzers/tools/tool-registry.js +109 -0
- package/dist/analyzers/tools/tool-registry.js.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -1
- package/dist/languages/index.d.ts.map +1 -1
- package/dist/languages/index.js +2 -0
- package/dist/languages/index.js.map +1 -1
- package/dist/languages/java.d.ts.map +1 -1
- package/dist/languages/java.js +8 -6
- package/dist/languages/java.js.map +1 -1
- package/dist/languages/kotlin.d.ts.map +1 -1
- package/dist/languages/kotlin.js +8 -6
- package/dist/languages/kotlin.js.map +1 -1
- package/dist/languages/ruby.d.ts +77 -0
- package/dist/languages/ruby.d.ts.map +1 -0
- package/dist/languages/ruby.js +531 -0
- package/dist/languages/ruby.js.map +1 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/templates/.claude/rules/ruby.md +11 -0
- package/templates/configs/ruby/README.md +6 -0
- package/dist/analyzers/tools/osv-scanner-maven.d.ts +0 -42
- package/dist/analyzers/tools/osv-scanner-maven.d.ts.map +0 -1
- package/dist/analyzers/tools/osv-scanner-maven.js.map +0 -1
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.ruby = void 0;
|
|
37
|
+
exports.extractRubyImportsRaw = extractRubyImportsRaw;
|
|
38
|
+
exports.mapRubocopSeverity = mapRubocopSeverity;
|
|
39
|
+
exports.parseRubocopOutput = parseRubocopOutput;
|
|
40
|
+
exports.parseSimpleCovResultset = parseSimpleCovResultset;
|
|
41
|
+
const fs = __importStar(require("fs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
const coverage_1 = require("../analyzers/tools/coverage");
|
|
44
|
+
const exclusions_1 = require("../analyzers/tools/exclusions");
|
|
45
|
+
const osv_scanner_deps_1 = require("../analyzers/tools/osv-scanner-deps");
|
|
46
|
+
const runner_1 = require("../analyzers/tools/runner");
|
|
47
|
+
const tool_registry_1 = require("../analyzers/tools/tool-registry");
|
|
48
|
+
// ─── Detection ──────────────────────────────────────────────────────────────
|
|
49
|
+
/**
|
|
50
|
+
* Walk the project tree (bounded depth) looking for a `.rb` source file.
|
|
51
|
+
* G9 discipline (Recipe v3): manifest-only detection (Gemfile alone)
|
|
52
|
+
* over-activates on mixed-stack repos and scaffolded-but-empty projects.
|
|
53
|
+
* The pack only matters when there is actual Ruby source to analyze.
|
|
54
|
+
*/
|
|
55
|
+
function hasRubySourceWithinDepth(cwd, maxDepth = 5) {
|
|
56
|
+
function search(dir, depth) {
|
|
57
|
+
if (depth > maxDepth)
|
|
58
|
+
return false;
|
|
59
|
+
let entries;
|
|
60
|
+
try {
|
|
61
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
for (const e of entries) {
|
|
67
|
+
if (e.name.startsWith('.') || ['node_modules', 'vendor', 'tmp', 'log'].includes(e.name)) {
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
if (e.isFile() && e.name.endsWith('.rb'))
|
|
71
|
+
return true;
|
|
72
|
+
if (e.isDirectory() && search(path.join(dir, e.name), depth + 1))
|
|
73
|
+
return true;
|
|
74
|
+
}
|
|
75
|
+
return false;
|
|
76
|
+
}
|
|
77
|
+
return search(cwd, 0);
|
|
78
|
+
}
|
|
79
|
+
function detectRuby(cwd) {
|
|
80
|
+
return hasRubySourceWithinDepth(cwd, 5);
|
|
81
|
+
}
|
|
82
|
+
// ─── Imports (regex extraction, no resolver) ────────────────────────────────
|
|
83
|
+
/**
|
|
84
|
+
* Capture Ruby require / require_relative / autoload specifiers from source
|
|
85
|
+
* text. Three forms recognised:
|
|
86
|
+
*
|
|
87
|
+
* require 'json' → 'json'
|
|
88
|
+
* require_relative '../foo/bar' → '../foo/bar'
|
|
89
|
+
* autoload :Sym, 'foo/bar' → 'foo/bar'
|
|
90
|
+
*
|
|
91
|
+
* Ruby's metaprogramming (`__send__`, `Object.const_missing`, Rails'
|
|
92
|
+
* Zeitwerk autoloader) makes static import analysis fundamentally
|
|
93
|
+
* best-effort — many "imports" in idiomatic Ruby never appear as
|
|
94
|
+
* literal `require` calls. This parser extracts the literal-string
|
|
95
|
+
* cases only; downstream consumers should treat the output as a lower
|
|
96
|
+
* bound. Future v4 candidate: explicit best-effort contract on the
|
|
97
|
+
* imports envelope so consumers can distinguish "exhaustive" (TS, Go)
|
|
98
|
+
* from "best-effort" (Ruby, kotlin/Java reflection paths).
|
|
99
|
+
*
|
|
100
|
+
* Comments are stripped (single-line `#`) before matching so a
|
|
101
|
+
* commented-out `# require 'foo'` does not false-match. Multi-line
|
|
102
|
+
* `=begin ... =end` blocks containing requires are not extracted
|
|
103
|
+
* (acceptable: comment-out-import is intentional non-use).
|
|
104
|
+
*
|
|
105
|
+
* Both single and double quotes are accepted; dynamic `require x` (no
|
|
106
|
+
* literal string) is skipped — there is no specifier to capture.
|
|
107
|
+
*
|
|
108
|
+
* Exported for unit tests; consumed by `gatherRubyImportsResult`.
|
|
109
|
+
*/
|
|
110
|
+
function extractRubyImportsRaw(content) {
|
|
111
|
+
const out = [];
|
|
112
|
+
// Strip line comments first so `# require 'foo'` doesn't false-match.
|
|
113
|
+
// Conservative: only `#` at start-of-line or after whitespace, to avoid
|
|
114
|
+
// mangling `#{interpolation}` inside double-quoted strings.
|
|
115
|
+
const stripped = content.replace(/(^|\s)#[^\n]*/g, '$1');
|
|
116
|
+
const requireRe = /^\s*(?:require|require_relative)\s+['"]([^'"]+)['"]/gm;
|
|
117
|
+
let m;
|
|
118
|
+
while ((m = requireRe.exec(stripped)) !== null) {
|
|
119
|
+
out.push(m[1]);
|
|
120
|
+
}
|
|
121
|
+
// autoload :Sym, 'path' — capture the path arg only (the symbol is the
|
|
122
|
+
// local binding name, not the import target).
|
|
123
|
+
const autoloadRe = /^\s*autoload\s+:[A-Za-z_]\w*\s*,\s*['"]([^'"]+)['"]/gm;
|
|
124
|
+
while ((m = autoloadRe.exec(stripped)) !== null) {
|
|
125
|
+
out.push(m[1]);
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Enumerate `.rb` files under cwd and capture per-file imports. Ruby has
|
|
131
|
+
* no file-level resolver — `require 'foo'` searches `$LOAD_PATH` (a
|
|
132
|
+
* runtime-mutable array), Rails projects defer wholly to Zeitwerk's
|
|
133
|
+
* convention-based autoload, and `require_relative` paths sometimes
|
|
134
|
+
* lack the `.rb` extension. Mirrors rust/kotlin/csharp/java packs:
|
|
135
|
+
* `extracted` is populated for completeness, `edges` is always empty,
|
|
136
|
+
* file-level resolution is left to graphify if downstream consumers
|
|
137
|
+
* need it.
|
|
138
|
+
*/
|
|
139
|
+
function gatherRubyImportsResult(cwd) {
|
|
140
|
+
const excludes = (0, exclusions_1.getFindExcludeFlags)(cwd);
|
|
141
|
+
const raw = (0, runner_1.run)(`find . -type f -name "*.rb" ${excludes} 2>/dev/null`, cwd);
|
|
142
|
+
if (!raw)
|
|
143
|
+
return null;
|
|
144
|
+
const extracted = new Map();
|
|
145
|
+
for (const line of raw.split('\n')) {
|
|
146
|
+
const p = line.trim();
|
|
147
|
+
if (!p)
|
|
148
|
+
continue;
|
|
149
|
+
const rel = p.replace(/^\.\//, '');
|
|
150
|
+
let content;
|
|
151
|
+
try {
|
|
152
|
+
content = fs.readFileSync(path.join(cwd, rel), 'utf-8');
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
continue;
|
|
156
|
+
}
|
|
157
|
+
extracted.set(rel, extractRubyImportsRaw(content));
|
|
158
|
+
}
|
|
159
|
+
if (extracted.size === 0)
|
|
160
|
+
return null;
|
|
161
|
+
return {
|
|
162
|
+
schemaVersion: 1,
|
|
163
|
+
tool: 'ruby-imports',
|
|
164
|
+
sourceExtensions: ['.rb'],
|
|
165
|
+
extracted,
|
|
166
|
+
edges: new Map(),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
const rubyImportsProvider = {
|
|
170
|
+
source: 'ruby',
|
|
171
|
+
async gather(cwd) {
|
|
172
|
+
return gatherRubyImportsResult(cwd);
|
|
173
|
+
},
|
|
174
|
+
};
|
|
175
|
+
// ─── Test framework (Gemfile / Gemfile.lock text scan) ──────────────────────
|
|
176
|
+
/**
|
|
177
|
+
* Detect the Ruby test framework by scanning Gemfile + Gemfile.lock for
|
|
178
|
+
* known gem names. Order of precedence: rspec → minitest → test-unit.
|
|
179
|
+
*
|
|
180
|
+
* - RSpec ('rspec', 'rspec-rails') — by far the most common Ruby
|
|
181
|
+
* test runner, takes precedence when present.
|
|
182
|
+
* - Minitest — Ruby stdlib's runner, often used directly or via
|
|
183
|
+
* Rails' default `test/` directory.
|
|
184
|
+
* - test-unit — Ruby 1.8-era runner; still used by some legacy
|
|
185
|
+
* projects and by Ruby itself's stdlib tests.
|
|
186
|
+
*
|
|
187
|
+
* Falls back to test-file glob counts when no Gemfile is present (a
|
|
188
|
+
* vendored library directory or scratch script repo). The glob counts
|
|
189
|
+
* mirror the test patterns declared on the pack: `*_spec.rb` → rspec,
|
|
190
|
+
* `*_test.rb` / `test_*.rb` → minitest.
|
|
191
|
+
*
|
|
192
|
+
* Returns null when nothing identifies a framework — analyzers should
|
|
193
|
+
* treat null as "test-runner unknown" rather than "no tests."
|
|
194
|
+
*/
|
|
195
|
+
function gatherRubyTestFrameworkResult(cwd) {
|
|
196
|
+
const manifests = ['Gemfile', 'Gemfile.lock'];
|
|
197
|
+
let combined = '';
|
|
198
|
+
for (const rel of manifests) {
|
|
199
|
+
if (!(0, runner_1.fileExists)(cwd, rel))
|
|
200
|
+
continue;
|
|
201
|
+
try {
|
|
202
|
+
combined += fs.readFileSync(path.join(cwd, rel), 'utf-8') + '\n';
|
|
203
|
+
}
|
|
204
|
+
catch {
|
|
205
|
+
/* ignore unreadable */
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (combined) {
|
|
209
|
+
if (/\brspec(?:-rails)?\b/.test(combined)) {
|
|
210
|
+
return { schemaVersion: 1, tool: 'ruby', name: 'rspec' };
|
|
211
|
+
}
|
|
212
|
+
if (/\bminitest\b/.test(combined)) {
|
|
213
|
+
return { schemaVersion: 1, tool: 'ruby', name: 'minitest' };
|
|
214
|
+
}
|
|
215
|
+
if (/\btest-unit\b/.test(combined)) {
|
|
216
|
+
return { schemaVersion: 1, tool: 'ruby', name: 'test-unit' };
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// Glob-count fallback: no Gemfile (or Gemfile mentions no known runner).
|
|
220
|
+
// Run two cheap finds and pick the framework whose convention dominates.
|
|
221
|
+
const excludes = (0, exclusions_1.getFindExcludeFlags)(cwd);
|
|
222
|
+
const specCount = (0, runner_1.run)(`find . -type f -name "*_spec.rb" ${excludes} 2>/dev/null | wc -l`, cwd);
|
|
223
|
+
const testCount = (0, runner_1.run)(`find . -type f \\( -name "*_test.rb" -o -name "test_*.rb" \\) ${excludes} 2>/dev/null | wc -l`, cwd);
|
|
224
|
+
const specs = parseInt(specCount, 10) || 0;
|
|
225
|
+
const tests = parseInt(testCount, 10) || 0;
|
|
226
|
+
if (specs === 0 && tests === 0)
|
|
227
|
+
return null;
|
|
228
|
+
return {
|
|
229
|
+
schemaVersion: 1,
|
|
230
|
+
tool: 'ruby',
|
|
231
|
+
name: specs >= tests ? 'rspec' : 'minitest',
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
const rubyTestFrameworkProvider = {
|
|
235
|
+
source: 'ruby',
|
|
236
|
+
async gather(cwd) {
|
|
237
|
+
return gatherRubyTestFrameworkResult(cwd);
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
// ─── Lint (rubocop --format json) ───────────────────────────────────────────
|
|
241
|
+
/**
|
|
242
|
+
* Map RuboCop's severity strings to dxkit's four-tier scheme. RuboCop
|
|
243
|
+
* canonically emits 5 severities (see `RuboCop::Cop::Severity::CODES`
|
|
244
|
+
* in the upstream source — `lib/rubocop/cop/severity.rb`):
|
|
245
|
+
*
|
|
246
|
+
* - `convention` → low (style + naming — the bulk of findings)
|
|
247
|
+
* - `refactor` → low (complexity hints; Metrics/* cops)
|
|
248
|
+
* - `warning` → medium (Lint/* cops — actual code-quality risk)
|
|
249
|
+
* - `error` → high (real defects; rare in default config)
|
|
250
|
+
* - `fatal` → critical (rubocop-internal failure or syntax error)
|
|
251
|
+
*
|
|
252
|
+
* Defensive `'low'` default for unknown severities — matches the
|
|
253
|
+
* mapDetektSeverity / mapRuffSeverity contract: never silently drop a
|
|
254
|
+
* finding, even if rubocop adds a new tier we don't recognize yet.
|
|
255
|
+
*
|
|
256
|
+
* Exported for unit tests.
|
|
257
|
+
*/
|
|
258
|
+
function mapRubocopSeverity(severity) {
|
|
259
|
+
if (typeof severity !== 'string')
|
|
260
|
+
return 'low';
|
|
261
|
+
switch (severity.toLowerCase()) {
|
|
262
|
+
case 'fatal':
|
|
263
|
+
return 'critical';
|
|
264
|
+
case 'error':
|
|
265
|
+
return 'high';
|
|
266
|
+
case 'warning':
|
|
267
|
+
return 'medium';
|
|
268
|
+
case 'convention':
|
|
269
|
+
case 'refactor':
|
|
270
|
+
return 'low';
|
|
271
|
+
default:
|
|
272
|
+
return 'low';
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Pure parser for RuboCop's JSON output (rubocop --format json). The
|
|
277
|
+
* shape is fixed per the upstream `RuboCop::Formatter::JSONFormatter`
|
|
278
|
+
* contract — `metadata` + `files[*].offenses[*]` + `summary`. We only
|
|
279
|
+
* need the offenses; metadata + summary are surface for future
|
|
280
|
+
* enrichment (per-file attribution, top-N rules) but not needed for
|
|
281
|
+
* the dxkit lint envelope which carries SeverityCounts only.
|
|
282
|
+
*
|
|
283
|
+
* Returns zero counts on malformed input rather than throwing —
|
|
284
|
+
* matches mapDetektSeverity / parseEslintFinal conventions. The
|
|
285
|
+
* gather function distinguishes "rubocop ran fine, found nothing"
|
|
286
|
+
* from "rubocop missing / parse error" via LintGatherOutcome's
|
|
287
|
+
* kind field.
|
|
288
|
+
*
|
|
289
|
+
* Exported for unit tests; consumed by `gatherRubyLintResult`.
|
|
290
|
+
*/
|
|
291
|
+
function parseRubocopOutput(raw) {
|
|
292
|
+
const counts = { critical: 0, high: 0, medium: 0, low: 0 };
|
|
293
|
+
let data;
|
|
294
|
+
try {
|
|
295
|
+
data = JSON.parse(raw);
|
|
296
|
+
}
|
|
297
|
+
catch {
|
|
298
|
+
return counts;
|
|
299
|
+
}
|
|
300
|
+
for (const file of data.files ?? []) {
|
|
301
|
+
for (const offense of file.offenses ?? []) {
|
|
302
|
+
counts[mapRubocopSeverity(offense.severity)]++;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
return counts;
|
|
306
|
+
}
|
|
307
|
+
/**
|
|
308
|
+
* Single source of truth for the ruby pack's lint gathering. Consumed
|
|
309
|
+
* by `rubyLintProvider` (capability dispatcher).
|
|
310
|
+
*
|
|
311
|
+
* RuboCop is invoked with `--format json` so we always get a
|
|
312
|
+
* machine-readable payload (the default formatter is human-text).
|
|
313
|
+
* Exit code: rubocop exits 1 when offenses are found, 0 when clean.
|
|
314
|
+
* We tolerate any exit code (rubocop writes valid JSON to stdout
|
|
315
|
+
* regardless) and rely on parseRubocopOutput's empty-on-malformed
|
|
316
|
+
* contract.
|
|
317
|
+
*/
|
|
318
|
+
function gatherRubyLintResult(cwd) {
|
|
319
|
+
const rubocop = (0, tool_registry_1.findTool)(tool_registry_1.TOOL_DEFS.rubocop, cwd);
|
|
320
|
+
if (!rubocop.available || !rubocop.path) {
|
|
321
|
+
return { kind: 'unavailable', reason: 'not installed' };
|
|
322
|
+
}
|
|
323
|
+
const raw = (0, runner_1.run)(`${rubocop.path} --format json . 2>/dev/null`, cwd, 120000);
|
|
324
|
+
if (!raw) {
|
|
325
|
+
return { kind: 'unavailable', reason: 'no rubocop output' };
|
|
326
|
+
}
|
|
327
|
+
const counts = parseRubocopOutput(raw);
|
|
328
|
+
const envelope = { schemaVersion: 1, tool: 'rubocop', counts };
|
|
329
|
+
return { kind: 'success', envelope };
|
|
330
|
+
}
|
|
331
|
+
const rubyLintProvider = {
|
|
332
|
+
source: 'ruby',
|
|
333
|
+
async gather(cwd) {
|
|
334
|
+
const outcome = gatherRubyLintResult(cwd);
|
|
335
|
+
return outcome.kind === 'success' ? outcome.envelope : null;
|
|
336
|
+
},
|
|
337
|
+
};
|
|
338
|
+
/**
|
|
339
|
+
* Pure parser for SimpleCov `.resultset.json`. Returns null when the
|
|
340
|
+
* input has no parseable suites (empty file, missing `coverage` key,
|
|
341
|
+
* or malformed JSON) — distinct from "0% coverage" (where suites
|
|
342
|
+
* exist with zero hits).
|
|
343
|
+
*
|
|
344
|
+
* Exported for unit tests; consumed by `gatherSimpleCovCoverageResult`.
|
|
345
|
+
*/
|
|
346
|
+
function parseSimpleCovResultset(raw, sourceFile, cwd) {
|
|
347
|
+
let data;
|
|
348
|
+
try {
|
|
349
|
+
data = JSON.parse(raw);
|
|
350
|
+
}
|
|
351
|
+
catch {
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
// Per-file line arrays unioned across suites (max per index).
|
|
355
|
+
const merged = new Map();
|
|
356
|
+
for (const suite of Object.values(data)) {
|
|
357
|
+
const cov = suite?.coverage;
|
|
358
|
+
if (!cov || typeof cov !== 'object')
|
|
359
|
+
continue;
|
|
360
|
+
for (const [absPath, entry] of Object.entries(cov)) {
|
|
361
|
+
const lines = entry?.lines;
|
|
362
|
+
if (!Array.isArray(lines))
|
|
363
|
+
continue;
|
|
364
|
+
const existing = merged.get(absPath);
|
|
365
|
+
if (!existing) {
|
|
366
|
+
merged.set(absPath, lines.slice());
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
// Union: per index, keep max(existing, new). null stays null only if
|
|
370
|
+
// both are null; any int wins over null; max int wins between two ints.
|
|
371
|
+
const len = Math.max(existing.length, lines.length);
|
|
372
|
+
const out = new Array(len);
|
|
373
|
+
for (let i = 0; i < len; i++) {
|
|
374
|
+
const a = existing[i] ?? null;
|
|
375
|
+
const b = lines[i] ?? null;
|
|
376
|
+
if (a === null && b === null)
|
|
377
|
+
out[i] = null;
|
|
378
|
+
else if (a === null)
|
|
379
|
+
out[i] = b;
|
|
380
|
+
else if (b === null)
|
|
381
|
+
out[i] = a;
|
|
382
|
+
else
|
|
383
|
+
out[i] = Math.max(a, b);
|
|
384
|
+
}
|
|
385
|
+
merged.set(absPath, out);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
if (merged.size === 0)
|
|
389
|
+
return null;
|
|
390
|
+
const files = new Map();
|
|
391
|
+
let totalCovered = 0;
|
|
392
|
+
let totalExecutable = 0;
|
|
393
|
+
for (const [absPath, lines] of merged) {
|
|
394
|
+
let covered = 0;
|
|
395
|
+
let executable = 0;
|
|
396
|
+
for (const v of lines) {
|
|
397
|
+
if (v === null)
|
|
398
|
+
continue;
|
|
399
|
+
executable += 1;
|
|
400
|
+
if (v > 0)
|
|
401
|
+
covered += 1;
|
|
402
|
+
}
|
|
403
|
+
const rel = (0, coverage_1.toRelative)(absPath, cwd);
|
|
404
|
+
files.set(rel, {
|
|
405
|
+
path: rel,
|
|
406
|
+
covered,
|
|
407
|
+
total: executable,
|
|
408
|
+
pct: (0, coverage_1.round1)(executable > 0 ? (covered / executable) * 100 : 0),
|
|
409
|
+
});
|
|
410
|
+
totalCovered += covered;
|
|
411
|
+
totalExecutable += executable;
|
|
412
|
+
}
|
|
413
|
+
return {
|
|
414
|
+
source: 'simplecov',
|
|
415
|
+
sourceFile,
|
|
416
|
+
linePercent: (0, coverage_1.round1)(totalExecutable > 0 ? (totalCovered / totalExecutable) * 100 : 0),
|
|
417
|
+
files,
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
/**
|
|
421
|
+
* Probe SimpleCov's canonical artifact path. The default formatter
|
|
422
|
+
* writes `coverage/.resultset.json`; the simplecov-json gem writes
|
|
423
|
+
* `coverage/coverage.json` (less common). We probe the canonical
|
|
424
|
+
* path first — it ships with vanilla SimpleCov and is the most
|
|
425
|
+
* likely to exist.
|
|
426
|
+
*
|
|
427
|
+
* HTML-only fallback (no JSON, only `coverage/index.html`) is currently
|
|
428
|
+
* not parseable — the analyzer reports "no coverage" in that state,
|
|
429
|
+
* which is indistinguishable from "tool didn't run." Tracked as a
|
|
430
|
+
* Recipe v4 candidate (extend the coverage outcome enum to distinguish
|
|
431
|
+
* 'output-format-incompatible' from 'unavailable').
|
|
432
|
+
*/
|
|
433
|
+
function findSimpleCovResultset(cwd) {
|
|
434
|
+
const candidates = ['coverage/.resultset.json', 'coverage/coverage.json'];
|
|
435
|
+
for (const rel of candidates) {
|
|
436
|
+
if ((0, runner_1.fileExists)(cwd, rel))
|
|
437
|
+
return rel;
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Single source of truth for the ruby pack's coverage gathering.
|
|
443
|
+
* Consumed by `rubyCoverageProvider` (capability dispatcher).
|
|
444
|
+
*/
|
|
445
|
+
function gatherSimpleCovCoverageResult(cwd) {
|
|
446
|
+
const reportRel = findSimpleCovResultset(cwd);
|
|
447
|
+
if (!reportRel)
|
|
448
|
+
return null;
|
|
449
|
+
let raw;
|
|
450
|
+
try {
|
|
451
|
+
raw = fs.readFileSync(path.join(cwd, reportRel), 'utf-8');
|
|
452
|
+
}
|
|
453
|
+
catch {
|
|
454
|
+
return null;
|
|
455
|
+
}
|
|
456
|
+
const coverage = parseSimpleCovResultset(raw, reportRel, cwd);
|
|
457
|
+
if (!coverage)
|
|
458
|
+
return null;
|
|
459
|
+
return { schemaVersion: 1, tool: `coverage:${coverage.source}`, coverage };
|
|
460
|
+
}
|
|
461
|
+
const rubyCoverageProvider = {
|
|
462
|
+
source: 'ruby',
|
|
463
|
+
async gather(cwd) {
|
|
464
|
+
return gatherSimpleCovCoverageResult(cwd);
|
|
465
|
+
},
|
|
466
|
+
};
|
|
467
|
+
// ─── DepVulns (osv-scanner against Gemfile.lock) ────────────────────────────
|
|
468
|
+
//
|
|
469
|
+
// Parser + manifest discovery + tool invocation + CVSS resolution all
|
|
470
|
+
// live in `src/analyzers/tools/osv-scanner-deps.ts` — language-agnostic
|
|
471
|
+
// SSOT (CLAUDE.md rule #2). Same module powers kotlin/java's Maven
|
|
472
|
+
// scanning. ParseOsvScannerFindings is exported there for unit tests
|
|
473
|
+
// and is exercised by both Maven and RubyGems fixtures.
|
|
474
|
+
//
|
|
475
|
+
// bundler-audit alternative: deliberately NOT used. Its JSON output
|
|
476
|
+
// is unstable upstream (line-oriented text is the canonical format),
|
|
477
|
+
// and osv-scanner gives us SSOT consistency across Maven/RubyGems/PyPI
|
|
478
|
+
// + stable JSON + CVSS resolution + the same enrichment surface. If a
|
|
479
|
+
// future customer needs bundler-audit specifically (e.g. air-gapped
|
|
480
|
+
// env where osv.dev queries are unavailable), it can be added as a
|
|
481
|
+
// secondary tool without disturbing this primary path.
|
|
482
|
+
const RUBY_DEP_MANIFESTS = ['Gemfile.lock'];
|
|
483
|
+
const rubyDepVulnsProvider = {
|
|
484
|
+
source: 'ruby',
|
|
485
|
+
async gather(cwd) {
|
|
486
|
+
const outcome = await (0, osv_scanner_deps_1.gatherOsvScannerDepVulnsResult)(cwd, 'ruby', 'RubyGems', RUBY_DEP_MANIFESTS);
|
|
487
|
+
return outcome.kind === 'success' ? outcome.envelope : null;
|
|
488
|
+
},
|
|
489
|
+
};
|
|
490
|
+
// ─── Pack export ────────────────────────────────────────────────────────────
|
|
491
|
+
exports.ruby = {
|
|
492
|
+
id: 'ruby',
|
|
493
|
+
displayName: 'Ruby',
|
|
494
|
+
sourceExtensions: ['.rb'],
|
|
495
|
+
testFilePatterns: [
|
|
496
|
+
'*_spec.rb',
|
|
497
|
+
'*_test.rb',
|
|
498
|
+
'test_*.rb',
|
|
499
|
+
'spec/**/*_spec.rb',
|
|
500
|
+
'test/**/*_test.rb',
|
|
501
|
+
],
|
|
502
|
+
extraExcludes: ['vendor/bundle', '.bundle', 'coverage', 'tmp', 'log'],
|
|
503
|
+
detect: detectRuby,
|
|
504
|
+
tools: ['osv-scanner', 'rubocop', 'simplecov'],
|
|
505
|
+
semgrepRulesets: ['p/ruby'],
|
|
506
|
+
capabilities: {
|
|
507
|
+
imports: rubyImportsProvider,
|
|
508
|
+
testFramework: rubyTestFrameworkProvider,
|
|
509
|
+
coverage: rubyCoverageProvider,
|
|
510
|
+
lint: rubyLintProvider,
|
|
511
|
+
depVulns: rubyDepVulnsProvider,
|
|
512
|
+
},
|
|
513
|
+
mapLintSeverity: mapRubocopSeverity,
|
|
514
|
+
permissions: [
|
|
515
|
+
'Bash(bundle:*)',
|
|
516
|
+
'Bash(rake:*)',
|
|
517
|
+
'Bash(rspec:*)',
|
|
518
|
+
'Bash(rubocop:*)',
|
|
519
|
+
'Bash(ruby:*)',
|
|
520
|
+
],
|
|
521
|
+
ruleFile: 'ruby.md',
|
|
522
|
+
templateFiles: [],
|
|
523
|
+
cliBinaries: ['ruby', 'bundle'],
|
|
524
|
+
defaultVersion: '3.3.0',
|
|
525
|
+
projectYamlBlock: ({ config, enabled }) => [
|
|
526
|
+
` ruby:`,
|
|
527
|
+
` enabled: ${enabled}`,
|
|
528
|
+
` version: "${config.versions['ruby'] ?? '3.3.0'}"`,
|
|
529
|
+
].join('\n'),
|
|
530
|
+
};
|
|
531
|
+
//# sourceMappingURL=ruby.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ruby.js","sourceRoot":"","sources":["../../src/languages/ruby.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkFA,sDAoBC;AAyID,gDAeC;AAkCD,gDAcC;AA+ED,0DAuEC;AApcD,uCAAyB;AACzB,2CAA6B;AAE7B,0DAAmG;AACnG,8DAAoE;AACpE,0EAAqF;AACrF,sDAA4D;AAC5D,oEAAuE;AAavE,+EAA+E;AAE/E;;;;;GAKG;AACH,SAAS,wBAAwB,CAAC,GAAW,EAAE,QAAQ,GAAG,CAAC;IACzD,SAAS,MAAM,CAAC,GAAW,EAAE,KAAa;QACxC,IAAI,KAAK,GAAG,QAAQ;YAAE,OAAO,KAAK,CAAC;QACnC,IAAI,OAAoB,CAAC;QACzB,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;QACD,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,IAAI,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,EAAE,QAAQ,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxF,SAAS;YACX,CAAC;YACD,IAAI,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,CAAC;YACtD,IAAI,CAAC,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,EAAE,KAAK,GAAG,CAAC,CAAC;gBAAE,OAAO,IAAI,CAAC;QAChF,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,OAAO,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,wBAAwB,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;AAC1C,CAAC;AAED,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,SAAgB,qBAAqB,CAAC,OAAe;IACnD,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,sEAAsE;IACtE,wEAAwE;IACxE,4DAA4D;IAC5D,MAAM,QAAQ,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,EAAE,IAAI,CAAC,CAAC;IAEzD,MAAM,SAAS,GAAG,uDAAuD,CAAC;IAC1E,IAAI,CAAyB,CAAC;IAC9B,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,uEAAuE;IACvE,8CAA8C;IAC9C,MAAM,UAAU,GAAG,uDAAuD,CAAC;IAC3E,OAAO,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAChD,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;GASG;AACH,SAAS,uBAAuB,CAAC,GAAW;IAC1C,MAAM,QAAQ,GAAG,IAAA,gCAAmB,EAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,GAAG,GAAG,IAAA,YAAG,EAAC,+BAA+B,QAAQ,cAAc,EAAE,GAAG,CAAC,CAAC;IAC5E,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IAEtB,MAAM,SAAS,GAAG,IAAI,GAAG,EAAiC,CAAC;IAC3D,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACtB,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QACnC,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,CAAC;QAC1D,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,qBAAqB,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,IAAI,EAAE,cAAc;QACpB,gBAAgB,EAAE,CAAC,KAAK,CAAC;QACzB,SAAS;QACT,KAAK,EAAE,IAAI,GAAG,EAAE;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,mBAAmB,GAAsC;IAC7D,MAAM,EAAE,MAAM;IACd,KAAK,CAAC,MAAM,CAAC,GAAG;QACd,OAAO,uBAAuB,CAAC,GAAG,CAAC,CAAC;IACtC,CAAC;CACF,CAAC;AAEF,+EAA+E;AAE/E;;;;;;;;;;;;;;;;;;GAkBG;AACH,SAAS,6BAA6B,CAAC,GAAW;IAChD,MAAM,SAAS,GAAG,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC;IAC9C,IAAI,QAAQ,GAAG,EAAE,CAAC;IAClB,KAAK,MAAM,GAAG,IAAI,SAAS,EAAE,CAAC;QAC5B,IAAI,CAAC,IAAA,mBAAU,EAAC,GAAG,EAAE,GAAG,CAAC;YAAE,SAAS;QACpC,IAAI,CAAC;YACH,QAAQ,IAAI,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;QACnE,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IAED,IAAI,QAAQ,EAAE,CAAC;QACb,IAAI,sBAAsB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1C,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAC3D,CAAC;QACD,IAAI,cAAc,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YAClC,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC;QAC9D,CAAC;QACD,IAAI,eAAe,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC;YACnC,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAC/D,CAAC;IACH,CAAC;IAED,yEAAyE;IACzE,yEAAyE;IACzE,MAAM,QAAQ,GAAG,IAAA,gCAAmB,EAAC,GAAG,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAA,YAAG,EAAC,oCAAoC,QAAQ,sBAAsB,EAAE,GAAG,CAAC,CAAC;IAC/F,MAAM,SAAS,GAAG,IAAA,YAAG,EACnB,iEAAiE,QAAQ,sBAAsB,EAC/F,GAAG,CACJ,CAAC;IACF,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG,QAAQ,CAAC,SAAS,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IAC3C,IAAI,KAAK,KAAK,CAAC,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAC5C,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,IAAI,EAAE,MAAM;QACZ,IAAI,EAAE,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,UAAU;KAC5C,CAAC;AACJ,CAAC;AAED,MAAM,yBAAyB,GAA4C;IACzE,MAAM,EAAE,MAAM;IACd,KAAK,CAAC,MAAM,CAAC,GAAG;QACd,OAAO,6BAA6B,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC;CACF,CAAC;AAEF,+EAA+E;AAE/E;;;;;;;;;;;;;;;;GAgBG;AACH,SAAgB,kBAAkB,CAAC,QAAmC;IACpE,IAAI,OAAO,QAAQ,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC/C,QAAQ,QAAQ,CAAC,WAAW,EAAE,EAAE,CAAC;QAC/B,KAAK,OAAO;YACV,OAAO,UAAU,CAAC;QACpB,KAAK,OAAO;YACV,OAAO,MAAM,CAAC;QAChB,KAAK,SAAS;YACZ,OAAO,QAAQ,CAAC;QAClB,KAAK,YAAY,CAAC;QAClB,KAAK,UAAU;YACb,OAAO,KAAK,CAAC;QACf;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAkBD;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,kBAAkB,CAAC,GAAW;IAC5C,MAAM,MAAM,GAAmB,EAAE,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC3E,IAAI,IAAmB,CAAC;IACxB,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAkB,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;QACpC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,IAAI,EAAE,EAAE,CAAC;YAC1C,MAAM,CAAC,kBAAkB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;QACjD,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;;;;GAUG;AACH,SAAS,oBAAoB,CAAC,GAAW;IACvC,MAAM,OAAO,GAAG,IAAA,wBAAQ,EAAC,yBAAS,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACjD,IAAI,CAAC,OAAO,CAAC,SAAS,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QACxC,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1D,CAAC;IACD,MAAM,GAAG,GAAG,IAAA,YAAG,EAAC,GAAG,OAAO,CAAC,IAAI,8BAA8B,EAAE,GAAG,EAAE,MAAM,CAAC,CAAC;IAC5E,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9D,CAAC;IACD,MAAM,MAAM,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAe,EAAE,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAC3E,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC;AACvC,CAAC;AAED,MAAM,gBAAgB,GAAmC;IACvD,MAAM,EAAE,MAAM;IACd,KAAK,CAAC,MAAM,CAAC,GAAG;QACd,MAAM,OAAO,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;QAC1C,OAAO,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,CAAC;CACF,CAAC;AAsCF;;;;;;;GAOG;AACH,SAAgB,uBAAuB,CACrC,GAAW,EACX,UAAkB,EAClB,GAAW;IAEX,IAAI,IAAwB,CAAC;IAC7B,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IAED,8DAA8D;IAC9D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAgC,CAAC;IACvD,KAAK,MAAM,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QACxC,MAAM,GAAG,GAAG,KAAK,EAAE,QAAQ,CAAC;QAC5B,IAAI,CAAC,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ;YAAE,SAAS;QAC9C,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YACnD,MAAM,KAAK,GAAG,KAAK,EAAE,KAAK,CAAC;YAC3B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;gBAAE,SAAS;YACpC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrC,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACd,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;gBACnC,SAAS;YACX,CAAC;YACD,qEAAqE;YACrE,wEAAwE;YACxE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;YACpD,MAAM,GAAG,GAAyB,IAAI,KAAK,CAAC,GAAG,CAAC,CAAC;YACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC7B,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;gBAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;gBAC3B,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,IAAI;oBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;qBACvC,IAAI,CAAC,KAAK,IAAI;oBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;qBAC3B,IAAI,CAAC,KAAK,IAAI;oBAAE,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;;oBAC3B,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/B,CAAC;YACD,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEnC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC9C,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,KAAK,MAAM,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QACtC,IAAI,OAAO,GAAG,CAAC,CAAC;QAChB,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;YACtB,IAAI,CAAC,KAAK,IAAI;gBAAE,SAAS;YACzB,UAAU,IAAI,CAAC,CAAC;YAChB,IAAI,CAAC,GAAG,CAAC;gBAAE,OAAO,IAAI,CAAC,CAAC;QAC1B,CAAC;QACD,MAAM,GAAG,GAAG,IAAA,qBAAU,EAAC,OAAO,EAAE,GAAG,CAAC,CAAC;QACrC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE;YACb,IAAI,EAAE,GAAG;YACT,OAAO;YACP,KAAK,EAAE,UAAU;YACjB,GAAG,EAAE,IAAA,iBAAM,EAAC,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC/D,CAAC,CAAC;QACH,YAAY,IAAI,OAAO,CAAC;QACxB,eAAe,IAAI,UAAU,CAAC;IAChC,CAAC;IAED,OAAO;QACL,MAAM,EAAE,WAAW;QACnB,UAAU;QACV,WAAW,EAAE,IAAA,iBAAM,EAAC,eAAe,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,GAAG,eAAe,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACrF,KAAK;KACN,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,SAAS,sBAAsB,CAAC,GAAW;IACzC,MAAM,UAAU,GAAG,CAAC,0BAA0B,EAAE,wBAAwB,CAAC,CAAC;IAC1E,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,IAAI,IAAA,mBAAU,EAAC,GAAG,EAAE,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;IACvC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;GAGG;AACH,SAAS,6BAA6B,CAAC,GAAW;IAChD,MAAM,SAAS,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;IAC9C,IAAI,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAC5B,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,QAAQ,GAAG,uBAAuB,CAAC,GAAG,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC;IAC9D,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC;IAC3B,OAAO,EAAE,aAAa,EAAE,CAAC,EAAE,IAAI,EAAE,YAAY,QAAQ,CAAC,MAAM,EAAE,EAAE,QAAQ,EAAE,CAAC;AAC7E,CAAC;AAED,MAAM,oBAAoB,GAAuC;IAC/D,MAAM,EAAE,MAAM;IACd,KAAK,CAAC,MAAM,CAAC,GAAG;QACd,OAAO,6BAA6B,CAAC,GAAG,CAAC,CAAC;IAC5C,CAAC;CACF,CAAC;AAEF,+EAA+E;AAC/E,EAAE;AACF,sEAAsE;AACtE,wEAAwE;AACxE,mEAAmE;AACnE,qEAAqE;AACrE,wDAAwD;AACxD,EAAE;AACF,oEAAoE;AACpE,qEAAqE;AACrE,uEAAuE;AACvE,sEAAsE;AACtE,oEAAoE;AACpE,mEAAmE;AACnE,uDAAuD;AAEvD,MAAM,kBAAkB,GAAG,CAAC,cAAc,CAAC,CAAC;AAE5C,MAAM,oBAAoB,GAAsC;IAC9D,MAAM,EAAE,MAAM;IACd,KAAK,CAAC,MAAM,CAAC,GAAG;QACd,MAAM,OAAO,GAAG,MAAM,IAAA,iDAA8B,EAClD,GAAG,EACH,MAAM,EACN,UAAU,EACV,kBAAkB,CACnB,CAAC;QACF,OAAO,OAAO,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9D,CAAC;CACF,CAAC;AAEF,+EAA+E;AAElE,QAAA,IAAI,GAAoB;IACnC,EAAE,EAAE,MAAM;IACV,WAAW,EAAE,MAAM;IAEnB,gBAAgB,EAAE,CAAC,KAAK,CAAC;IAEzB,gBAAgB,EAAE;QAChB,WAAW;QACX,WAAW;QACX,WAAW;QACX,mBAAmB;QACnB,mBAAmB;KACpB;IAED,aAAa,EAAE,CAAC,eAAe,EAAE,SAAS,EAAE,UAAU,EAAE,KAAK,EAAE,KAAK,CAAC;IAErE,MAAM,EAAE,UAAU;IAElB,KAAK,EAAE,CAAC,aAAa,EAAE,SAAS,EAAE,WAAW,CAAC;IAE9C,eAAe,EAAE,CAAC,QAAQ,CAAC;IAE3B,YAAY,EAAE;QACZ,OAAO,EAAE,mBAAmB;QAC5B,aAAa,EAAE,yBAAyB;QACxC,QAAQ,EAAE,oBAAoB;QAC9B,IAAI,EAAE,gBAAgB;QACtB,QAAQ,EAAE,oBAAoB;KAC/B;IAED,eAAe,EAAE,kBAAkB;IAEnC,WAAW,EAAE;QACX,gBAAgB;QAChB,cAAc;QACd,eAAe;QACf,iBAAiB;QACjB,cAAc;KACf;IAED,QAAQ,EAAE,SAAS;IAEnB,aAAa,EAAE,EAAE;IAEjB,WAAW,EAAE,CAAC,MAAM,EAAE,QAAQ,CAAC;IAE/B,cAAc,EAAE,OAAO;IAEvB,gBAAgB,EAAE,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE,CACxC;QACE,SAAS;QACT,gBAAgB,OAAO,EAAE;QACzB,iBAAiB,MAAM,CAAC,QAAQ,CAAC,MAAsC,CAAC,IAAI,OAAO,GAAG;KACvF,CAAC,IAAI,CAAC,IAAI,CAAC;CACf,CAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* `src/languages/index.ts` LANGUAGES. The scaffolder
|
|
11
11
|
* (`scripts/scaffold-language.js`) automates both.
|
|
12
12
|
*/
|
|
13
|
-
export type LanguageId = 'typescript' | 'python' | 'go' | 'rust' | 'csharp' | 'kotlin' | 'java';
|
|
13
|
+
export type LanguageId = 'typescript' | 'python' | 'go' | 'rust' | 'csharp' | 'kotlin' | 'java' | 'ruby';
|
|
14
14
|
/** Tool required for analysis — consumed by devstack for devcontainer packaging. */
|
|
15
15
|
export interface ToolRequirement {
|
|
16
16
|
name: string;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,UAAU,GAClB,YAAY,GACZ,QAAQ,GACR,IAAI,GACJ,MAAM,GACN,QAAQ,GACR,QAAQ,GACR,MAAM,GACN,MAAM,CAAC;AAEX,oFAAoF;AACpF,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,WAAW,GAAG,UAAU,GAAG,UAAU,CAAC;CAC9C;AAED,MAAM,WAAW,aAAa;IAC5B;;;;;;;;;;;OAWG;IACH,SAAS,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IACvC,cAAc,EAAE;QACd,MAAM,EAAE,OAAO,CAAC;QAChB,QAAQ,EAAE,OAAO,CAAC;QAClB,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,KAAK,EAAE;QACL,MAAM,EAAE,OAAO,CAAC;QAChB,MAAM,EAAE,OAAO,CAAC;QAChB,SAAS,EAAE,OAAO,CAAC;QACnB,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B;;;;;;;;;;;;;OAaG;IACH,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,GAAG,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACvD,UAAU,CAAC,EAAE;QACX,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IACF,iFAAiF;IACjF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,eAAe,EAAE,CAAC;CAClC;AAED,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,iBAAiB,EAAE,MAAM,CAAC;IAC1B,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,MAAM,cAAc,GAAG,SAAS,GAAG,MAAM,CAAC;AAEhD,MAAM,WAAW,SAAS;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,cAAc,CAAC;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,cAAc,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,cAAc,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC1C;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,cAAc,CAAC;IACrB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,OAAO,CAAC;IACb,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC"}
|
package/package.json
CHANGED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Ruby — Claude rules
|
|
2
|
+
|
|
3
|
+
TODO(ruby): document conventions Claude should follow when writing
|
|
4
|
+
Ruby code in this project.
|
|
5
|
+
|
|
6
|
+
Topics that work well in this file:
|
|
7
|
+
- Preferred test framework / commands
|
|
8
|
+
- Lint rules and exceptions
|
|
9
|
+
- Module structure conventions
|
|
10
|
+
- Common idioms and anti-patterns
|
|
11
|
+
- Build / format commands
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import type { DepVulnFinding, DepVulnGatherOutcome, SeverityCounts } from '../../languages/capabilities/types';
|
|
2
|
-
/**
|
|
3
|
-
* Pure parser for osv-scanner v2.x JSON output, scoped to Maven
|
|
4
|
-
* findings only. Other ecosystems (npm, PyPI, Go) are filtered out so
|
|
5
|
-
* polyglot repos don't double-count: the typescript pack handles npm,
|
|
6
|
-
* the python pack handles PyPI, etc. JVM packs (kotlin, java) own
|
|
7
|
-
* Maven via this shared parser.
|
|
8
|
-
*
|
|
9
|
-
* Returns counts + findings + the raw OSV vuln records for downstream
|
|
10
|
-
* CVSS resolution. Exported for unit tests.
|
|
11
|
-
*/
|
|
12
|
-
export declare function parseOsvScannerMavenFindings(raw: string): {
|
|
13
|
-
counts: SeverityCounts;
|
|
14
|
-
findings: DepVulnFinding[];
|
|
15
|
-
vulnsForCvss: Array<{
|
|
16
|
-
primaryId: string;
|
|
17
|
-
embeddedCvss: number | null;
|
|
18
|
-
aliases: string[];
|
|
19
|
-
}>;
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Single source of truth for osv-scanner Maven dep-vuln gathering.
|
|
23
|
-
* Both kotlin and java packs delegate here.
|
|
24
|
-
*
|
|
25
|
-
* Manifest discovery order: lockfile > pom.xml > verification-metadata.
|
|
26
|
-
* We pass the manifest explicitly via --lockfile so osv-scanner doesn't
|
|
27
|
-
* fall back to its (unreliable) build.gradle.kts parser. Multi-module
|
|
28
|
-
* Android/Java projects with per-module lockfiles are not yet handled —
|
|
29
|
-
* first-module-found is the v1 behaviour.
|
|
30
|
-
*
|
|
31
|
-
* `scan source --lockfile <path>` is the v2.x form. JSON output to
|
|
32
|
-
* stdout. Exit code is non-zero when findings exist — we ignore the
|
|
33
|
-
* exit code and parse the JSON regardless (run() already swallows
|
|
34
|
-
* non-zero exits cleanly via execSync's catch).
|
|
35
|
-
*
|
|
36
|
-
* CVSS alias-fallback: osv-scanner ships CVSS vectors when present, but
|
|
37
|
-
* Maven advisories are inconsistent — some carry only
|
|
38
|
-
* `database_specific.severity` strings. resolveCvssScores looks up via
|
|
39
|
-
* CVE alias when the primary record lacks a vector.
|
|
40
|
-
*/
|
|
41
|
-
export declare function gatherOsvScannerMavenDepVulnsResult(cwd: string, source: string): Promise<DepVulnGatherOutcome>;
|
|
42
|
-
//# sourceMappingURL=osv-scanner-maven.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"osv-scanner-maven.d.ts","sourceRoot":"","sources":["../../../src/analyzers/tools/osv-scanner-maven.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EACV,cAAc,EACd,oBAAoB,EAEpB,cAAc,EACf,MAAM,oCAAoC,CAAC;AAiB5C;;;;;;;;;GASG;AACH,wBAAgB,4BAA4B,CAAC,GAAG,EAAE,MAAM,GAAG;IACzD,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,YAAY,EAAE,KAAK,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CAC5F,CAiEA;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,mCAAmC,CACvD,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,oBAAoB,CAAC,CA6C/B"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"osv-scanner-maven.js","sourceRoot":"","sources":["../../../src/analyzers/tools/osv-scanner-maven.ts"],"names":[],"mappings":"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"}
|