@diff-review-system/drs 1.0.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/.opencode/agent/github-reviewer.md +62 -0
- package/.opencode/agent/gitlab-reviewer.md +62 -0
- package/.opencode/agent/local-reviewer.md +71 -0
- package/.opencode/agent/review/performance.md +151 -0
- package/.opencode/agent/review/quality.md +127 -0
- package/.opencode/agent/review/security.md +115 -0
- package/.opencode/agent/review/style.md +116 -0
- package/.opencode/opencode.jsonc +52 -0
- package/LICENSE +201 -0
- package/README.md +361 -0
- package/dist/ci/runner.d.ts +21 -0
- package/dist/ci/runner.d.ts.map +1 -0
- package/dist/ci/runner.js +82 -0
- package/dist/ci/runner.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 +137 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/init.d.ts +5 -0
- package/dist/cli/init.d.ts.map +1 -0
- package/dist/cli/init.js +166 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/review-local.d.ts +9 -0
- package/dist/cli/review-local.d.ts.map +1 -0
- package/dist/cli/review-local.js +105 -0
- package/dist/cli/review-local.js.map +1 -0
- package/dist/cli/review-mr.d.ts +11 -0
- package/dist/cli/review-mr.d.ts.map +1 -0
- package/dist/cli/review-mr.js +128 -0
- package/dist/cli/review-mr.js.map +1 -0
- package/dist/cli/review-pr.d.ts +12 -0
- package/dist/cli/review-pr.d.ts.map +1 -0
- package/dist/cli/review-pr.js +125 -0
- package/dist/cli/review-pr.js.map +1 -0
- package/dist/github/client.d.ts +1346 -0
- package/dist/github/client.d.ts.map +1 -0
- package/dist/github/client.js +137 -0
- package/dist/github/client.js.map +1 -0
- package/dist/gitlab/client.d.ts +55 -0
- package/dist/gitlab/client.d.ts.map +1 -0
- package/dist/gitlab/client.js +86 -0
- package/dist/gitlab/client.js.map +1 -0
- package/dist/gitlab/comment-formatter.d.ts +36 -0
- package/dist/gitlab/comment-formatter.d.ts.map +1 -0
- package/dist/gitlab/comment-formatter.js +118 -0
- package/dist/gitlab/comment-formatter.js.map +1 -0
- package/dist/gitlab/diff-parser.d.ts +41 -0
- package/dist/gitlab/diff-parser.d.ts.map +1 -0
- package/dist/gitlab/diff-parser.js +147 -0
- package/dist/gitlab/diff-parser.js.map +1 -0
- package/dist/lib/config.d.ts +42 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +144 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/opencode/agent-loader.d.ts +31 -0
- package/dist/opencode/agent-loader.d.ts.map +1 -0
- package/dist/opencode/agent-loader.js +115 -0
- package/dist/opencode/agent-loader.js.map +1 -0
- package/dist/opencode/client.d.ts +82 -0
- package/dist/opencode/client.d.ts.map +1 -0
- package/dist/opencode/client.js +184 -0
- package/dist/opencode/client.js.map +1 -0
- package/package.json +70 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/github/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { Octokit } from '@octokit/rest';
|
|
2
|
+
export class GitHubClient {
|
|
3
|
+
octokit;
|
|
4
|
+
owner;
|
|
5
|
+
repo;
|
|
6
|
+
constructor(config) {
|
|
7
|
+
this.octokit = new Octokit({
|
|
8
|
+
auth: config.token,
|
|
9
|
+
});
|
|
10
|
+
this.owner = config.owner;
|
|
11
|
+
this.repo = config.repo;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Get pull request details
|
|
15
|
+
*/
|
|
16
|
+
async getPullRequest(owner, repo, prNumber) {
|
|
17
|
+
const response = await this.octokit.pulls.get({
|
|
18
|
+
owner,
|
|
19
|
+
repo,
|
|
20
|
+
pull_number: prNumber,
|
|
21
|
+
});
|
|
22
|
+
return response.data;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Get pull request files (changes)
|
|
26
|
+
*/
|
|
27
|
+
async getPRFiles(owner, repo, prNumber) {
|
|
28
|
+
const response = await this.octokit.pulls.listFiles({
|
|
29
|
+
owner,
|
|
30
|
+
repo,
|
|
31
|
+
pull_number: prNumber,
|
|
32
|
+
per_page: 100,
|
|
33
|
+
});
|
|
34
|
+
return response.data.map(file => ({
|
|
35
|
+
filename: file.filename,
|
|
36
|
+
status: file.status,
|
|
37
|
+
additions: file.additions,
|
|
38
|
+
deletions: file.deletions,
|
|
39
|
+
changes: file.changes,
|
|
40
|
+
patch: file.patch,
|
|
41
|
+
previousFilename: file.previous_filename,
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Post a review comment on the PR
|
|
46
|
+
*/
|
|
47
|
+
async createPRComment(owner, repo, prNumber, body) {
|
|
48
|
+
return await this.octokit.issues.createComment({
|
|
49
|
+
owner,
|
|
50
|
+
repo,
|
|
51
|
+
issue_number: prNumber,
|
|
52
|
+
body,
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Create a review comment on a specific line
|
|
57
|
+
*/
|
|
58
|
+
async createPRReviewComment(owner, repo, prNumber, body, commitId, path, line) {
|
|
59
|
+
return await this.octokit.pulls.createReviewComment({
|
|
60
|
+
owner,
|
|
61
|
+
repo,
|
|
62
|
+
pull_number: prNumber,
|
|
63
|
+
body,
|
|
64
|
+
commit_id: commitId,
|
|
65
|
+
path,
|
|
66
|
+
line,
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Create a pull request review with multiple comments
|
|
71
|
+
*/
|
|
72
|
+
async createPRReview(owner, repo, prNumber, commitId, body, event, comments) {
|
|
73
|
+
return await this.octokit.pulls.createReview({
|
|
74
|
+
owner,
|
|
75
|
+
repo,
|
|
76
|
+
pull_number: prNumber,
|
|
77
|
+
commit_id: commitId,
|
|
78
|
+
body,
|
|
79
|
+
event,
|
|
80
|
+
comments,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Add labels to a PR
|
|
85
|
+
*/
|
|
86
|
+
async addLabels(owner, repo, prNumber, labels) {
|
|
87
|
+
return await this.octokit.issues.addLabels({
|
|
88
|
+
owner,
|
|
89
|
+
repo,
|
|
90
|
+
issue_number: prNumber,
|
|
91
|
+
labels,
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Check if PR has a specific label
|
|
96
|
+
*/
|
|
97
|
+
async hasLabel(owner, repo, prNumber, label) {
|
|
98
|
+
const response = await this.octokit.issues.listLabelsOnIssue({
|
|
99
|
+
owner,
|
|
100
|
+
repo,
|
|
101
|
+
issue_number: prNumber,
|
|
102
|
+
});
|
|
103
|
+
return response.data.some(l => l.name === label);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get repository details
|
|
107
|
+
*/
|
|
108
|
+
async getRepository(owner, repo) {
|
|
109
|
+
const response = await this.octokit.repos.get({
|
|
110
|
+
owner,
|
|
111
|
+
repo,
|
|
112
|
+
});
|
|
113
|
+
return response.data;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get the authenticated user
|
|
117
|
+
*/
|
|
118
|
+
async getAuthenticatedUser() {
|
|
119
|
+
const response = await this.octokit.users.getAuthenticated();
|
|
120
|
+
return response.data;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Create a GitHub client from environment variables
|
|
125
|
+
*/
|
|
126
|
+
export function createGitHubClient() {
|
|
127
|
+
const token = process.env.GITHUB_TOKEN;
|
|
128
|
+
if (!token) {
|
|
129
|
+
throw new Error('GITHUB_TOKEN environment variable is required');
|
|
130
|
+
}
|
|
131
|
+
return new GitHubClient({
|
|
132
|
+
token,
|
|
133
|
+
owner: process.env.GITHUB_OWNER,
|
|
134
|
+
repo: process.env.GITHUB_REPO,
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/github/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
export interface GitLabConfig {
|
|
2
|
+
url: string;
|
|
3
|
+
token: string;
|
|
4
|
+
}
|
|
5
|
+
export interface MRChange {
|
|
6
|
+
oldPath: string;
|
|
7
|
+
newPath: string;
|
|
8
|
+
newFile: boolean;
|
|
9
|
+
renamedFile: boolean;
|
|
10
|
+
deletedFile: boolean;
|
|
11
|
+
diff: string;
|
|
12
|
+
}
|
|
13
|
+
export declare class GitLabClient {
|
|
14
|
+
private client;
|
|
15
|
+
constructor(config: GitLabConfig);
|
|
16
|
+
/**
|
|
17
|
+
* Get merge request details
|
|
18
|
+
*/
|
|
19
|
+
getMergeRequest(projectId: string, mrIid: number): Promise<import("@gitbeaker/core/dist/types/types").MergeRequestSchema>;
|
|
20
|
+
/**
|
|
21
|
+
* Get merge request changes (diffs)
|
|
22
|
+
*/
|
|
23
|
+
getMRChanges(projectId: string, mrIid: number): Promise<MRChange[]>;
|
|
24
|
+
/**
|
|
25
|
+
* Post a comment to the MR
|
|
26
|
+
*/
|
|
27
|
+
createMRComment(projectId: string, mrIid: number, body: string): Promise<import("@gitbeaker/core/dist/types/types").MergeRequestNoteSchema>;
|
|
28
|
+
/**
|
|
29
|
+
* Create a discussion thread on a specific line
|
|
30
|
+
*/
|
|
31
|
+
createMRDiscussionThread(projectId: string, mrIid: number, body: string, position: {
|
|
32
|
+
baseSha: string;
|
|
33
|
+
headSha: string;
|
|
34
|
+
startSha: string;
|
|
35
|
+
newPath: string;
|
|
36
|
+
newLine: number;
|
|
37
|
+
}): Promise<import("@gitbeaker/core/dist/types/types").DiscussionSchema>;
|
|
38
|
+
/**
|
|
39
|
+
* Add a label to the MR
|
|
40
|
+
*/
|
|
41
|
+
addLabel(projectId: string, mrIid: number, labels: string[]): Promise<import("@gitbeaker/core/dist/types/types").MergeRequestSchema>;
|
|
42
|
+
/**
|
|
43
|
+
* Check if MR has a specific label
|
|
44
|
+
*/
|
|
45
|
+
hasLabel(projectId: string, mrIid: number, label: string): Promise<boolean>;
|
|
46
|
+
/**
|
|
47
|
+
* Get project details
|
|
48
|
+
*/
|
|
49
|
+
getProject(projectId: string): Promise<import("@gitbeaker/core/dist/types/types").ProjectExtendedSchema>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Create a GitLab client from environment variables
|
|
53
|
+
*/
|
|
54
|
+
export declare function createGitLabClient(): GitLabClient;
|
|
55
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/gitlab/client.ts"],"names":[],"mappings":"AAEA,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,WAAW,EAAE,OAAO,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAA8B;gBAEhC,MAAM,EAAE,YAAY;IAOhC;;OAEG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM;IAItD;;OAEG;IACG,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAczE;;OAEG;IACG,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM;IAIpE;;OAEG;IACG,wBAAwB,CAC5B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE;QACR,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,OAAO,EAAE,MAAM,CAAC;KACjB;IAeH;;OAEG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IAUjE;;OAEG;IACG,QAAQ,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMjF;;OAEG;IACG,UAAU,CAAC,SAAS,EAAE,MAAM;CAGnC;AAED;;GAEG;AACH,wBAAgB,kBAAkB,IAAI,YAAY,CASjD"}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Gitlab } from '@gitbeaker/node';
|
|
2
|
+
export class GitLabClient {
|
|
3
|
+
client;
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.client = new Gitlab({
|
|
6
|
+
host: config.url,
|
|
7
|
+
token: config.token,
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get merge request details
|
|
12
|
+
*/
|
|
13
|
+
async getMergeRequest(projectId, mrIid) {
|
|
14
|
+
return await this.client.MergeRequests.show(projectId, mrIid);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Get merge request changes (diffs)
|
|
18
|
+
*/
|
|
19
|
+
async getMRChanges(projectId, mrIid) {
|
|
20
|
+
const mr = await this.client.MergeRequests.changes(projectId, mrIid);
|
|
21
|
+
if (!mr.changes)
|
|
22
|
+
return [];
|
|
23
|
+
return mr.changes.map((change) => ({
|
|
24
|
+
oldPath: change.old_path,
|
|
25
|
+
newPath: change.new_path,
|
|
26
|
+
newFile: change.new_file,
|
|
27
|
+
renamedFile: change.renamed_file,
|
|
28
|
+
deletedFile: change.deleted_file,
|
|
29
|
+
diff: change.diff,
|
|
30
|
+
}));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Post a comment to the MR
|
|
34
|
+
*/
|
|
35
|
+
async createMRComment(projectId, mrIid, body) {
|
|
36
|
+
return await this.client.MergeRequestNotes.create(projectId, mrIid, body);
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Create a discussion thread on a specific line
|
|
40
|
+
*/
|
|
41
|
+
async createMRDiscussionThread(projectId, mrIid, body, position) {
|
|
42
|
+
return await this.client.MergeRequestDiscussions.create(projectId, mrIid, body, {
|
|
43
|
+
position: {
|
|
44
|
+
position_type: 'text',
|
|
45
|
+
...position,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Add a label to the MR
|
|
51
|
+
*/
|
|
52
|
+
async addLabel(projectId, mrIid, labels) {
|
|
53
|
+
const mr = await this.getMergeRequest(projectId, mrIid);
|
|
54
|
+
const currentLabels = Array.isArray(mr.labels) ? mr.labels : [];
|
|
55
|
+
const newLabels = [...new Set([...currentLabels, ...labels])];
|
|
56
|
+
return await this.client.MergeRequests.edit(projectId, mrIid, {
|
|
57
|
+
labels: newLabels.join(','),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Check if MR has a specific label
|
|
62
|
+
*/
|
|
63
|
+
async hasLabel(projectId, mrIid, label) {
|
|
64
|
+
const mr = await this.getMergeRequest(projectId, mrIid);
|
|
65
|
+
const labels = Array.isArray(mr.labels) ? mr.labels : [];
|
|
66
|
+
return labels.includes(label);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get project details
|
|
70
|
+
*/
|
|
71
|
+
async getProject(projectId) {
|
|
72
|
+
return await this.client.Projects.show(projectId);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Create a GitLab client from environment variables
|
|
77
|
+
*/
|
|
78
|
+
export function createGitLabClient() {
|
|
79
|
+
const url = process.env.GITLAB_URL || 'https://gitlab.com';
|
|
80
|
+
const token = process.env.GITLAB_TOKEN;
|
|
81
|
+
if (!token) {
|
|
82
|
+
throw new Error('GITLAB_TOKEN environment variable is required');
|
|
83
|
+
}
|
|
84
|
+
return new GitLabClient({ url, token });
|
|
85
|
+
}
|
|
86
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/gitlab/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export type IssueSeverity = 'CRITICAL' | 'HIGH' | 'MEDIUM' | 'LOW';
|
|
2
|
+
export type IssueCategory = 'SECURITY' | 'QUALITY' | 'STYLE' | 'PERFORMANCE';
|
|
3
|
+
export interface ReviewIssue {
|
|
4
|
+
category: IssueCategory;
|
|
5
|
+
severity: IssueSeverity;
|
|
6
|
+
title: string;
|
|
7
|
+
file: string;
|
|
8
|
+
line?: number;
|
|
9
|
+
problem: string;
|
|
10
|
+
solution: string;
|
|
11
|
+
references?: string[];
|
|
12
|
+
agent: string;
|
|
13
|
+
}
|
|
14
|
+
export interface ReviewSummary {
|
|
15
|
+
filesReviewed: number;
|
|
16
|
+
issuesFound: number;
|
|
17
|
+
bySeverity: Record<IssueSeverity, number>;
|
|
18
|
+
byCategory: Record<IssueCategory, number>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Format a single review issue as a GitLab comment
|
|
22
|
+
*/
|
|
23
|
+
export declare function formatIssueComment(issue: ReviewIssue): string;
|
|
24
|
+
/**
|
|
25
|
+
* Format a review summary as a GitLab comment
|
|
26
|
+
*/
|
|
27
|
+
export declare function formatSummaryComment(summary: ReviewSummary, issues: ReviewIssue[]): string;
|
|
28
|
+
/**
|
|
29
|
+
* Format issue for terminal output with colors
|
|
30
|
+
*/
|
|
31
|
+
export declare function formatTerminalIssue(issue: ReviewIssue): string;
|
|
32
|
+
/**
|
|
33
|
+
* Calculate review summary from issues
|
|
34
|
+
*/
|
|
35
|
+
export declare function calculateSummary(filesReviewed: number, issues: ReviewIssue[]): ReviewSummary;
|
|
36
|
+
//# sourceMappingURL=comment-formatter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comment-formatter.d.ts","sourceRoot":"","sources":["../../src/gitlab/comment-formatter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;AACnE,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;AAE7E,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,aAAa,CAAC;IACxB,QAAQ,EAAE,aAAa,CAAC;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;IAC1C,UAAU,EAAE,MAAM,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;CAC3C;AAgBD;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAoB7D;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAiD1F;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAY9D;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,WAAW,EAAE,GACpB,aAAa,CAwBf"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
const SEVERITY_EMOJI = {
|
|
2
|
+
CRITICAL: '🔴',
|
|
3
|
+
HIGH: '🟡',
|
|
4
|
+
MEDIUM: '🟠',
|
|
5
|
+
LOW: '⚪',
|
|
6
|
+
};
|
|
7
|
+
const CATEGORY_EMOJI = {
|
|
8
|
+
SECURITY: '🔒',
|
|
9
|
+
QUALITY: '📊',
|
|
10
|
+
STYLE: '✨',
|
|
11
|
+
PERFORMANCE: '⚡',
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Format a single review issue as a GitLab comment
|
|
15
|
+
*/
|
|
16
|
+
export function formatIssueComment(issue) {
|
|
17
|
+
const emoji = CATEGORY_EMOJI[issue.category];
|
|
18
|
+
const severityEmoji = SEVERITY_EMOJI[issue.severity];
|
|
19
|
+
let comment = `## ${emoji} ${issue.category} - ${issue.title}\n\n`;
|
|
20
|
+
comment += `**File**: \`${issue.file}${issue.line ? `:${issue.line}` : ''}\`\n`;
|
|
21
|
+
comment += `**Severity**: ${severityEmoji} ${issue.severity}\n`;
|
|
22
|
+
comment += `**Reviewer**: ${issue.agent}\n\n`;
|
|
23
|
+
comment += `### Problem\n${issue.problem}\n\n`;
|
|
24
|
+
comment += `### Solution\n${issue.solution}\n`;
|
|
25
|
+
if (issue.references && issue.references.length > 0) {
|
|
26
|
+
comment += `\n### References\n`;
|
|
27
|
+
for (const ref of issue.references) {
|
|
28
|
+
comment += `- ${ref}\n`;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return comment;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Format a review summary as a GitLab comment
|
|
35
|
+
*/
|
|
36
|
+
export function formatSummaryComment(summary, issues) {
|
|
37
|
+
let comment = `# 🤖 AI Code Review Summary\n\n`;
|
|
38
|
+
comment += `## 📊 Statistics\n\n`;
|
|
39
|
+
comment += `- **Files Reviewed**: ${summary.filesReviewed}\n`;
|
|
40
|
+
comment += `- **Total Issues**: ${summary.issuesFound}\n\n`;
|
|
41
|
+
if (summary.issuesFound > 0) {
|
|
42
|
+
comment += `### By Severity\n`;
|
|
43
|
+
comment += `- ${SEVERITY_EMOJI.CRITICAL} **Critical**: ${summary.bySeverity.CRITICAL}\n`;
|
|
44
|
+
comment += `- ${SEVERITY_EMOJI.HIGH} **High**: ${summary.bySeverity.HIGH}\n`;
|
|
45
|
+
comment += `- ${SEVERITY_EMOJI.MEDIUM} **Medium**: ${summary.bySeverity.MEDIUM}\n`;
|
|
46
|
+
comment += `- ${SEVERITY_EMOJI.LOW} **Low**: ${summary.bySeverity.LOW}\n\n`;
|
|
47
|
+
comment += `### By Category\n`;
|
|
48
|
+
comment += `- ${CATEGORY_EMOJI.SECURITY} **Security**: ${summary.byCategory.SECURITY}\n`;
|
|
49
|
+
comment += `- ${CATEGORY_EMOJI.QUALITY} **Quality**: ${summary.byCategory.QUALITY}\n`;
|
|
50
|
+
comment += `- ${CATEGORY_EMOJI.STYLE} **Style**: ${summary.byCategory.STYLE}\n`;
|
|
51
|
+
comment += `- ${CATEGORY_EMOJI.PERFORMANCE} **Performance**: ${summary.byCategory.PERFORMANCE}\n\n`;
|
|
52
|
+
// List critical and high issues
|
|
53
|
+
const criticalIssues = issues.filter(i => i.severity === 'CRITICAL');
|
|
54
|
+
const highIssues = issues.filter(i => i.severity === 'HIGH');
|
|
55
|
+
if (criticalIssues.length > 0) {
|
|
56
|
+
comment += `## 🔴 Critical Issues\n\n`;
|
|
57
|
+
for (const issue of criticalIssues) {
|
|
58
|
+
comment += `- **${issue.title}** in \`${issue.file}${issue.line ? `:${issue.line}` : ''}\`\n`;
|
|
59
|
+
}
|
|
60
|
+
comment += `\n`;
|
|
61
|
+
}
|
|
62
|
+
if (highIssues.length > 0) {
|
|
63
|
+
comment += `## 🟡 High Priority Issues\n\n`;
|
|
64
|
+
for (const issue of highIssues) {
|
|
65
|
+
comment += `- **${issue.title}** in \`${issue.file}${issue.line ? `:${issue.line}` : ''}\`\n`;
|
|
66
|
+
}
|
|
67
|
+
comment += `\n`;
|
|
68
|
+
}
|
|
69
|
+
comment += `\n---\n`;
|
|
70
|
+
comment += `*Detailed findings have been posted as individual discussion threads on the affected lines.*\n`;
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
comment += `✅ **No issues found!** The code looks good.\n`;
|
|
74
|
+
}
|
|
75
|
+
comment += `\n*Powered by DRS - GitLab Review Bot*\n`;
|
|
76
|
+
return comment;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Format issue for terminal output with colors
|
|
80
|
+
*/
|
|
81
|
+
export function formatTerminalIssue(issue) {
|
|
82
|
+
const emoji = CATEGORY_EMOJI[issue.category];
|
|
83
|
+
const severityEmoji = SEVERITY_EMOJI[issue.severity];
|
|
84
|
+
let output = `\n━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
85
|
+
output += `${severityEmoji} ${issue.severity}: ${emoji} ${issue.category} - ${issue.title}\n`;
|
|
86
|
+
output += `━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n`;
|
|
87
|
+
output += `📁 ${issue.file}${issue.line ? `:${issue.line}` : ''}\n\n`;
|
|
88
|
+
output += `${issue.problem}\n\n`;
|
|
89
|
+
output += `✅ Fix: ${issue.solution}\n`;
|
|
90
|
+
return output;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Calculate review summary from issues
|
|
94
|
+
*/
|
|
95
|
+
export function calculateSummary(filesReviewed, issues) {
|
|
96
|
+
const summary = {
|
|
97
|
+
filesReviewed,
|
|
98
|
+
issuesFound: issues.length,
|
|
99
|
+
bySeverity: {
|
|
100
|
+
CRITICAL: 0,
|
|
101
|
+
HIGH: 0,
|
|
102
|
+
MEDIUM: 0,
|
|
103
|
+
LOW: 0,
|
|
104
|
+
},
|
|
105
|
+
byCategory: {
|
|
106
|
+
SECURITY: 0,
|
|
107
|
+
QUALITY: 0,
|
|
108
|
+
STYLE: 0,
|
|
109
|
+
PERFORMANCE: 0,
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
for (const issue of issues) {
|
|
113
|
+
summary.bySeverity[issue.severity]++;
|
|
114
|
+
summary.byCategory[issue.category]++;
|
|
115
|
+
}
|
|
116
|
+
return summary;
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=comment-formatter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"comment-formatter.js","sourceRoot":"","sources":["../../src/gitlab/comment-formatter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface DiffHunk {
|
|
2
|
+
oldStart: number;
|
|
3
|
+
oldLines: number;
|
|
4
|
+
newStart: number;
|
|
5
|
+
newLines: number;
|
|
6
|
+
lines: DiffLine[];
|
|
7
|
+
}
|
|
8
|
+
export interface DiffLine {
|
|
9
|
+
type: 'add' | 'delete' | 'context';
|
|
10
|
+
content: string;
|
|
11
|
+
oldLineNumber?: number;
|
|
12
|
+
newLineNumber?: number;
|
|
13
|
+
}
|
|
14
|
+
export interface ParsedDiff {
|
|
15
|
+
oldPath: string;
|
|
16
|
+
newPath: string;
|
|
17
|
+
hunks: DiffHunk[];
|
|
18
|
+
isNew: boolean;
|
|
19
|
+
isDeleted: boolean;
|
|
20
|
+
isRenamed: boolean;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Parse a unified diff string into structured format
|
|
24
|
+
*/
|
|
25
|
+
export declare function parseDiff(diffText: string): ParsedDiff[];
|
|
26
|
+
/**
|
|
27
|
+
* Get a list of changed file paths from parsed diff
|
|
28
|
+
*/
|
|
29
|
+
export declare function getChangedFiles(diffs: ParsedDiff[]): string[];
|
|
30
|
+
/**
|
|
31
|
+
* Get added lines from a diff with their line numbers
|
|
32
|
+
*/
|
|
33
|
+
export declare function getAddedLines(diff: ParsedDiff): Array<{
|
|
34
|
+
line: number;
|
|
35
|
+
content: string;
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* Check if a diff contains specific patterns (e.g., for filtering)
|
|
39
|
+
*/
|
|
40
|
+
export declare function diffContainsPattern(diff: ParsedDiff, pattern: RegExp): boolean;
|
|
41
|
+
//# sourceMappingURL=diff-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"diff-parser.d.ts","sourceRoot":"","sources":["../../src/gitlab/diff-parser.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,KAAK,GAAG,QAAQ,GAAG,SAAS,CAAC;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,QAAQ,EAAE,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU,EAAE,CA+GxD;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,MAAM,EAAE,CAK7D;AAED;;GAEG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAexF;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAS9E"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parse a unified diff string into structured format
|
|
3
|
+
*/
|
|
4
|
+
export function parseDiff(diffText) {
|
|
5
|
+
const files = [];
|
|
6
|
+
const lines = diffText.split('\n');
|
|
7
|
+
let currentFile = null;
|
|
8
|
+
let currentHunk = null;
|
|
9
|
+
let oldLineNumber = 0;
|
|
10
|
+
let newLineNumber = 0;
|
|
11
|
+
for (let i = 0; i < lines.length; i++) {
|
|
12
|
+
const line = lines[i];
|
|
13
|
+
// File header: diff --git a/path b/path
|
|
14
|
+
if (line.startsWith('diff --git')) {
|
|
15
|
+
if (currentFile && currentHunk) {
|
|
16
|
+
currentFile.hunks.push(currentHunk);
|
|
17
|
+
}
|
|
18
|
+
if (currentFile) {
|
|
19
|
+
files.push(currentFile);
|
|
20
|
+
}
|
|
21
|
+
currentFile = {
|
|
22
|
+
oldPath: '',
|
|
23
|
+
newPath: '',
|
|
24
|
+
hunks: [],
|
|
25
|
+
isNew: false,
|
|
26
|
+
isDeleted: false,
|
|
27
|
+
isRenamed: false,
|
|
28
|
+
};
|
|
29
|
+
currentHunk = null;
|
|
30
|
+
}
|
|
31
|
+
// Old file: --- a/path or --- /dev/null
|
|
32
|
+
if (line.startsWith('---')) {
|
|
33
|
+
if (currentFile) {
|
|
34
|
+
if (line === '--- /dev/null') {
|
|
35
|
+
currentFile.isNew = true;
|
|
36
|
+
currentFile.oldPath = '/dev/null';
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
currentFile.oldPath = line.substring(6); // Remove '--- a/'
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// New file: +++ b/path or +++ /dev/null
|
|
44
|
+
if (line.startsWith('+++')) {
|
|
45
|
+
if (currentFile) {
|
|
46
|
+
if (line === '+++ /dev/null') {
|
|
47
|
+
currentFile.isDeleted = true;
|
|
48
|
+
currentFile.newPath = '/dev/null';
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
currentFile.newPath = line.substring(6); // Remove '+++ b/'
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Hunk header: @@ -oldStart,oldLines +newStart,newLines @@
|
|
56
|
+
if (line.startsWith('@@')) {
|
|
57
|
+
if (currentFile && currentHunk) {
|
|
58
|
+
currentFile.hunks.push(currentHunk);
|
|
59
|
+
}
|
|
60
|
+
const match = line.match(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
|
|
61
|
+
if (match) {
|
|
62
|
+
oldLineNumber = parseInt(match[1]);
|
|
63
|
+
newLineNumber = parseInt(match[3]);
|
|
64
|
+
currentHunk = {
|
|
65
|
+
oldStart: oldLineNumber,
|
|
66
|
+
oldLines: match[2] ? parseInt(match[2]) : 1,
|
|
67
|
+
newStart: newLineNumber,
|
|
68
|
+
newLines: match[4] ? parseInt(match[4]) : 1,
|
|
69
|
+
lines: [],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Diff line content
|
|
74
|
+
if (currentHunk && line.length > 0) {
|
|
75
|
+
if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
76
|
+
currentHunk.lines.push({
|
|
77
|
+
type: 'add',
|
|
78
|
+
content: line.substring(1),
|
|
79
|
+
newLineNumber: newLineNumber++,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
else if (line.startsWith('-') && !line.startsWith('---')) {
|
|
83
|
+
currentHunk.lines.push({
|
|
84
|
+
type: 'delete',
|
|
85
|
+
content: line.substring(1),
|
|
86
|
+
oldLineNumber: oldLineNumber++,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else if (line.startsWith(' ')) {
|
|
90
|
+
currentHunk.lines.push({
|
|
91
|
+
type: 'context',
|
|
92
|
+
content: line.substring(1),
|
|
93
|
+
oldLineNumber: oldLineNumber++,
|
|
94
|
+
newLineNumber: newLineNumber++,
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Push last hunk and file
|
|
100
|
+
if (currentFile && currentHunk) {
|
|
101
|
+
currentFile.hunks.push(currentHunk);
|
|
102
|
+
}
|
|
103
|
+
if (currentFile) {
|
|
104
|
+
files.push(currentFile);
|
|
105
|
+
}
|
|
106
|
+
return files;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Get a list of changed file paths from parsed diff
|
|
110
|
+
*/
|
|
111
|
+
export function getChangedFiles(diffs) {
|
|
112
|
+
return diffs
|
|
113
|
+
.filter(d => !d.isDeleted)
|
|
114
|
+
.map(d => d.newPath)
|
|
115
|
+
.filter(path => path !== '/dev/null');
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Get added lines from a diff with their line numbers
|
|
119
|
+
*/
|
|
120
|
+
export function getAddedLines(diff) {
|
|
121
|
+
const added = [];
|
|
122
|
+
for (const hunk of diff.hunks) {
|
|
123
|
+
for (const line of hunk.lines) {
|
|
124
|
+
if (line.type === 'add' && line.newLineNumber) {
|
|
125
|
+
added.push({
|
|
126
|
+
line: line.newLineNumber,
|
|
127
|
+
content: line.content,
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return added;
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Check if a diff contains specific patterns (e.g., for filtering)
|
|
136
|
+
*/
|
|
137
|
+
export function diffContainsPattern(diff, pattern) {
|
|
138
|
+
for (const hunk of diff.hunks) {
|
|
139
|
+
for (const line of hunk.lines) {
|
|
140
|
+
if (line.type === 'add' && pattern.test(line.content)) {
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=diff-parser.js.map
|