ghagga-core 2.3.0 → 2.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/format.d.ts.map +1 -1
- package/dist/format.js +23 -1
- package/dist/format.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/pipeline.d.ts.map +1 -1
- package/dist/pipeline.js +36 -19
- package/dist/pipeline.js.map +1 -1
- package/dist/tools/budget.d.ts +26 -0
- package/dist/tools/budget.d.ts.map +1 -0
- package/dist/tools/budget.js +78 -0
- package/dist/tools/budget.js.map +1 -0
- package/dist/tools/execution.d.ts +18 -0
- package/dist/tools/execution.d.ts.map +1 -0
- package/dist/tools/execution.js +82 -0
- package/dist/tools/execution.js.map +1 -0
- package/dist/tools/index.d.ts +16 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +20 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/orchestrator.d.ts +24 -0
- package/dist/tools/orchestrator.d.ts.map +1 -0
- package/dist/tools/orchestrator.js +127 -0
- package/dist/tools/orchestrator.js.map +1 -0
- package/dist/tools/plugins/bandit.d.ts +22 -0
- package/dist/tools/plugins/bandit.d.ts.map +1 -0
- package/dist/tools/plugins/bandit.js +79 -0
- package/dist/tools/plugins/bandit.js.map +1 -0
- package/dist/tools/plugins/biome.d.ts +22 -0
- package/dist/tools/plugins/biome.d.ts.map +1 -0
- package/dist/tools/plugins/biome.js +80 -0
- package/dist/tools/plugins/biome.js.map +1 -0
- package/dist/tools/plugins/clippy.d.ts +25 -0
- package/dist/tools/plugins/clippy.d.ts.map +1 -0
- package/dist/tools/plugins/clippy.js +95 -0
- package/dist/tools/plugins/clippy.js.map +1 -0
- package/dist/tools/plugins/cpd.d.ts +20 -0
- package/dist/tools/plugins/cpd.d.ts.map +1 -0
- package/dist/tools/plugins/cpd.js +111 -0
- package/dist/tools/plugins/cpd.js.map +1 -0
- package/dist/tools/plugins/gitleaks.d.ts +18 -0
- package/dist/tools/plugins/gitleaks.d.ts.map +1 -0
- package/dist/tools/plugins/gitleaks.js +81 -0
- package/dist/tools/plugins/gitleaks.js.map +1 -0
- package/dist/tools/plugins/golangci-lint.d.ts +27 -0
- package/dist/tools/plugins/golangci-lint.d.ts.map +1 -0
- package/dist/tools/plugins/golangci-lint.js +87 -0
- package/dist/tools/plugins/golangci-lint.js.map +1 -0
- package/dist/tools/plugins/hadolint.d.ts +22 -0
- package/dist/tools/plugins/hadolint.d.ts.map +1 -0
- package/dist/tools/plugins/hadolint.js +99 -0
- package/dist/tools/plugins/hadolint.js.map +1 -0
- package/dist/tools/plugins/index.d.ts +37 -0
- package/dist/tools/plugins/index.d.ts.map +1 -0
- package/dist/tools/plugins/index.js +93 -0
- package/dist/tools/plugins/index.js.map +1 -0
- package/dist/tools/plugins/lizard.d.ts +24 -0
- package/dist/tools/plugins/lizard.d.ts.map +1 -0
- package/dist/tools/plugins/lizard.js +83 -0
- package/dist/tools/plugins/lizard.js.map +1 -0
- package/dist/tools/plugins/markdownlint.d.ts +17 -0
- package/dist/tools/plugins/markdownlint.d.ts.map +1 -0
- package/dist/tools/plugins/markdownlint.js +70 -0
- package/dist/tools/plugins/markdownlint.js.map +1 -0
- package/dist/tools/plugins/pmd.d.ts +23 -0
- package/dist/tools/plugins/pmd.d.ts.map +1 -0
- package/dist/tools/plugins/pmd.js +108 -0
- package/dist/tools/plugins/pmd.js.map +1 -0
- package/dist/tools/plugins/psalm.d.ts +24 -0
- package/dist/tools/plugins/psalm.d.ts.map +1 -0
- package/dist/tools/plugins/psalm.js +85 -0
- package/dist/tools/plugins/psalm.js.map +1 -0
- package/dist/tools/plugins/ruff.d.ts +22 -0
- package/dist/tools/plugins/ruff.d.ts.map +1 -0
- package/dist/tools/plugins/ruff.js +80 -0
- package/dist/tools/plugins/ruff.js.map +1 -0
- package/dist/tools/plugins/semgrep.d.ts +23 -0
- package/dist/tools/plugins/semgrep.d.ts.map +1 -0
- package/dist/tools/plugins/semgrep.js +82 -0
- package/dist/tools/plugins/semgrep.js.map +1 -0
- package/dist/tools/plugins/shellcheck.d.ts +23 -0
- package/dist/tools/plugins/shellcheck.d.ts.map +1 -0
- package/dist/tools/plugins/shellcheck.js +87 -0
- package/dist/tools/plugins/shellcheck.js.map +1 -0
- package/dist/tools/plugins/trivy.d.ts +25 -0
- package/dist/tools/plugins/trivy.d.ts.map +1 -0
- package/dist/tools/plugins/trivy.js +108 -0
- package/dist/tools/plugins/trivy.js.map +1 -0
- package/dist/tools/registry.d.ts +37 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +61 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/resolve.d.ts +37 -0
- package/dist/tools/resolve.d.ts.map +1 -0
- package/dist/tools/resolve.js +67 -0
- package/dist/tools/resolve.js.map +1 -0
- package/dist/tools/runner.d.ts +15 -1
- package/dist/tools/runner.d.ts.map +1 -1
- package/dist/tools/runner.js +76 -6
- package/dist/tools/runner.js.map +1 -1
- package/dist/tools/types.d.ts +83 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +11 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/types.d.ts +15 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* markdownlint-cli2 plugin — Markdown documentation linting (always-on).
|
|
3
|
+
*
|
|
4
|
+
* Lints Markdown files for style and formatting issues.
|
|
5
|
+
* Only runs on *.md files; returns empty findings if none found.
|
|
6
|
+
*
|
|
7
|
+
* Uses ExecutionContext for DI instead of direct child_process.
|
|
8
|
+
*/
|
|
9
|
+
const MARKDOWNLINT_VERSION = '0.17.1';
|
|
10
|
+
/**
|
|
11
|
+
* Parse markdownlint-cli2 JSON output into ReviewFinding[].
|
|
12
|
+
* Exported for direct testing with fixture data.
|
|
13
|
+
*/
|
|
14
|
+
export function parseMarkdownlintOutput(raw, repoDir) {
|
|
15
|
+
if (raw.timedOut)
|
|
16
|
+
return [];
|
|
17
|
+
try {
|
|
18
|
+
const findings = JSON.parse(raw.stdout);
|
|
19
|
+
return findings.map((f) => {
|
|
20
|
+
const ruleName = f.ruleNames[0] ?? 'unknown';
|
|
21
|
+
const detail = f.errorDetail ? ` (${f.errorDetail})` : '';
|
|
22
|
+
return {
|
|
23
|
+
severity: 'info',
|
|
24
|
+
category: 'docs',
|
|
25
|
+
file: f.fileName.replace(`${repoDir}/`, ''),
|
|
26
|
+
line: f.lineNumber,
|
|
27
|
+
message: `${ruleName}: ${f.ruleDescription}${detail}`,
|
|
28
|
+
source: 'markdownlint',
|
|
29
|
+
};
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return [];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export const markdownlintPlugin = {
|
|
37
|
+
name: 'markdownlint',
|
|
38
|
+
displayName: 'markdownlint-cli2',
|
|
39
|
+
category: 'docs',
|
|
40
|
+
tier: 'always-on',
|
|
41
|
+
version: MARKDOWNLINT_VERSION,
|
|
42
|
+
outputFormat: 'json',
|
|
43
|
+
async install(ctx) {
|
|
44
|
+
try {
|
|
45
|
+
await ctx.exec('markdownlint-cli2', ['--help'], { timeoutMs: 10_000 });
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
catch {
|
|
49
|
+
ctx.log('info', 'markdownlint-cli2 not found, installing...');
|
|
50
|
+
}
|
|
51
|
+
await ctx.exec('npm', ['install', '-g', `markdownlint-cli2@${MARKDOWNLINT_VERSION}`], {
|
|
52
|
+
timeoutMs: 120_000,
|
|
53
|
+
});
|
|
54
|
+
await ctx.exec('markdownlint-cli2', ['--help'], { timeoutMs: 10_000 });
|
|
55
|
+
},
|
|
56
|
+
async run(ctx, _repoDir, files, timeout) {
|
|
57
|
+
// Filter to only Markdown files
|
|
58
|
+
const mdFiles = files.filter((f) => f.endsWith('.md'));
|
|
59
|
+
if (mdFiles.length === 0) {
|
|
60
|
+
// No Markdown files — return empty output
|
|
61
|
+
return { stdout: '[]', stderr: '', exitCode: 0, timedOut: false };
|
|
62
|
+
}
|
|
63
|
+
return ctx.exec('markdownlint-cli2', ['--config', '{}', ...mdFiles], {
|
|
64
|
+
timeoutMs: timeout,
|
|
65
|
+
allowExitCodes: [1], // markdownlint returns 1 when findings are present
|
|
66
|
+
});
|
|
67
|
+
},
|
|
68
|
+
parse: parseMarkdownlintOutput,
|
|
69
|
+
};
|
|
70
|
+
//# sourceMappingURL=markdownlint.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdownlint.js","sourceRoot":"","sources":["../../../src/tools/plugins/markdownlint.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PMD plugin — Java code quality analysis (auto-detect).
|
|
3
|
+
*
|
|
4
|
+
* Runs PMD static analysis with the quickstart ruleset.
|
|
5
|
+
* Shares installation with CPD (both use the PMD binary at /opt/pmd).
|
|
6
|
+
* Activates when Java or Kotlin files are detected.
|
|
7
|
+
*
|
|
8
|
+
* Uses ExecutionContext for DI instead of direct child_process.
|
|
9
|
+
*/
|
|
10
|
+
import type { FindingSeverity, ReviewFinding } from '../../types.js';
|
|
11
|
+
import type { RawToolOutput, ToolDefinition } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Map PMD violation priority to GHAGGA FindingSeverity.
|
|
14
|
+
* 1→critical, 2→high, 3→medium, 4→low, 5→info
|
|
15
|
+
*/
|
|
16
|
+
export declare function mapPmdPriority(priority: number): FindingSeverity;
|
|
17
|
+
/**
|
|
18
|
+
* Parse PMD JSON output into ReviewFinding[].
|
|
19
|
+
* Exported for direct testing with fixture data.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parsePmdOutput(raw: RawToolOutput, repoDir: string): ReviewFinding[];
|
|
22
|
+
export declare const pmdPlugin: ToolDefinition;
|
|
23
|
+
//# sourceMappingURL=pmd.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pmd.d.ts","sourceRoot":"","sources":["../../../src/tools/plugins/pmd.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAoB,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAMnF;;;GAGG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,CAehE;AAgBD;;;GAGG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAwBnF;AAED,eAAO,MAAM,SAAS,EAAE,cA+DvB,CAAC"}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PMD plugin — Java code quality analysis (auto-detect).
|
|
3
|
+
*
|
|
4
|
+
* Runs PMD static analysis with the quickstart ruleset.
|
|
5
|
+
* Shares installation with CPD (both use the PMD binary at /opt/pmd).
|
|
6
|
+
* Activates when Java or Kotlin files are detected.
|
|
7
|
+
*
|
|
8
|
+
* Uses ExecutionContext for DI instead of direct child_process.
|
|
9
|
+
*/
|
|
10
|
+
const PMD_VERSION = '7.8.0';
|
|
11
|
+
const PMD_HOME = '/opt/pmd';
|
|
12
|
+
const PMD_BIN = `${PMD_HOME}/bin/pmd`;
|
|
13
|
+
/**
|
|
14
|
+
* Map PMD violation priority to GHAGGA FindingSeverity.
|
|
15
|
+
* 1→critical, 2→high, 3→medium, 4→low, 5→info
|
|
16
|
+
*/
|
|
17
|
+
export function mapPmdPriority(priority) {
|
|
18
|
+
switch (priority) {
|
|
19
|
+
case 1:
|
|
20
|
+
return 'critical';
|
|
21
|
+
case 2:
|
|
22
|
+
return 'high';
|
|
23
|
+
case 3:
|
|
24
|
+
return 'medium';
|
|
25
|
+
case 4:
|
|
26
|
+
return 'low';
|
|
27
|
+
case 5:
|
|
28
|
+
return 'info';
|
|
29
|
+
default:
|
|
30
|
+
return 'low';
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Parse PMD JSON output into ReviewFinding[].
|
|
35
|
+
* Exported for direct testing with fixture data.
|
|
36
|
+
*/
|
|
37
|
+
export function parsePmdOutput(raw, repoDir) {
|
|
38
|
+
if (raw.timedOut)
|
|
39
|
+
return [];
|
|
40
|
+
try {
|
|
41
|
+
const result = JSON.parse(raw.stdout);
|
|
42
|
+
const findings = [];
|
|
43
|
+
for (const file of result.files ?? []) {
|
|
44
|
+
for (const violation of file.violations) {
|
|
45
|
+
findings.push({
|
|
46
|
+
severity: mapPmdPriority(violation.priority),
|
|
47
|
+
category: 'quality',
|
|
48
|
+
file: file.filename.replace(`${repoDir}/`, ''),
|
|
49
|
+
line: violation.beginline,
|
|
50
|
+
message: `[${violation.rule}] ${violation.description}`,
|
|
51
|
+
source: 'pmd',
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return findings;
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
export const pmdPlugin = {
|
|
62
|
+
name: 'pmd',
|
|
63
|
+
displayName: 'PMD',
|
|
64
|
+
category: 'quality',
|
|
65
|
+
tier: 'auto-detect',
|
|
66
|
+
version: PMD_VERSION,
|
|
67
|
+
outputFormat: 'json',
|
|
68
|
+
detect(files) {
|
|
69
|
+
return files.some((f) => /\.(java|kt)$/.test(f));
|
|
70
|
+
},
|
|
71
|
+
async install(ctx) {
|
|
72
|
+
// PMD may already be installed via CPD plugin (shared binary)
|
|
73
|
+
try {
|
|
74
|
+
await ctx.exec(PMD_BIN, ['--version'], { timeoutMs: 10_000 });
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
ctx.log('info', 'PMD not found, installing (shared with CPD)...');
|
|
79
|
+
}
|
|
80
|
+
const cached = await ctx.cacheRestore('cpd', [PMD_HOME]);
|
|
81
|
+
if (cached) {
|
|
82
|
+
try {
|
|
83
|
+
await ctx.exec(PMD_BIN, ['--version'], { timeoutMs: 10_000 });
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
ctx.log('warn', 'PMD cache restored but binary not functional, reinstalling');
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
await ctx.exec('bash', [
|
|
91
|
+
'-c',
|
|
92
|
+
`curl -sL "https://github.com/pmd/pmd/releases/download/pmd_releases%2F${PMD_VERSION}/pmd-dist-${PMD_VERSION}-bin.zip" -o /tmp/pmd.zip && ` +
|
|
93
|
+
`unzip -q /tmp/pmd.zip -d /opt && ` +
|
|
94
|
+
`mv /opt/pmd-bin-${PMD_VERSION} ${PMD_HOME} && ` +
|
|
95
|
+
`rm -f /tmp/pmd.zip`,
|
|
96
|
+
], { timeoutMs: 120_000 });
|
|
97
|
+
await ctx.exec(PMD_BIN, ['--version'], { timeoutMs: 10_000 });
|
|
98
|
+
await ctx.cacheSave('cpd', [PMD_HOME]);
|
|
99
|
+
},
|
|
100
|
+
async run(ctx, repoDir, _files, timeout) {
|
|
101
|
+
return ctx.exec(PMD_BIN, ['check', '--format', 'json', '--dir', repoDir, '--rulesets', 'rulesets/java/quickstart.xml'], {
|
|
102
|
+
timeoutMs: timeout,
|
|
103
|
+
allowExitCodes: [4], // PMD returns 4 when violations are found
|
|
104
|
+
});
|
|
105
|
+
},
|
|
106
|
+
parse: parsePmdOutput,
|
|
107
|
+
};
|
|
108
|
+
//# sourceMappingURL=pmd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pmd.js","sourceRoot":"","sources":["../../../src/tools/plugins/pmd.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Psalm plugin — PHP static analysis (auto-detect).
|
|
3
|
+
*
|
|
4
|
+
* Runs Psalm for type checking and security analysis on PHP codebases.
|
|
5
|
+
* Activates when PHP files or composer.json is detected.
|
|
6
|
+
* Maps taint-related findings to critical severity.
|
|
7
|
+
*
|
|
8
|
+
* Uses ExecutionContext for DI instead of direct child_process.
|
|
9
|
+
*/
|
|
10
|
+
import type { FindingSeverity, ReviewFinding } from '../../types.js';
|
|
11
|
+
import type { RawToolOutput, ToolDefinition } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Map Psalm finding to GHAGGA FindingSeverity.
|
|
14
|
+
* Taint findings (e.g., TaintedHtml, TaintedSql) → critical.
|
|
15
|
+
* error → high, info → low, default → medium
|
|
16
|
+
*/
|
|
17
|
+
export declare function mapPsalmSeverity(severity: string, type: string): FindingSeverity;
|
|
18
|
+
/**
|
|
19
|
+
* Parse Psalm JSON output into ReviewFinding[].
|
|
20
|
+
* Exported for direct testing with fixture data.
|
|
21
|
+
*/
|
|
22
|
+
export declare function parsePsalmOutput(raw: RawToolOutput, repoDir: string): ReviewFinding[];
|
|
23
|
+
export declare const psalmPlugin: ToolDefinition;
|
|
24
|
+
//# sourceMappingURL=psalm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"psalm.d.ts","sourceRoot":"","sources":["../../../src/tools/plugins/psalm.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAoB,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAInF;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,eAAe,CAYhF;AAYD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAiBrF;AAED,eAAO,MAAM,WAAW,EAAE,cA0CzB,CAAC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Psalm plugin — PHP static analysis (auto-detect).
|
|
3
|
+
*
|
|
4
|
+
* Runs Psalm for type checking and security analysis on PHP codebases.
|
|
5
|
+
* Activates when PHP files or composer.json is detected.
|
|
6
|
+
* Maps taint-related findings to critical severity.
|
|
7
|
+
*
|
|
8
|
+
* Uses ExecutionContext for DI instead of direct child_process.
|
|
9
|
+
*/
|
|
10
|
+
const PSALM_VERSION = '6.5.1';
|
|
11
|
+
/**
|
|
12
|
+
* Map Psalm finding to GHAGGA FindingSeverity.
|
|
13
|
+
* Taint findings (e.g., TaintedHtml, TaintedSql) → critical.
|
|
14
|
+
* error → high, info → low, default → medium
|
|
15
|
+
*/
|
|
16
|
+
export function mapPsalmSeverity(severity, type) {
|
|
17
|
+
// Taint findings are always critical regardless of severity
|
|
18
|
+
if (type.toLowerCase().startsWith('tainted'))
|
|
19
|
+
return 'critical';
|
|
20
|
+
switch (severity.toLowerCase()) {
|
|
21
|
+
case 'error':
|
|
22
|
+
return 'high';
|
|
23
|
+
case 'info':
|
|
24
|
+
return 'low';
|
|
25
|
+
default:
|
|
26
|
+
return 'medium';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Parse Psalm JSON output into ReviewFinding[].
|
|
31
|
+
* Exported for direct testing with fixture data.
|
|
32
|
+
*/
|
|
33
|
+
export function parsePsalmOutput(raw, repoDir) {
|
|
34
|
+
if (raw.timedOut)
|
|
35
|
+
return [];
|
|
36
|
+
try {
|
|
37
|
+
const findings = JSON.parse(raw.stdout);
|
|
38
|
+
return findings.map((f) => ({
|
|
39
|
+
severity: mapPsalmSeverity(f.severity, f.type),
|
|
40
|
+
category: 'quality',
|
|
41
|
+
file: f.file_path.replace(`${repoDir}/`, ''),
|
|
42
|
+
line: f.line_from,
|
|
43
|
+
message: `[${f.type}] ${f.message}`,
|
|
44
|
+
source: 'psalm',
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return [];
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export const psalmPlugin = {
|
|
52
|
+
name: 'psalm',
|
|
53
|
+
displayName: 'Psalm',
|
|
54
|
+
category: 'quality',
|
|
55
|
+
tier: 'auto-detect',
|
|
56
|
+
version: PSALM_VERSION,
|
|
57
|
+
outputFormat: 'json',
|
|
58
|
+
detect(files) {
|
|
59
|
+
return files.some((f) => f.endsWith('.php') || f === 'composer.json');
|
|
60
|
+
},
|
|
61
|
+
async install(ctx) {
|
|
62
|
+
// Check if Psalm PHAR is already available
|
|
63
|
+
try {
|
|
64
|
+
await ctx.exec('psalm', ['--version'], { timeoutMs: 10_000 });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
catch {
|
|
68
|
+
ctx.log('info', 'Psalm not found, installing...');
|
|
69
|
+
}
|
|
70
|
+
// Install via Composer global
|
|
71
|
+
await ctx.exec('composer', ['global', 'require', `vimeo/psalm:${PSALM_VERSION}`], {
|
|
72
|
+
timeoutMs: 120_000,
|
|
73
|
+
});
|
|
74
|
+
await ctx.exec('psalm', ['--version'], { timeoutMs: 10_000 });
|
|
75
|
+
},
|
|
76
|
+
async run(ctx, repoDir, _files, timeout) {
|
|
77
|
+
return ctx.exec('psalm', ['--output-format=json', '--no-cache'], {
|
|
78
|
+
timeoutMs: timeout,
|
|
79
|
+
cwd: repoDir,
|
|
80
|
+
allowExitCodes: [1, 2], // psalm returns 1 for info, 2 for errors
|
|
81
|
+
});
|
|
82
|
+
},
|
|
83
|
+
parse: parsePsalmOutput,
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=psalm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"psalm.js","sourceRoot":"","sources":["../../../src/tools/plugins/psalm.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ruff plugin — Python linting (auto-detect).
|
|
3
|
+
*
|
|
4
|
+
* Fast Python linter. Activates when Python files are detected.
|
|
5
|
+
* Maps ruff rule code prefixes to severity levels.
|
|
6
|
+
*
|
|
7
|
+
* Uses ExecutionContext for DI instead of direct child_process.
|
|
8
|
+
*/
|
|
9
|
+
import type { FindingSeverity, ReviewFinding } from '../../types.js';
|
|
10
|
+
import type { RawToolOutput, ToolDefinition } from '../types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Map Ruff code prefix to GHAGGA FindingSeverity.
|
|
13
|
+
* F (Pyflakes) → high, E (errors) → medium, W (warnings) → low, others → low
|
|
14
|
+
*/
|
|
15
|
+
export declare function mapRuffSeverity(code: string): FindingSeverity;
|
|
16
|
+
/**
|
|
17
|
+
* Parse Ruff JSON output into ReviewFinding[].
|
|
18
|
+
* Exported for direct testing with fixture data.
|
|
19
|
+
*/
|
|
20
|
+
export declare function parseRuffOutput(raw: RawToolOutput, repoDir: string): ReviewFinding[];
|
|
21
|
+
export declare const ruffPlugin: ToolDefinition;
|
|
22
|
+
//# sourceMappingURL=ruff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ruff.d.ts","sourceRoot":"","sources":["../../../src/tools/plugins/ruff.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAoB,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAInF;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CAY7D;AAWD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAiBpF;AAED,eAAO,MAAM,UAAU,EAAE,cAuCxB,CAAC"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ruff plugin — Python linting (auto-detect).
|
|
3
|
+
*
|
|
4
|
+
* Fast Python linter. Activates when Python files are detected.
|
|
5
|
+
* Maps ruff rule code prefixes to severity levels.
|
|
6
|
+
*
|
|
7
|
+
* Uses ExecutionContext for DI instead of direct child_process.
|
|
8
|
+
*/
|
|
9
|
+
const RUFF_VERSION = '0.9.7';
|
|
10
|
+
/**
|
|
11
|
+
* Map Ruff code prefix to GHAGGA FindingSeverity.
|
|
12
|
+
* F (Pyflakes) → high, E (errors) → medium, W (warnings) → low, others → low
|
|
13
|
+
*/
|
|
14
|
+
export function mapRuffSeverity(code) {
|
|
15
|
+
const prefix = code.charAt(0).toUpperCase();
|
|
16
|
+
switch (prefix) {
|
|
17
|
+
case 'F':
|
|
18
|
+
return 'high';
|
|
19
|
+
case 'E':
|
|
20
|
+
return 'medium';
|
|
21
|
+
case 'W':
|
|
22
|
+
return 'low';
|
|
23
|
+
default:
|
|
24
|
+
return 'low';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse Ruff JSON output into ReviewFinding[].
|
|
29
|
+
* Exported for direct testing with fixture data.
|
|
30
|
+
*/
|
|
31
|
+
export function parseRuffOutput(raw, repoDir) {
|
|
32
|
+
if (raw.timedOut)
|
|
33
|
+
return [];
|
|
34
|
+
try {
|
|
35
|
+
const findings = JSON.parse(raw.stdout);
|
|
36
|
+
return findings.map((f) => ({
|
|
37
|
+
severity: mapRuffSeverity(f.code),
|
|
38
|
+
category: 'quality',
|
|
39
|
+
file: f.filename.replace(`${repoDir}/`, ''),
|
|
40
|
+
line: f.location.row,
|
|
41
|
+
message: `${f.code}: ${f.message}`,
|
|
42
|
+
source: 'ruff',
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export const ruffPlugin = {
|
|
50
|
+
name: 'ruff',
|
|
51
|
+
displayName: 'Ruff',
|
|
52
|
+
category: 'quality',
|
|
53
|
+
tier: 'auto-detect',
|
|
54
|
+
version: RUFF_VERSION,
|
|
55
|
+
outputFormat: 'json',
|
|
56
|
+
detect(files) {
|
|
57
|
+
return files.some((f) => f.endsWith('.py') || f.endsWith('.pyi'));
|
|
58
|
+
},
|
|
59
|
+
async install(ctx) {
|
|
60
|
+
try {
|
|
61
|
+
await ctx.exec('ruff', ['--version'], { timeoutMs: 10_000 });
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
ctx.log('info', 'Ruff not found, installing...');
|
|
66
|
+
}
|
|
67
|
+
await ctx.exec('pip', ['install', '--quiet', `ruff==${RUFF_VERSION}`], {
|
|
68
|
+
timeoutMs: 120_000,
|
|
69
|
+
});
|
|
70
|
+
await ctx.exec('ruff', ['--version'], { timeoutMs: 10_000 });
|
|
71
|
+
},
|
|
72
|
+
async run(ctx, repoDir, _files, timeout) {
|
|
73
|
+
return ctx.exec('ruff', ['check', '--output-format', 'json', repoDir], {
|
|
74
|
+
timeoutMs: timeout,
|
|
75
|
+
allowExitCodes: [1], // ruff returns 1 when findings are present
|
|
76
|
+
});
|
|
77
|
+
},
|
|
78
|
+
parse: parseRuffOutput,
|
|
79
|
+
};
|
|
80
|
+
//# sourceMappingURL=ruff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ruff.js","sourceRoot":"","sources":["../../../src/tools/plugins/ruff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semgrep plugin — security analysis (always-on).
|
|
3
|
+
*
|
|
4
|
+
* Adapted from:
|
|
5
|
+
* - packages/core/src/tools/semgrep.ts (parsing logic)
|
|
6
|
+
* - apps/action/src/tools/semgrep.ts (install/run flow)
|
|
7
|
+
*
|
|
8
|
+
* Uses ExecutionContext for DI instead of direct child_process.
|
|
9
|
+
*/
|
|
10
|
+
import type { FindingSeverity, ReviewFinding } from '../../types.js';
|
|
11
|
+
import type { RawToolOutput, ToolDefinition } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Map Semgrep severity to GHAGGA FindingSeverity.
|
|
14
|
+
* ERROR -> high, WARNING -> medium, INFO -> info, default -> low
|
|
15
|
+
*/
|
|
16
|
+
export declare function mapSemgrepSeverity(semgrepSeverity: string): FindingSeverity;
|
|
17
|
+
/**
|
|
18
|
+
* Parse Semgrep JSON output into ReviewFinding[].
|
|
19
|
+
* Exported for direct testing with fixture data.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseSemgrepOutput(raw: RawToolOutput, repoDir: string): ReviewFinding[];
|
|
22
|
+
export declare const semgrepPlugin: ToolDefinition;
|
|
23
|
+
//# sourceMappingURL=semgrep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semgrep.d.ts","sourceRoot":"","sources":["../../../src/tools/plugins/semgrep.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAoB,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAInF;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,eAAe,EAAE,MAAM,GAAG,eAAe,CAW3E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAuBvF;AAED,eAAO,MAAM,aAAa,EAAE,cAwC3B,CAAC"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semgrep plugin — security analysis (always-on).
|
|
3
|
+
*
|
|
4
|
+
* Adapted from:
|
|
5
|
+
* - packages/core/src/tools/semgrep.ts (parsing logic)
|
|
6
|
+
* - apps/action/src/tools/semgrep.ts (install/run flow)
|
|
7
|
+
*
|
|
8
|
+
* Uses ExecutionContext for DI instead of direct child_process.
|
|
9
|
+
*/
|
|
10
|
+
const SEMGREP_VERSION = '1.90.0';
|
|
11
|
+
/**
|
|
12
|
+
* Map Semgrep severity to GHAGGA FindingSeverity.
|
|
13
|
+
* ERROR -> high, WARNING -> medium, INFO -> info, default -> low
|
|
14
|
+
*/
|
|
15
|
+
export function mapSemgrepSeverity(semgrepSeverity) {
|
|
16
|
+
switch (semgrepSeverity.toUpperCase()) {
|
|
17
|
+
case 'ERROR':
|
|
18
|
+
return 'high';
|
|
19
|
+
case 'WARNING':
|
|
20
|
+
return 'medium';
|
|
21
|
+
case 'INFO':
|
|
22
|
+
return 'info';
|
|
23
|
+
default:
|
|
24
|
+
return 'low';
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Parse Semgrep JSON output into ReviewFinding[].
|
|
29
|
+
* Exported for direct testing with fixture data.
|
|
30
|
+
*/
|
|
31
|
+
export function parseSemgrepOutput(raw, repoDir) {
|
|
32
|
+
if (raw.timedOut)
|
|
33
|
+
return [];
|
|
34
|
+
try {
|
|
35
|
+
const result = JSON.parse(raw.stdout);
|
|
36
|
+
return (result.results ?? []).map((r) => ({
|
|
37
|
+
severity: mapSemgrepSeverity(r.extra.severity),
|
|
38
|
+
category: 'security',
|
|
39
|
+
file: r.path.replace(`${repoDir}/`, ''),
|
|
40
|
+
line: r.start.line,
|
|
41
|
+
message: r.extra.message,
|
|
42
|
+
source: 'semgrep',
|
|
43
|
+
}));
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return [];
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export const semgrepPlugin = {
|
|
50
|
+
name: 'semgrep',
|
|
51
|
+
displayName: 'Semgrep',
|
|
52
|
+
category: 'security',
|
|
53
|
+
tier: 'always-on',
|
|
54
|
+
version: SEMGREP_VERSION,
|
|
55
|
+
outputFormat: 'json',
|
|
56
|
+
cachePaths: ['/usr/local/bin/semgrep'],
|
|
57
|
+
async install(ctx) {
|
|
58
|
+
const cached = await ctx.cacheRestore('semgrep', ['/usr/local/bin/semgrep']);
|
|
59
|
+
if (cached) {
|
|
60
|
+
try {
|
|
61
|
+
await ctx.exec('semgrep', ['--version'], { timeoutMs: 10_000 });
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
ctx.log('warn', 'Semgrep cache restored but binary not functional, reinstalling');
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
await ctx.exec('pip', ['install', '--quiet', `semgrep==${SEMGREP_VERSION}`], {
|
|
69
|
+
timeoutMs: 120_000,
|
|
70
|
+
});
|
|
71
|
+
await ctx.exec('semgrep', ['--version'], { timeoutMs: 10_000 });
|
|
72
|
+
await ctx.cacheSave('semgrep', ['/usr/local/bin/semgrep']);
|
|
73
|
+
},
|
|
74
|
+
async run(ctx, repoDir, _files, timeout) {
|
|
75
|
+
return ctx.exec('semgrep', ['--json', '--config', 'auto', '--quiet', repoDir], {
|
|
76
|
+
timeoutMs: timeout,
|
|
77
|
+
allowExitCodes: [1], // semgrep returns 1 when findings are present
|
|
78
|
+
});
|
|
79
|
+
},
|
|
80
|
+
parse: parseSemgrepOutput,
|
|
81
|
+
};
|
|
82
|
+
//# sourceMappingURL=semgrep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semgrep.js","sourceRoot":"","sources":["../../../src/tools/plugins/semgrep.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ShellCheck plugin — shell script linting (always-on).
|
|
3
|
+
*
|
|
4
|
+
* Lints shell scripts for common issues and portability problems.
|
|
5
|
+
* Only runs on *.sh and *.bash files; returns empty findings if none found.
|
|
6
|
+
*
|
|
7
|
+
* Pre-installed on GitHub Actions runners — install is a verification step.
|
|
8
|
+
* Uses ExecutionContext for DI instead of direct child_process.
|
|
9
|
+
*/
|
|
10
|
+
import type { FindingSeverity, ReviewFinding } from '../../types.js';
|
|
11
|
+
import type { RawToolOutput, ToolDefinition } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Map ShellCheck level to GHAGGA FindingSeverity.
|
|
14
|
+
* error→high, warning→medium, info→info, style→low
|
|
15
|
+
*/
|
|
16
|
+
export declare function mapShellCheckSeverity(level: string): FindingSeverity;
|
|
17
|
+
/**
|
|
18
|
+
* Parse ShellCheck JSON output into ReviewFinding[].
|
|
19
|
+
* Exported for direct testing with fixture data.
|
|
20
|
+
*/
|
|
21
|
+
export declare function parseShellCheckOutput(raw: RawToolOutput, repoDir: string): ReviewFinding[];
|
|
22
|
+
export declare const shellcheckPlugin: ToolDefinition;
|
|
23
|
+
//# sourceMappingURL=shellcheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shellcheck.d.ts","sourceRoot":"","sources":["../../../src/tools/plugins/shellcheck.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAoB,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAInF;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,GAAG,eAAe,CAapE;AAYD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,GAAG,aAAa,EAAE,CAiB1F;AAED,eAAO,MAAM,gBAAgB,EAAE,cAiD9B,CAAC"}
|