随着人工智能技术的突飞猛进,我们终于迎来了代码审查的新纪元。
AI技术已被应用于自动化识别代码中的潜在问题,包括但不限于代码风格一致性、潜在的bug、性能问题、安全漏洞等。
通过训练模型识别代码模式和已知问题,AI可以在代码提交到版本控制系统之前或之后自动进行审查。以此提高开发效率和代码质量。
阅读本文将学习到
- AI自动点评的整体流程
gitlab webhook
的基础使用、配置gitlab api
的调用、使用场景及相关字段说明- 网络穿透 工具
ngrok
、localtunnel
的使用 - openai的基础调用
AI自动点评的整体流程
触发AI点评流程图:
流程说明
设置webhook地址
在设置--webhooks
中配置接口(node服务)地址、触发来源,如无webhooks入口需申请相应的权限。
gitlab上创建合并请求
在gitlab上发起合并请求,将触发webhook
。
此时将发起post
请求、并携带相关gitlab
的body
参数进入到上面的配置的node服务
,其中主要用到的参数是body.project(项目信息)
、body.object_attributes(触发的hook类型对应的属性信息)
注意: 在更新或合并请求时也会触发hook,如果只想要创建时触发、需要过滤掉这些情况。
要区分创建、更新或合并操作,可以使用object_attributes
字段中的action
字段。其值有:
open
:表示Merge Request被创建。update
:表示现有的Merge Request被更新。merge
:表示Merge Request被合并。close
:表示Merge Request被关闭
另外在测试webhooks
时会要用到合并状态object_attributes.state
,其值有:
opened
:表示合并请求已被打开,正在等待处理。closed
:表示合并请求已被关闭,但并未合并。merged
:表示合并请求已被接受并合并到目标分支。locked
:表示合并请求因为某些原因被锁定。
过滤具体实现如下:
javascript
const action = body.object_attributes && body.object_attributes.action
const state = body.object_attributes && body.object_attributes.state
// 在gitlab上测试时其值为undefined
const isHookTest = action === undefined && /^opened|merged|closed|locked$/.test(state)
// 满足该条件时拦截(不去请求openai服务)
if(!(action === 'open' || isHookTest) && !query.project_id) {
return
}
如上,只允许以下三种情况去请求openai服务
- 创建合并请求时
- 外部使用Get方法传入project_id直接调用node服务时(本地调试、手动触发)
- gitlab上点击合并请求测试时,此时action===undefined,state值是不固定的
手动触发测试webhook
为什么直接使用本地 IP 可能不行?
- 网络可达性:GitLab 实例必须能够访问 webhook 配置的地址。如果 GitLab 托管在云端或另一个网络环境中,而 webhook 目标地址是本地网络中的 IP 地址,则 GitLab 可能无法直接访问该地址。
- 安全策略:一些网络和托管环境可能出于安全考虑,默认阻止出站连接到内网地址。
在测试时,由于本地node服务地址和gitlab部署的服务器不在同一局域网,将无法触发webhook。此时需要进行本地网络穿透。
本地网络穿透
可实现外网访问,在本地调试时非常有用。场景:如webhook地址、企微告警等第三方配置时无法识别本地localhost的情况下,实现本地实时调试(无需反复发版 )。这里主要介绍两种:ngrok
、localtunnel
,推荐使用localtunnel
、比较稳定,使用ngrok
测试时 有时无法成功触发hook。
ngrok使用简介
安装
brew install ngrok
去官网获取令牌
ngrok官网:dashboard.ngrok.com/tunnels/aut...
设置令牌
ngrok authtoken 授权令牌
启动
后续使用执行该命令即可
yaml
ngrok http 8000
外网访问
查看访问记录
localtunnel使用简介
安装:
npm install -g localtunnel
启动:
css
lt --port 8000
或 使用自定义子域名 启动
css
lt --port 8000 --subdomain yourcustomsubdomain
验证:
访问loca.lt/mytunnelpas...(固定地址)获取到通往外网的隧道密码
外网访问:
默认支持https,本地修改时、自动同步,无需再部署。非常适合本地调试。
node服务处理
调用gitlab api获取到diff信息
创建项目令牌,获取token(用户请求gitlab api):
根据project_id和request_id调用gitlab api获取到diff信息:
javascript
const gitlabAPI = `https://gitlab.com/api/v4/projects/${project_id}/merge_requests/${request_id}/changes`;
const token = 'xxx'
await new Promise((resolve, reject)=>{
request({
url: gitlabAPI,
method: 'GET',
timeout: 3000,
headers: {
'Content-Type': 'application/json',
'Private-Token': token
}
},async (error, response, body) => {
if(error) {
throw new Error(error)
}
// 拿到body
apiOpenAi(body.changes)
})
})
附: 更多使用请阅读gitlab api的文档地址:archives.docs.gitlab.com/15.11/ee/ap...
不同版本的gitlab,其文档会有差异,具体可通过gitlab后台--帮助--进入对应文档
调用openai接口
openai在国内无法直接调用,有两个解决方案
- 设置baseURL,通过baseURL转发调用,比较容易实现
- 将openAI的api部署到国外服务器,本地请求国外服务器接口,由国外服务器去请求openai api即可,其原理也是服务转发而已。
arduino
生成AI实例
const ai = new OpenAI({
baseURL,
apiKey,
timeout: 60000, // 超时时间
});
kotlin
// 获取AI评审内容
const notes = []
for (const change of content) {
// 需要忽略的diff文件
if (
/^(.|public|dist|build)/.test(change.new_path) ||
/(.s?css)$/.test(change.new_path) ||
/package-lock|package.json/.test(change.new_path)
) {
continue;
}
const data = await ai.chat.completions.create({
model: 'gpt-4',
messages: [
{
role: 'system',
// 这里和用户内容都可以做成配置化,以实现不同项目的AI定制
content: '你是资深的程序专家,对用户提供的diff内容进行review,并指出明显的问题、错误',
},
{
role: 'user',
content: change.diff,
},
],
}).catch(console.error);
if(!data) continue
notes.push(data.choices?.[0].message?.content || '');
}
// 除了notes,也可以收集token的使用情况
return notes
在openai调用这里可以做一些处理:
- 过滤掉非必要的文件diff,以减少token损耗
- 可以做成项目定制化(可配置)
- 可以收集token使用情况
- 可以做消耗及反馈和使用情况的统计报表 等
单次调用openai 4的最大输入token数为8192,超过将报错、需要对此做些方案应对:
OpenAI计费情况说明
OpanAI3.5调用api也不是免费的,只是费用相对较低而已。openAI4的收费相对较高,一个大需求diff一次可能要花费好几刀🤔🤣🤗。
因此在使用时务必要控制成本(减少非必要的diff、过滤无需diff的文件【如样式文件、第三方sdk文件、lock文件等】、把控好diff的时机【避免频繁、重复的diff】等)
调用gitlab点评接口
传入AI结果、请求gitlab api点评接口后,AI点评的结果将出现的pr评论区域:
javascript
const url = `https://gitlab.com/api/v4/projects/${project_id}/merge_requests/${request_id}/notes`
request({
url: ,
method: 'POST',
json: {
body: `消费总token: ${_total_tokens}个,输入token:${_prompt_tokens}个,输出token:${_completion_tokens}个。\n AI总耗时:${answer.costTime}ms。 \n;${answer.choices[0].message.content}` ,
id: project_id,
merge_request_iid: request_id
},
headers: {
'Content-Type': 'application/json',
'Private-Token': token
}
}, async (_error, _response, _body) => {
if(_error) {
console.error('ai点评error', error);
return
} else {
console.log('ai点评ok :>> 点评成功');
}
})
gitlab上查看点评结果:
至此,完成AI自动点评的整个过程。 如果有多个项目时,其gitlab的项目令牌需要做成可配置化。可以借助Appollo
、zookeeper
等第三方工具并以项目名称作为key来实现可配置化。也可以将整个过程搬到管理后台(项目展示、AI人设配置、点评结果汇总及展示、手动操作点击触发AI点评),实现完全可控的定制化。
总结
通过将AI集成至GitLab,我们不仅能够提高代码质量,还能极大提升审查效率,从而加速产品迭代过程。
AI自动化代码审查不仅可以提高代码质量,还可以释放开发者的时间,让开发者专注于更重要的任务 。将AI审查集成至GitLab,可以让整个开发流程更加流畅高效。
随着AI技术的不断发展,未来AI在代码审查领域的应用将更加广泛和深入。