-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
executable file
·247 lines (207 loc) · 7.61 KB
/
server.js
File metadata and controls
executable file
·247 lines (207 loc) · 7.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
const express = require("express");
const crypto = require("crypto");
const axios = require("axios"); // For making HTTP requests
const nodemailer = require("nodemailer"); // For sending email notifications
const marked = require("marked"); // For converting markdown to HTML
require("dotenv").config();
const mongoose = require("mongoose");
const cors = require("cors");
const app = express();
const corsOpt = {
origin: ["http://localhost:5173", "http://host.docker.internal:5173", "http://frontend:5173"],
methods: "*",
};
app.use(cors(corsOpt));
const port = process.env.PORT;
const secret = process.env.SECRET;
const LM_STUDIO_URL = process.env.LM_STUDIO_URL;
const MONGODB_URI = process.env.MONGODB_URI;
const APP_PASS = process.env.APP_PASS;
// Replace with LM Studio's actual endpoint
// Middleware to capture the raw body for signature verification
app.use(
express.json({
verify: (req, res, buf, encoding) => {
req.rawBody = buf;
},
})
);
// Connect to MongoDB
mongoose
.connect(MONGODB_URI, {
useNewUrlParser: true,
useUnifiedTopology: true,
})
.then(() => console.log("Connected to MongoDB"))
.catch((err) => console.error("MongoDB connection error:", err));
// Define the schema for a code review document
const codeReviewSchema = new mongoose.Schema({
repository: { type: String, required: true },
commit: { type: String, required: true },
author: { type: String, required: true },
message: { type: String },
findings: { type: String },
createdAt: { type: Date, default: Date.now },
});
// Define the model using the schema, which will be stored in the "code_reviews" collection
const CodeReview = mongoose.model(
"CodeReview",
codeReviewSchema,
"code_reviews"
);
function generateHTMLReport(reviewData) {
// Parse markdown to HTML for the review findings
const findingsHtml = marked.parse(reviewData.findings);
return `
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Code Review Report</title>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
h1 { text-align: center; }
.section { margin-bottom: 20px; }
.section h2 { border-bottom: 1px solid #ccc; }
</style>
</head>
<body>
<h1>Code Review Report</h1>
<div class="section">
<h2>Repository Details</h2>
<p><strong>Repository:</strong> ${reviewData.repository}</p>
<p><strong>Commit:</strong> ${reviewData.commit}</p>
<p><strong>Author:</strong> ${reviewData.author}</p>
<p><strong>Message:</strong> ${reviewData.message}</p>
</div>
<div class="section">
<h2>Review Findings</h2>
${findingsHtml}
</div>
</body>
</html>
`;
}
// get for health check
app.get("/", (req, res) => {
res.send("Server is running");
});
app.post("/webhook", async (req, res) => {
const signature = req.headers["x-hub-signature-256"];
if (!signature) {
return res.status(400).send("Missing signature");
}
// Verify signature
const hmac = crypto.createHmac("sha256", secret);
hmac.update(req.rawBody);
const expected = "sha256=" + hmac.digest("hex");
if (signature !== expected) {
return res.status(403).send("Forbidden");
}
console.log("Webhook received:", req.body);
// Extract necessary GitHub webhook payload data
const { repository, head_commit } = req.body;
const codeDiff =
head_commit && head_commit.modified
? head_commit.modified.join("\n")
: "No modified files data available";
const prompt = `
You are an expert code reviewer with extensive experience in analyzing commit changes in large-scale software projects. Your task is to thoroughly examine the following commit, which includes modifications across various parts of the codebase. Please provide a detailed, structured review that covers the following areas:
1. Potential Bugs & Logical Errors:
- Identify any bugs or unexpected behavior introduced by the changes.
- Highlight areas where the logic might be flawed or error-prone.
2. Code Quality & Best Practices:
- Assess the overall readability, maintainability, and consistency of the code.
- Evaluate adherence to coding standards and best practices.
- Note any areas that could benefit from improved documentation or clearer variable/method naming.
3. Performance Optimizations:
- Suggest improvements for optimizing performance, including algorithmic enhancements and resource management.
- Identify any inefficient code patterns that could be refactored.
4. Security Considerations:
- Point out potential security vulnerabilities or risky patterns.
- Recommend any changes to bolster the security posture of the code.
5. Refactoring & Future Improvements:
- Provide actionable recommendations for refactoring, if needed.
- Suggest potential enhancements for future-proofing the codebase.
Your review should be precise, objective, and actionable, ensuring that the commit not only meets current functional requirements but also sets a solid foundation for long-term code quality and performance improvements.
Repository: ${repository.full_name}
Commit: ${head_commit?.id}
Author: ${head_commit?.author?.name}
Message: ${head_commit?.message}
Changed Files:
${codeDiff}
`;
const codeReviewPayload = {
prompt: prompt,
};
try {
const response = await axios.post(LM_STUDIO_URL, codeReviewPayload);
const reviewFindings = response.data.choices[0].text;
const reviewData = {
repository: repository.full_name,
commit: head_commit?.id,
author: head_commit?.author?.name,
message: head_commit?.message,
findings: reviewFindings,
};
const newReview = new CodeReview(reviewData);
newReview.save();
const htmlReport = generateHTMLReport(reviewData);
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: "saivedant2805@gmail.com",
pass: APP_PASS,
},
});
const mailOptions = {
from: "saivedant2805@gmail.com",
to: "saivedant169@gmail.com",
subject: "Automated Code Review Report",
text: "Please find attached the latest code review report.",
html: htmlReport,
};
await transporter.sendMail(mailOptions);
res.status(200).send("Code review triggered successfully");
} catch (error) {
console.error("Error triggering code review:", error.message);
res.status(500).send("Error triggering code review");
}
});
//https://github.com/saivedant169/spring-2025-cps518
app.get("/repo-metrics", async (req, res) => {
const { owner, repo } = req.query;
if (!owner || !repo) {
return res.status(400).send("Missing owner or repo parameter");
}
try {
const pullRequestsResponse = await axios.get(
`https://api.github.com/repos/${owner}/${repo}/pulls?state=all&per_page=200`
);
const numberOfPullRequests = pullRequestsResponse.data.length;
const commitsResponse = await axios.get(
`https://api.github.com/repos/${owner}/${repo}/commits?per_page=200`
);
console.log(commitsResponse.data);
const numberOfCommits = commitsResponse.data.length;
res.json({
numberOfPullRequests,
numberOfCommits,
});
} catch (error) {
console.error("Error fetching repository metrics:", error.message);
res.status(500).send("Error fetching repository metrics");
}
});
app.get("/code-reviews", async (req, res) => {
try {
const reviews = await CodeReview.find({}).sort({ createdAt: -1 });
res.status(200).json(reviews);
} catch (error) {
console.error("Error fetching code reviews:", error);
res.status(500).send("Error retrieving code reviews");
}
});
app.listen(port, () => {
console.log(`Webhook server listening on port ${port}`);
});