@ash-technologia/fathom 0.1.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/CHANGELOG.md +62 -0
- package/LICENSE +21 -0
- package/README.md +725 -0
- package/dist/analyzers/architecture/graph.d.ts +29 -0
- package/dist/analyzers/architecture/graph.d.ts.map +1 -0
- package/dist/analyzers/architecture/graph.js +347 -0
- package/dist/analyzers/architecture/graph.js.map +1 -0
- package/dist/analyzers/architecture/imports.d.ts +24 -0
- package/dist/analyzers/architecture/imports.d.ts.map +1 -0
- package/dist/analyzers/architecture/imports.js +155 -0
- package/dist/analyzers/architecture/imports.js.map +1 -0
- package/dist/analyzers/architecture/index.d.ts +13 -0
- package/dist/analyzers/architecture/index.d.ts.map +1 -0
- package/dist/analyzers/architecture/index.js +217 -0
- package/dist/analyzers/architecture/index.js.map +1 -0
- package/dist/analyzers/architecture/types.d.ts +65 -0
- package/dist/analyzers/architecture/types.d.ts.map +1 -0
- package/dist/analyzers/architecture/types.js +2 -0
- package/dist/analyzers/architecture/types.js.map +1 -0
- package/dist/analyzers/cicd/index.d.ts +11 -0
- package/dist/analyzers/cicd/index.d.ts.map +1 -0
- package/dist/analyzers/cicd/index.js +157 -0
- package/dist/analyzers/cicd/index.js.map +1 -0
- package/dist/analyzers/dependencies/index.d.ts +11 -0
- package/dist/analyzers/dependencies/index.d.ts.map +1 -0
- package/dist/analyzers/dependencies/index.js +403 -0
- package/dist/analyzers/dependencies/index.js.map +1 -0
- package/dist/analyzers/dependencies/lockfiles.d.ts +19 -0
- package/dist/analyzers/dependencies/lockfiles.d.ts.map +1 -0
- package/dist/analyzers/dependencies/lockfiles.js +172 -0
- package/dist/analyzers/dependencies/lockfiles.js.map +1 -0
- package/dist/analyzers/dependencies/online.d.ts +19 -0
- package/dist/analyzers/dependencies/online.d.ts.map +1 -0
- package/dist/analyzers/dependencies/online.js +116 -0
- package/dist/analyzers/dependencies/online.js.map +1 -0
- package/dist/analyzers/dependencies/types.d.ts +49 -0
- package/dist/analyzers/dependencies/types.d.ts.map +1 -0
- package/dist/analyzers/dependencies/types.js +2 -0
- package/dist/analyzers/dependencies/types.js.map +1 -0
- package/dist/analyzers/documentation/index.d.ts +11 -0
- package/dist/analyzers/documentation/index.d.ts.map +1 -0
- package/dist/analyzers/documentation/index.js +166 -0
- package/dist/analyzers/documentation/index.js.map +1 -0
- package/dist/analyzers/git/index.d.ts +11 -0
- package/dist/analyzers/git/index.d.ts.map +1 -0
- package/dist/analyzers/git/index.js +180 -0
- package/dist/analyzers/git/index.js.map +1 -0
- package/dist/analyzers/project/index.d.ts +11 -0
- package/dist/analyzers/project/index.d.ts.map +1 -0
- package/dist/analyzers/project/index.js +95 -0
- package/dist/analyzers/project/index.js.map +1 -0
- package/dist/analyzers/quality/index.d.ts +11 -0
- package/dist/analyzers/quality/index.d.ts.map +1 -0
- package/dist/analyzers/quality/index.js +198 -0
- package/dist/analyzers/quality/index.js.map +1 -0
- package/dist/analyzers/security/index.d.ts +11 -0
- package/dist/analyzers/security/index.d.ts.map +1 -0
- package/dist/analyzers/security/index.js +236 -0
- package/dist/analyzers/security/index.js.map +1 -0
- package/dist/analyzers/testing/index.d.ts +11 -0
- package/dist/analyzers/testing/index.d.ts.map +1 -0
- package/dist/analyzers/testing/index.js +134 -0
- package/dist/analyzers/testing/index.js.map +1 -0
- package/dist/baseline/baseline.d.ts +20 -0
- package/dist/baseline/baseline.d.ts.map +1 -0
- package/dist/baseline/baseline.js +134 -0
- package/dist/baseline/baseline.js.map +1 -0
- package/dist/baseline/compare.d.ts +14 -0
- package/dist/baseline/compare.d.ts.map +1 -0
- package/dist/baseline/compare.js +113 -0
- package/dist/baseline/compare.js.map +1 -0
- package/dist/baseline/types.d.ts +25 -0
- package/dist/baseline/types.d.ts.map +1 -0
- package/dist/baseline/types.js +2 -0
- package/dist/baseline/types.js.map +1 -0
- package/dist/cli/commands.d.ts +39 -0
- package/dist/cli/commands.d.ts.map +1 -0
- package/dist/cli/commands.js +277 -0
- package/dist/cli/commands.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +29 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/options.d.ts +55 -0
- package/dist/cli/options.d.ts.map +1 -0
- package/dist/cli/options.js +258 -0
- package/dist/cli/options.js.map +1 -0
- package/dist/core/analyzer.d.ts +33 -0
- package/dist/core/analyzer.d.ts.map +1 -0
- package/dist/core/analyzer.js +19 -0
- package/dist/core/analyzer.js.map +1 -0
- package/dist/core/context.d.ts +90 -0
- package/dist/core/context.d.ts.map +1 -0
- package/dist/core/context.js +159 -0
- package/dist/core/context.js.map +1 -0
- package/dist/core/errors.d.ts +74 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +109 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/findings.d.ts +59 -0
- package/dist/core/findings.d.ts.map +1 -0
- package/dist/core/findings.js +34 -0
- package/dist/core/findings.js.map +1 -0
- package/dist/core/orchestrator.d.ts +44 -0
- package/dist/core/orchestrator.d.ts.map +1 -0
- package/dist/core/orchestrator.js +160 -0
- package/dist/core/orchestrator.js.map +1 -0
- package/dist/core/result.d.ts +169 -0
- package/dist/core/result.d.ts.map +1 -0
- package/dist/core/result.js +2 -0
- package/dist/core/result.js.map +1 -0
- package/dist/detectors/framework.d.ts +22 -0
- package/dist/detectors/framework.d.ts.map +1 -0
- package/dist/detectors/framework.js +147 -0
- package/dist/detectors/framework.js.map +1 -0
- package/dist/detectors/language.d.ts +13 -0
- package/dist/detectors/language.d.ts.map +1 -0
- package/dist/detectors/language.js +100 -0
- package/dist/detectors/language.js.map +1 -0
- package/dist/detectors/package-manager.d.ts +17 -0
- package/dist/detectors/package-manager.d.ts.map +1 -0
- package/dist/detectors/package-manager.js +67 -0
- package/dist/detectors/package-manager.js.map +1 -0
- package/dist/detectors/project-type.d.ts +20 -0
- package/dist/detectors/project-type.d.ts.map +1 -0
- package/dist/detectors/project-type.js +48 -0
- package/dist/detectors/project-type.js.map +1 -0
- package/dist/diff/analyzer.d.ts +16 -0
- package/dist/diff/analyzer.d.ts.map +1 -0
- package/dist/diff/analyzer.js +296 -0
- package/dist/diff/analyzer.js.map +1 -0
- package/dist/diff/git-diff.d.ts +44 -0
- package/dist/diff/git-diff.d.ts.map +1 -0
- package/dist/diff/git-diff.js +256 -0
- package/dist/diff/git-diff.js.map +1 -0
- package/dist/diff/types.d.ts +75 -0
- package/dist/diff/types.d.ts.map +1 -0
- package/dist/diff/types.js +2 -0
- package/dist/diff/types.js.map +1 -0
- package/dist/integrations/github/context.d.ts +22 -0
- package/dist/integrations/github/context.d.ts.map +1 -0
- package/dist/integrations/github/context.js +115 -0
- package/dist/integrations/github/context.js.map +1 -0
- package/dist/integrations/github/types.d.ts +30 -0
- package/dist/integrations/github/types.d.ts.map +1 -0
- package/dist/integrations/github/types.js +2 -0
- package/dist/integrations/github/types.js.map +1 -0
- package/dist/plugins/context.d.ts +13 -0
- package/dist/plugins/context.d.ts.map +1 -0
- package/dist/plugins/context.js +102 -0
- package/dist/plugins/context.js.map +1 -0
- package/dist/plugins/examples/react.d.ts +8 -0
- package/dist/plugins/examples/react.d.ts.map +1 -0
- package/dist/plugins/examples/react.js +129 -0
- package/dist/plugins/examples/react.js.map +1 -0
- package/dist/plugins/index.d.ts +5 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +4 -0
- package/dist/plugins/index.js.map +1 -0
- package/dist/plugins/registry.d.ts +45 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +236 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/plugins/types.d.ts +148 -0
- package/dist/plugins/types.d.ts.map +1 -0
- package/dist/plugins/types.js +2 -0
- package/dist/plugins/types.js.map +1 -0
- package/dist/reporters/html.d.ts +11 -0
- package/dist/reporters/html.d.ts.map +1 -0
- package/dist/reporters/html.js +1352 -0
- package/dist/reporters/html.js.map +1 -0
- package/dist/reporters/json.d.ts +10 -0
- package/dist/reporters/json.d.ts.map +1 -0
- package/dist/reporters/json.js +11 -0
- package/dist/reporters/json.js.map +1 -0
- package/dist/reporters/markdown.d.ts +7 -0
- package/dist/reporters/markdown.d.ts.map +1 -0
- package/dist/reporters/markdown.js +74 -0
- package/dist/reporters/markdown.js.map +1 -0
- package/dist/reporters/sarif.d.ts +133 -0
- package/dist/reporters/sarif.d.ts.map +1 -0
- package/dist/reporters/sarif.js +268 -0
- package/dist/reporters/sarif.js.map +1 -0
- package/dist/reporters/terminal.d.ts +17 -0
- package/dist/reporters/terminal.d.ts.map +1 -0
- package/dist/reporters/terminal.js +423 -0
- package/dist/reporters/terminal.js.map +1 -0
- package/dist/rules/categories.d.ts +8 -0
- package/dist/rules/categories.d.ts.map +1 -0
- package/dist/rules/categories.js +23 -0
- package/dist/rules/categories.js.map +1 -0
- package/dist/rules/definitions.d.ts +25 -0
- package/dist/rules/definitions.d.ts.map +1 -0
- package/dist/rules/definitions.js +429 -0
- package/dist/rules/definitions.js.map +1 -0
- package/dist/rules/registry.d.ts +36 -0
- package/dist/rules/registry.d.ts.map +1 -0
- package/dist/rules/registry.js +64 -0
- package/dist/rules/registry.js.map +1 -0
- package/dist/rules/severity.d.ts +13 -0
- package/dist/rules/severity.d.ts.map +1 -0
- package/dist/rules/severity.js +15 -0
- package/dist/rules/severity.js.map +1 -0
- package/dist/scoring/confidence.d.ts +12 -0
- package/dist/scoring/confidence.d.ts.map +1 -0
- package/dist/scoring/confidence.js +22 -0
- package/dist/scoring/confidence.js.map +1 -0
- package/dist/scoring/score.d.ts +27 -0
- package/dist/scoring/score.d.ts.map +1 -0
- package/dist/scoring/score.js +81 -0
- package/dist/scoring/score.js.map +1 -0
- package/dist/scoring/weights.d.ts +11 -0
- package/dist/scoring/weights.d.ts.map +1 -0
- package/dist/scoring/weights.js +26 -0
- package/dist/scoring/weights.js.map +1 -0
- package/dist/utils/filesystem.d.ts +65 -0
- package/dist/utils/filesystem.d.ts.map +1 -0
- package/dist/utils/filesystem.js +299 -0
- package/dist/utils/filesystem.js.map +1 -0
- package/dist/utils/git.d.ts +47 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +125 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/logger.d.ts +14 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +25 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/paths.d.ts +30 -0
- package/dist/utils/paths.d.ts.map +1 -0
- package/dist/utils/paths.js +48 -0
- package/dist/utils/paths.js.map +1 -0
- package/dist/utils/timing.d.ts +12 -0
- package/dist/utils/timing.d.ts.map +1 -0
- package/dist/utils/timing.js +19 -0
- package/dist/utils/timing.js.map +1 -0
- package/package.json +73 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { PRDiffStats } from './types.js';
|
|
2
|
+
export interface GitCommandResult {
|
|
3
|
+
stdout: string;
|
|
4
|
+
stderr: string;
|
|
5
|
+
exitCode: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Execute a Git command safely via child_process.execFile.
|
|
9
|
+
* Arguments are passed as an array, never interpolated into shell strings.
|
|
10
|
+
*/
|
|
11
|
+
export declare function runGit(cwd: string, args: string[]): Promise<GitCommandResult>;
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the base Git reference to diff against.
|
|
14
|
+
* Handles explicit refs, auto-detection, shallow clones, and detached HEAD.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveBaseRef(repoRoot: string, requestedRef?: string | boolean): Promise<string>;
|
|
17
|
+
/**
|
|
18
|
+
* Determine the merge-base or comparison point between baseRef and current HEAD.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getDiffTargetRef(repoRoot: string, baseRef: string): Promise<string>;
|
|
21
|
+
/**
|
|
22
|
+
* Check if a 1-based line number falls into any of the changed line ranges.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isLineInRanges(ranges: Array<{
|
|
25
|
+
start: number;
|
|
26
|
+
end: number;
|
|
27
|
+
}>, line: number): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Parse hunk line ranges from git diff -U0 output.
|
|
30
|
+
*/
|
|
31
|
+
export declare function parseDiffHunks(diffOutput: string): Map<string, Array<{
|
|
32
|
+
start: number;
|
|
33
|
+
end: number;
|
|
34
|
+
}>>;
|
|
35
|
+
/**
|
|
36
|
+
* Retrieve summary and file-by-file stats for the diff against baseRef.
|
|
37
|
+
*/
|
|
38
|
+
export declare function getDiffStats(repoRoot: string, baseRef: string): Promise<PRDiffStats>;
|
|
39
|
+
/**
|
|
40
|
+
* Retrieve file contents at a given Git reference.
|
|
41
|
+
* Returns null if the file does not exist at that ref.
|
|
42
|
+
*/
|
|
43
|
+
export declare function getFileAtRef(repoRoot: string, ref: string, relativePath: string): Promise<string | null>;
|
|
44
|
+
//# sourceMappingURL=git-diff.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-diff.d.ts","sourceRoot":"","sources":["../../src/diff/git-diff.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAiB,WAAW,EAAE,MAAM,YAAY,CAAC;AAM7D,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;GAGG;AACH,wBAAsB,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAmBnF;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,GAC9B,OAAO,CAAC,MAAM,CAAC,CAwEjB;AAED;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAazF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,MAAM,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,EAC7C,IAAI,EAAE,MAAM,GACX,OAAO,CAET;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,UAAU,EAAE,MAAM,GACjB,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC,CAsCpD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAkG1F;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,GAAG,EAAE,MAAM,EACX,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAOxB"}
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
import { execFile } from 'node:child_process';
|
|
2
|
+
import { promisify } from 'node:util';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { FathomGitDiffError } from '../core/errors.js';
|
|
5
|
+
import { isGitRepository, hasCommits, hasUncommittedChanges } from '../utils/git.js';
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
/**
|
|
8
|
+
* Execute a Git command safely via child_process.execFile.
|
|
9
|
+
* Arguments are passed as an array, never interpolated into shell strings.
|
|
10
|
+
*/
|
|
11
|
+
export async function runGit(cwd, args) {
|
|
12
|
+
try {
|
|
13
|
+
const { stdout, stderr } = await execFileAsync('git', args, {
|
|
14
|
+
cwd,
|
|
15
|
+
timeout: 15_000,
|
|
16
|
+
maxBuffer: 10 * 1024 * 1024, // 10MB
|
|
17
|
+
});
|
|
18
|
+
return { stdout: stdout.trim(), stderr: stderr.trim(), exitCode: 0 };
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
if (err && typeof err === 'object' && 'stdout' in err && 'stderr' in err && 'code' in err) {
|
|
22
|
+
const e = err;
|
|
23
|
+
return {
|
|
24
|
+
stdout: (e.stdout ?? '').trim(),
|
|
25
|
+
stderr: (e.stderr ?? '').trim(),
|
|
26
|
+
exitCode: e.code ?? 1,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
return { stdout: '', stderr: String(err), exitCode: 1 };
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Resolve the base Git reference to diff against.
|
|
34
|
+
* Handles explicit refs, auto-detection, shallow clones, and detached HEAD.
|
|
35
|
+
*/
|
|
36
|
+
export async function resolveBaseRef(repoRoot, requestedRef) {
|
|
37
|
+
const isRepo = await isGitRepository(repoRoot);
|
|
38
|
+
if (!isRepo) {
|
|
39
|
+
throw new FathomGitDiffError(`Directory "${path.resolve(repoRoot)}" is not a valid Git repository root.`);
|
|
40
|
+
}
|
|
41
|
+
const commitsExist = await hasCommits(repoRoot);
|
|
42
|
+
if (!commitsExist) {
|
|
43
|
+
throw new FathomGitDiffError('Git repository has no commits to diff against.');
|
|
44
|
+
}
|
|
45
|
+
// If specific ref requested
|
|
46
|
+
if (typeof requestedRef === 'string' && requestedRef.trim() !== '') {
|
|
47
|
+
const ref = requestedRef.trim();
|
|
48
|
+
const verify = await runGit(repoRoot, ['rev-parse', '--verify', ref]);
|
|
49
|
+
if (verify.exitCode !== 0) {
|
|
50
|
+
const isShallow = await runGit(repoRoot, ['rev-parse', '--is-shallow-repository']);
|
|
51
|
+
if (isShallow.stdout === 'true') {
|
|
52
|
+
throw new FathomGitDiffError(`Base ref "${ref}" is not reachable in this shallow clone.\nFetch more history using "git fetch --depth=50 origin ${ref}" or "git fetch --unshallow".`);
|
|
53
|
+
}
|
|
54
|
+
throw new FathomGitDiffError(`Base ref "${ref}" could not be resolved. Please verify the branch, tag, or commit exists.`);
|
|
55
|
+
}
|
|
56
|
+
return ref;
|
|
57
|
+
}
|
|
58
|
+
// Auto-detect base ref
|
|
59
|
+
// 1. Try upstream tracking branch
|
|
60
|
+
const upstreamRes = await runGit(repoRoot, ['rev-parse', '--abbrev-ref', '@{u}']);
|
|
61
|
+
if (upstreamRes.exitCode === 0 && upstreamRes.stdout) {
|
|
62
|
+
const upstream = upstreamRes.stdout;
|
|
63
|
+
const verify = await runGit(repoRoot, ['rev-parse', '--verify', upstream]);
|
|
64
|
+
if (verify.exitCode === 0) {
|
|
65
|
+
return upstream;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
// 2. Try common default branches
|
|
69
|
+
const candidates = ['origin/main', 'main', 'origin/master', 'master'];
|
|
70
|
+
for (const candidate of candidates) {
|
|
71
|
+
const verify = await runGit(repoRoot, ['rev-parse', '--verify', candidate]);
|
|
72
|
+
if (verify.exitCode === 0) {
|
|
73
|
+
return candidate;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
// 3. If working directory has uncommitted changes, diff against HEAD
|
|
77
|
+
const uncommitted = await hasUncommittedChanges(repoRoot);
|
|
78
|
+
if (uncommitted) {
|
|
79
|
+
return 'HEAD';
|
|
80
|
+
}
|
|
81
|
+
// 4. Try HEAD~1 if history exists
|
|
82
|
+
const headPrev = await runGit(repoRoot, ['rev-parse', '--verify', 'HEAD~1']);
|
|
83
|
+
if (headPrev.exitCode === 0) {
|
|
84
|
+
return 'HEAD~1';
|
|
85
|
+
}
|
|
86
|
+
// 5. Fallback to HEAD
|
|
87
|
+
const head = await runGit(repoRoot, ['rev-parse', '--verify', 'HEAD']);
|
|
88
|
+
if (head.exitCode === 0) {
|
|
89
|
+
return 'HEAD';
|
|
90
|
+
}
|
|
91
|
+
throw new FathomGitDiffError('Could not auto-detect a base branch. Please specify a base ref (e.g. fathom --diff main).');
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Determine the merge-base or comparison point between baseRef and current HEAD.
|
|
95
|
+
*/
|
|
96
|
+
export async function getDiffTargetRef(repoRoot, baseRef) {
|
|
97
|
+
// If baseRef is already HEAD or HEAD~1, use it directly
|
|
98
|
+
if (baseRef === 'HEAD' || baseRef.startsWith('HEAD~')) {
|
|
99
|
+
return baseRef;
|
|
100
|
+
}
|
|
101
|
+
// Try finding common ancestor via merge-base
|
|
102
|
+
const mb = await runGit(repoRoot, ['merge-base', baseRef, 'HEAD']);
|
|
103
|
+
if (mb.exitCode === 0 && mb.stdout) {
|
|
104
|
+
return mb.stdout;
|
|
105
|
+
}
|
|
106
|
+
return baseRef;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Check if a 1-based line number falls into any of the changed line ranges.
|
|
110
|
+
*/
|
|
111
|
+
export function isLineInRanges(ranges, line) {
|
|
112
|
+
return ranges.some((r) => line >= r.start && line <= r.end);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Parse hunk line ranges from git diff -U0 output.
|
|
116
|
+
*/
|
|
117
|
+
export function parseDiffHunks(diffOutput) {
|
|
118
|
+
const lineRangeMap = new Map();
|
|
119
|
+
let currentFile = null;
|
|
120
|
+
const lines = diffOutput.split('\n');
|
|
121
|
+
for (const line of lines) {
|
|
122
|
+
if (line.startsWith('diff --git ')) {
|
|
123
|
+
// Format: diff --git a/path b/path
|
|
124
|
+
const match = /^diff --git a\/.+ b\/(.+)$/.exec(line);
|
|
125
|
+
if (match?.[1]) {
|
|
126
|
+
currentFile = match[1].replace(/\\/g, '/');
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
currentFile = null;
|
|
130
|
+
}
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
if (currentFile && line.startsWith('@@ ')) {
|
|
134
|
+
// Format: @@ -oldStart,oldLen +newStart,newLen @@
|
|
135
|
+
const match = /@@ -\d+(?:,\d+)? \+(\d+)(?:,(\d+))? @@/.exec(line);
|
|
136
|
+
if (match?.[1]) {
|
|
137
|
+
const start = parseInt(match[1], 10);
|
|
138
|
+
const len = match[2] !== undefined ? parseInt(match[2], 10) : 1;
|
|
139
|
+
if (!isNaN(start)) {
|
|
140
|
+
const ranges = lineRangeMap.get(currentFile) ?? [];
|
|
141
|
+
if (len > 0) {
|
|
142
|
+
ranges.push({ start, end: start + len - 1 });
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
// Line deleted at position `start`
|
|
146
|
+
ranges.push({ start, end: start });
|
|
147
|
+
}
|
|
148
|
+
lineRangeMap.set(currentFile, ranges);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return lineRangeMap;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Retrieve summary and file-by-file stats for the diff against baseRef.
|
|
157
|
+
*/
|
|
158
|
+
export async function getDiffStats(repoRoot, baseRef) {
|
|
159
|
+
const diffTarget = await getDiffTargetRef(repoRoot, baseRef);
|
|
160
|
+
// 1. Get name-status
|
|
161
|
+
const nameStatusRes = await runGit(repoRoot, ['diff', '--name-status', diffTarget]);
|
|
162
|
+
if (nameStatusRes.exitCode !== 0) {
|
|
163
|
+
throw new FathomGitDiffError(`Failed to compute git diff against "${baseRef}": ${nameStatusRes.stderr}`);
|
|
164
|
+
}
|
|
165
|
+
// 2. Get numstat
|
|
166
|
+
const numstatRes = await runGit(repoRoot, ['diff', '--numstat', diffTarget]);
|
|
167
|
+
// 3. Get unified diff for line ranges
|
|
168
|
+
const u0Res = await runGit(repoRoot, ['diff', '-U0', diffTarget]);
|
|
169
|
+
const hunksMap = u0Res.exitCode === 0
|
|
170
|
+
? parseDiffHunks(u0Res.stdout)
|
|
171
|
+
: new Map();
|
|
172
|
+
// Map numstats by file path
|
|
173
|
+
const numstatMap = new Map();
|
|
174
|
+
if (numstatRes.exitCode === 0 && numstatRes.stdout) {
|
|
175
|
+
for (const line of numstatRes.stdout.split('\n')) {
|
|
176
|
+
const parts = line.split('\t');
|
|
177
|
+
if (parts.length >= 3) {
|
|
178
|
+
const added = parts[0] === '-' ? 0 : parseInt(parts[0] ?? '0', 10) || 0;
|
|
179
|
+
const removed = parts[1] === '-' ? 0 : parseInt(parts[1] ?? '0', 10) || 0;
|
|
180
|
+
let filePath = (parts[2] ?? '').trim();
|
|
181
|
+
// Handle renamed paths in numstat: {old => new} or old => new
|
|
182
|
+
if (filePath.includes(' => ')) {
|
|
183
|
+
const renameMatch = /\{?.* => (.*?)\}?$/.exec(filePath);
|
|
184
|
+
if (renameMatch?.[1]) {
|
|
185
|
+
filePath = renameMatch[1].replace(/\\/g, '/');
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
numstatMap.set(filePath.replace(/\\/g, '/'), { added, removed });
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const files = [];
|
|
193
|
+
let totalAdded = 0;
|
|
194
|
+
let totalRemoved = 0;
|
|
195
|
+
if (nameStatusRes.stdout) {
|
|
196
|
+
for (const line of nameStatusRes.stdout.split('\n')) {
|
|
197
|
+
const parts = line.split('\t');
|
|
198
|
+
if (parts.length < 2)
|
|
199
|
+
continue;
|
|
200
|
+
const statusCode = (parts[0] ?? '').trim();
|
|
201
|
+
let filePath = (parts[1] ?? '').trim().replace(/\\/g, '/');
|
|
202
|
+
let basePath = undefined;
|
|
203
|
+
let status = 'modified';
|
|
204
|
+
if (statusCode.startsWith('A')) {
|
|
205
|
+
status = 'added';
|
|
206
|
+
}
|
|
207
|
+
else if (statusCode.startsWith('D')) {
|
|
208
|
+
status = 'deleted';
|
|
209
|
+
}
|
|
210
|
+
else if (statusCode.startsWith('R')) {
|
|
211
|
+
status = 'renamed';
|
|
212
|
+
basePath = filePath;
|
|
213
|
+
filePath = (parts[2] ?? '').trim().replace(/\\/g, '/');
|
|
214
|
+
}
|
|
215
|
+
else if (statusCode.startsWith('M')) {
|
|
216
|
+
status = 'modified';
|
|
217
|
+
}
|
|
218
|
+
const num = numstatMap.get(filePath) ?? { added: 0, removed: 0 };
|
|
219
|
+
totalAdded += num.added;
|
|
220
|
+
totalRemoved += num.removed;
|
|
221
|
+
const changedLineRanges = hunksMap.get(filePath) ?? [];
|
|
222
|
+
const changedFile = {
|
|
223
|
+
path: filePath,
|
|
224
|
+
status,
|
|
225
|
+
linesAdded: num.added,
|
|
226
|
+
linesRemoved: num.removed,
|
|
227
|
+
changedLineRanges,
|
|
228
|
+
};
|
|
229
|
+
if (basePath) {
|
|
230
|
+
changedFile.basePath = basePath;
|
|
231
|
+
}
|
|
232
|
+
files.push(changedFile);
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
baseRef,
|
|
237
|
+
targetRef: diffTarget,
|
|
238
|
+
filesChanged: files.length,
|
|
239
|
+
linesAdded: totalAdded,
|
|
240
|
+
linesRemoved: totalRemoved,
|
|
241
|
+
files,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Retrieve file contents at a given Git reference.
|
|
246
|
+
* Returns null if the file does not exist at that ref.
|
|
247
|
+
*/
|
|
248
|
+
export async function getFileAtRef(repoRoot, ref, relativePath) {
|
|
249
|
+
const normalized = relativePath.replace(/\\/g, '/');
|
|
250
|
+
const result = await runGit(repoRoot, ['show', `${ref}:${normalized}`]);
|
|
251
|
+
if (result.exitCode === 0) {
|
|
252
|
+
return result.stdout;
|
|
253
|
+
}
|
|
254
|
+
return null;
|
|
255
|
+
}
|
|
256
|
+
//# sourceMappingURL=git-diff.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-diff.js","sourceRoot":"","sources":["../../src/diff/git-diff.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Category } from '../rules/categories.js';
|
|
2
|
+
import type { Finding } from '../core/findings.js';
|
|
3
|
+
/**
|
|
4
|
+
* Information about an individual changed file in the Git diff.
|
|
5
|
+
*/
|
|
6
|
+
export interface PRChangedFile {
|
|
7
|
+
/** Repository-relative path */
|
|
8
|
+
path: string;
|
|
9
|
+
/** Status of the file in the diff */
|
|
10
|
+
status: 'added' | 'modified' | 'deleted' | 'renamed';
|
|
11
|
+
/** Lines added */
|
|
12
|
+
linesAdded: number;
|
|
13
|
+
/** Lines removed */
|
|
14
|
+
linesRemoved: number;
|
|
15
|
+
/** Line ranges added or modified in the target version (1-indexed) */
|
|
16
|
+
changedLineRanges: Array<{
|
|
17
|
+
start: number;
|
|
18
|
+
end: number;
|
|
19
|
+
}>;
|
|
20
|
+
/** Previous path if renamed */
|
|
21
|
+
basePath?: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Summary statistics of the Git diff.
|
|
25
|
+
*/
|
|
26
|
+
export interface PRDiffStats {
|
|
27
|
+
/** The base Git reference compared against */
|
|
28
|
+
baseRef: string;
|
|
29
|
+
/** The target Git reference (usually HEAD or working directory) */
|
|
30
|
+
targetRef: string;
|
|
31
|
+
/** Total number of changed files */
|
|
32
|
+
filesChanged: number;
|
|
33
|
+
/** Total number of lines added */
|
|
34
|
+
linesAdded: number;
|
|
35
|
+
/** Total number of lines removed */
|
|
36
|
+
linesRemoved: number;
|
|
37
|
+
/** List of changed files */
|
|
38
|
+
files: PRChangedFile[];
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Impact of the diff on a specific category's score.
|
|
42
|
+
*/
|
|
43
|
+
export interface PRCategoryImpact {
|
|
44
|
+
category: Category;
|
|
45
|
+
baseScore: number;
|
|
46
|
+
currentScore: number;
|
|
47
|
+
delta: number;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Complete result of the PR / Git diff analysis.
|
|
51
|
+
*/
|
|
52
|
+
export interface PRAnalysisResult {
|
|
53
|
+
/** Diff summary statistics */
|
|
54
|
+
stats: PRDiffStats;
|
|
55
|
+
/** Overall health score at the base ref */
|
|
56
|
+
baseScore: number;
|
|
57
|
+
/** Overall health score in current repository state */
|
|
58
|
+
currentScore: number;
|
|
59
|
+
/** Overall score change (currentScore - baseScore) */
|
|
60
|
+
scoreDelta: number;
|
|
61
|
+
/** Findings newly introduced by the diff */
|
|
62
|
+
newFindings: Finding[];
|
|
63
|
+
/** Existing findings in files/lines touched by the diff */
|
|
64
|
+
touchedFindings: Finding[];
|
|
65
|
+
/** Findings resolved by the diff */
|
|
66
|
+
resolvedFindings: Finding[];
|
|
67
|
+
/** Category-by-category score impact */
|
|
68
|
+
categoryImpact: PRCategoryImpact[];
|
|
69
|
+
/** Verdict */
|
|
70
|
+
verdict: {
|
|
71
|
+
passed: boolean;
|
|
72
|
+
summary: string;
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/diff/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,+BAA+B;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,qCAAqC;IACrC,MAAM,EAAE,OAAO,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;IACrD,kBAAkB;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,iBAAiB,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACzD,+BAA+B;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,WAAW;IAC1B,8CAA8C;IAC9C,OAAO,EAAE,MAAM,CAAC;IAChB,mEAAmE;IACnE,SAAS,EAAE,MAAM,CAAC;IAClB,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,oCAAoC;IACpC,YAAY,EAAE,MAAM,CAAC;IACrB,4BAA4B;IAC5B,KAAK,EAAE,aAAa,EAAE,CAAC;CACxB;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,QAAQ,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,8BAA8B;IAC9B,KAAK,EAAE,WAAW,CAAC;IACnB,2CAA2C;IAC3C,SAAS,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,YAAY,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,UAAU,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,WAAW,EAAE,OAAO,EAAE,CAAC;IACvB,2DAA2D;IAC3D,eAAe,EAAE,OAAO,EAAE,CAAC;IAC3B,oCAAoC;IACpC,gBAAgB,EAAE,OAAO,EAAE,CAAC;IAC5B,wCAAwC;IACxC,cAAc,EAAE,gBAAgB,EAAE,CAAC;IACnC,cAAc;IACd,OAAO,EAAE;QACP,MAAM,EAAE,OAAO,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB,CAAC;CACH"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/diff/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { GitHubContext, CommentResult } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Safely detect GitHub Actions environment variables and event payload.
|
|
4
|
+
* Never throws — returns safe defaults if not in GitHub Actions.
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectGitHubContext(): Promise<GitHubContext>;
|
|
7
|
+
/**
|
|
8
|
+
* Append a Markdown summary to GitHub Actions step summary file.
|
|
9
|
+
* Returns true if written, false if no summary path was found.
|
|
10
|
+
*/
|
|
11
|
+
export declare function publishStepSummary(markdown: string, customPath?: string): Promise<boolean>;
|
|
12
|
+
/**
|
|
13
|
+
* Post a comment to a GitHub pull request using the GitHub REST API.
|
|
14
|
+
* Never leaks credentials in error logs or stdout.
|
|
15
|
+
*/
|
|
16
|
+
export declare function publishPRComment(options: {
|
|
17
|
+
repository: string;
|
|
18
|
+
prNumber: number;
|
|
19
|
+
token: string;
|
|
20
|
+
body: string;
|
|
21
|
+
}): Promise<CommentResult>;
|
|
22
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/integrations/github/context.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAE/D;;;GAGG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,aAAa,CAAC,CA4ClE;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAehG;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE;IAC9C,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,GAAG,OAAO,CAAC,aAAa,CAAC,CAiDzB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
/**
|
|
3
|
+
* Safely detect GitHub Actions environment variables and event payload.
|
|
4
|
+
* Never throws — returns safe defaults if not in GitHub Actions.
|
|
5
|
+
*/
|
|
6
|
+
export async function detectGitHubContext() {
|
|
7
|
+
const isGitHubActions = process.env['GITHUB_ACTIONS'] === 'true';
|
|
8
|
+
const eventName = process.env['GITHUB_EVENT_NAME'];
|
|
9
|
+
const repository = process.env['GITHUB_REPOSITORY'];
|
|
10
|
+
const baseRef = process.env['GITHUB_BASE_REF'];
|
|
11
|
+
const headRef = process.env['GITHUB_HEAD_REF'];
|
|
12
|
+
const stepSummaryPath = process.env['GITHUB_STEP_SUMMARY'];
|
|
13
|
+
const token = process.env['GITHUB_TOKEN'];
|
|
14
|
+
let prNumber = undefined;
|
|
15
|
+
// Try extracting PR number from event payload if available
|
|
16
|
+
const eventPath = process.env['GITHUB_EVENT_PATH'];
|
|
17
|
+
if (eventPath) {
|
|
18
|
+
try {
|
|
19
|
+
const eventRaw = await fs.readFile(eventPath, 'utf8');
|
|
20
|
+
const eventData = JSON.parse(eventRaw);
|
|
21
|
+
if (typeof eventData?.pull_request?.number === 'number') {
|
|
22
|
+
prNumber = eventData.pull_request.number;
|
|
23
|
+
}
|
|
24
|
+
else if (typeof eventData?.number === 'number') {
|
|
25
|
+
prNumber = eventData.number;
|
|
26
|
+
}
|
|
27
|
+
else if (typeof eventData?.issue?.number === 'number') {
|
|
28
|
+
prNumber = eventData.issue.number;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// Ignore unreadable or invalid event file
|
|
33
|
+
prNumber = undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return {
|
|
37
|
+
isGitHubActions,
|
|
38
|
+
eventName,
|
|
39
|
+
repository,
|
|
40
|
+
prNumber,
|
|
41
|
+
baseRef,
|
|
42
|
+
headRef,
|
|
43
|
+
stepSummaryPath,
|
|
44
|
+
token,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Append a Markdown summary to GitHub Actions step summary file.
|
|
49
|
+
* Returns true if written, false if no summary path was found.
|
|
50
|
+
*/
|
|
51
|
+
export async function publishStepSummary(markdown, customPath) {
|
|
52
|
+
const targetPath = customPath ?? process.env['GITHUB_STEP_SUMMARY'];
|
|
53
|
+
if (!targetPath) {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
await fs.appendFile(targetPath, `${markdown}\n\n`, 'utf8');
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
process.stderr.write(`[Fathom] Warning: Failed to write to GitHub step summary (${targetPath}): ${String(err)}\n`);
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Post a comment to a GitHub pull request using the GitHub REST API.
|
|
67
|
+
* Never leaks credentials in error logs or stdout.
|
|
68
|
+
*/
|
|
69
|
+
export async function publishPRComment(options) {
|
|
70
|
+
const { repository, prNumber, token, body } = options;
|
|
71
|
+
if (!repository || !prNumber || !token) {
|
|
72
|
+
return {
|
|
73
|
+
success: false,
|
|
74
|
+
error: 'Missing repository, pull request number, or GitHub token.',
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const url = `https://api.github.com/repos/${repository}/issues/${prNumber}/comments`;
|
|
78
|
+
try {
|
|
79
|
+
const response = await fetch(url, {
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: {
|
|
82
|
+
Accept: 'application/vnd.github+json',
|
|
83
|
+
Authorization: `Bearer ${token}`,
|
|
84
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
85
|
+
'User-Agent': 'Fathom-PR-Intelligence/0.1.0',
|
|
86
|
+
'Content-Type': 'application/json',
|
|
87
|
+
},
|
|
88
|
+
body: JSON.stringify({ body }),
|
|
89
|
+
});
|
|
90
|
+
if (!response.ok) {
|
|
91
|
+
const statusText = response.statusText;
|
|
92
|
+
return {
|
|
93
|
+
success: false,
|
|
94
|
+
error: `GitHub API error (HTTP ${response.status}: ${statusText})`,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
const data = (await response.json());
|
|
98
|
+
return {
|
|
99
|
+
success: true,
|
|
100
|
+
commentId: data?.id,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
// Sanitize any error message to ensure token is never printed
|
|
105
|
+
let safeMessage = String(err);
|
|
106
|
+
if (token && safeMessage.includes(token)) {
|
|
107
|
+
safeMessage = safeMessage.replaceAll(token, '***TOKEN***');
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
success: false,
|
|
111
|
+
error: `Network error posting PR comment: ${safeMessage}`,
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/integrations/github/context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata and runtime state extracted from GitHub Actions environment.
|
|
3
|
+
*/
|
|
4
|
+
export interface GitHubContext {
|
|
5
|
+
/** True if running inside a GitHub Actions workflow */
|
|
6
|
+
isGitHubActions: boolean;
|
|
7
|
+
/** Name of the webhook event that triggered the workflow (e.g. 'pull_request', 'push') */
|
|
8
|
+
eventName?: string | undefined;
|
|
9
|
+
/** GitHub repository in 'owner/repo' format */
|
|
10
|
+
repository?: string | undefined;
|
|
11
|
+
/** Pull request number if triggered by a pull_request event */
|
|
12
|
+
prNumber?: number | undefined;
|
|
13
|
+
/** Base branch or ref name for pull request (e.g. 'main') */
|
|
14
|
+
baseRef?: string | undefined;
|
|
15
|
+
/** Head branch or ref name for pull request */
|
|
16
|
+
headRef?: string | undefined;
|
|
17
|
+
/** Absolute path to the file specified in $GITHUB_STEP_SUMMARY */
|
|
18
|
+
stepSummaryPath?: string | undefined;
|
|
19
|
+
/** Authentication token from $GITHUB_TOKEN if provided */
|
|
20
|
+
token?: string | undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Result of posting a comment to a GitHub PR.
|
|
24
|
+
*/
|
|
25
|
+
export interface CommentResult {
|
|
26
|
+
success: boolean;
|
|
27
|
+
commentId?: number | undefined;
|
|
28
|
+
error?: string | undefined;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/integrations/github/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,uDAAuD;IACvD,eAAe,EAAE,OAAO,CAAC;IACzB,0FAA0F;IAC1F,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,+CAA+C;IAC/C,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAChC,+DAA+D;IAC/D,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,6DAA6D;IAC7D,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,kEAAkE;IAClE,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,0DAA0D;IAC1D,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/integrations/github/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { RepositoryContext } from '../core/context.js';
|
|
2
|
+
import type { PluginContext, PluginRule } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Creates an isolated, sandboxed PluginContext.
|
|
5
|
+
*
|
|
6
|
+
* Enforces:
|
|
7
|
+
* - Read-only access to repository metadata
|
|
8
|
+
* - Traversal-safe file reading (cannot read outside repository root)
|
|
9
|
+
* - Size-bounded reads to avoid out-of-memory errors
|
|
10
|
+
* - Rule validation on finding creation
|
|
11
|
+
*/
|
|
12
|
+
export declare function createPluginContext(repoContext: RepositoryContext, rules: readonly PluginRule[]): PluginContext;
|
|
13
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/plugins/context.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAI5D,OAAO,KAAK,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI5D;;;;;;;;GAQG;AACH,wBAAgB,mBAAmB,CACjC,WAAW,EAAE,iBAAiB,EAC9B,KAAK,EAAE,SAAS,UAAU,EAAE,GAC3B,aAAa,CAgHf"}
|