最近公司机房建立了gpt模型,可以好好玩耍了,于是乎最近都在搞基建的我,有了个想法:
通过AI 对 Merge Requests 进行 Code Review
一、通过 Webhooks 接收 Merge Requests 通知
我们的代码管理工具是gitlab
,所以,我首先想到的,自然是通过gitlab webhooks
的能力进行合并请求消息通知。
1. 写一个应用
既然使用到webhooks
,自然需要有一个应用进行接收,那这里我采用了nestjs
进行构建(没有为什么,单纯快,spring风格,既装既用)。
webhook.controller
ts
@Controller(`/webhook`)
export class WebhookController {
constructor(private readonly webhookService: WebhookService) {}
@Post('/code-review')
postCodeReview(): string {
return this.webhookService.codeReview();
}
}
webhook.service
ts
@Injectable()
export class WebhookService {
async codeReview(): Promise<string> {
// todo
}
}
2. 接收 Merge Requests 通知
在webhooks
的选择中,我们选择通过合并请求事件
触发webhooks
:
当开发发起 Merge Requests
时,gitlab
会调用 webhooks
, 并将合并请求信息通过bodyJson
的形式发送到服务器:
那这里我们就可以使用body
进行接收合并信息了:
webhook.controller
ts
type CodeReviewDto = {
project: {
id: string;
};
object_attributes: {
id: number;
iid: number;
action: 'open' | 'approved' | 'merge';
};
};
@Controller(`/webhook`)
export class WebhookController {
constructor(private readonly webhookService: WebhookService) {}
@Post('/code-review')
postCodeReview(@Body() codeReviewDto: CodeReviewDto): string {
return this.webhookService.codeReview(codeReviewDto);
}
}
而通过调研 gitlab api
文档,这里我们需要获取此次请求所有的变更,那么我们需要使用到以下API
bash
projects/${projectId}/merge_requests/${mergerequestIId}/changes
这里我使用了 @gitbeaker/rest
这个库进行获取:
ts
import { Gitlab } from '@gitbeaker/rest';
const gl = new Gitlab({
host: 'gitlab.com', // gitlab 地址
token: 'xxxxxxx', // private token,在gitlab个人设置那获取
queryTimeout: 60000, // 超时时间
});
const mergeRequest: MergeRequestChangesSchema = await gl.MergeRequests.showChanges(projectId, mergeRequestIId);
console.log(mergeRequest.changes);
changes示例:
到这里,我们就可以获取到本次提交的所有代码变更了
二、对代码变更片段进行Code Review
有了代码变更片段,我们就可以对diff
代码进行 Ai Code Review
了
1. AI Code Review 测试
这里由于公司有本地模型,所以我使用的是机房的openai
地址
对本地模型搭建有兴趣的,可以去了解下OneAPI
这里主要是通过使用 openai
的库获取review
后的信息:
ts
import OpenAI from "openai";
const ai = new OpenAI({
baseURL: 'openai 地址',
apiKey: "openai 密钥",
timeout: 60000, // 超时时间
});
const change = `
function add(a, b) {
return a * b;
}
add(1, 3); // 6
`;
const data = await ai.chat.completions.create({
model: "gpt4",
messages: [
{
role: "system",
content: "你是一位资深的编程专家,负责代码变更的审查工作。麻烦给出审查建议并给出修改后的内容,反馈的内容请使用的markdown格式。",
},
{ role: "user", content: `请对这部分代码变更${change}进行review。` },
],
});
const answer = data.choices?.[0].message?.content || "";
console.log(answer);
返回的answer:
当然这里,我们也可以也可以用不同的角色来review
,比如天才小女孩:
ts
messages: [
{
role: "system",
content: "你是一个天才小女孩,精通前端编程工作,性格很傲娇又高傲,负责对前辈的代码变更进行审查,用后辈的态度、活泼轻快的方式的指出存在的问题。使用markdown格式。可以包含emoji。",
},
{
role: "user",
content: `请对这部分代码变更${change}进行review。`
},
],
返回的answer:
2. 将review结果评论到Merge Requests中
这里我们依然是使用 @gitbeaker/rest
库进行评论:
bash
${projectId}/merge_requests/${mergeRequestIId}/notes`,
webhook.service
ts
@Injectable()
export class WebhookService {
async codeReview(): Promise<string> {
const gl = new Gitlab({
host: 'gitlab.com', // gitlab 地址
token: 'xxxxxxx', // private token,在gitlab个人设置那获取
queryTimeout: 60000, // 超时时间
});
// 获取合并信息
const mergeRequest: MergeRequestChangesSchema = await gl.MergeRequests.showChanges(projectId, mergeRequestIId);
// 开始ai review
const ai = new OpenAI({
baseURL: 'openai 地址',
apiKey: "openai 密钥",
timeout: 60000, // 超时时间
});
const reviewNotes: string[] = [];
for (const change of mergeRequest.changes) {
const chatCompletion: ChatCompletion = await ai.chat.completions.create({
model: 'chatglm2',
messages: [
{
role: 'system',
content: "你是一位资深的编程专家,负责代码变更的审查工作。麻烦给出审查建议并给出修改后的内容,反馈的内容请使用的markdown格式。",
},
{
role: 'user',
content: `请对这部分代码变更${change.diff}进行review。`,
},
],
});
reviewNotes.push(data.choices?.[0].message?.content || "");
}
return await gl.MergeRequestNotes.create(projectId, mergeRequestIId, reviewNotes.join('\n\n---\n\n'));
}
}
效果如下:
以上就是基于GPT,对Merge Requests进行Code Review 的应用部分了,这里只涉及到webhook应用,下一篇,我会说下在部署该应用时遇到的问题。