疫情后对产品研发工作的最大影响,是随着经济下行,公司在不停地裁员,导致研发团队人力资源严重不足。 事情多得做不完,过去还在定期组织的质量控制手段–code review,现在也忙得没有时间组织了。
早就听说*-coder系列开源大模型在编码方便挺强悍,于是决定尝试使用本地大模型加入到CICD流程中,在团队提交代码的时候,由AI进行code review工作。
我们的源代码管理环境使用gitea,只要配置workflow工作流就可以了。在工作流中把diff信息交给本地编程大模型进行评估,并把结果输出,根据结果决定后续行为。
所以,我们需要:
我们倒序进行实现。
参考《LLM:使用Ollama访问本地大模型》,我们使用Ollama搭建本地编程大模型服务。
curl -fsSL https://ollama.com/install.sh | shollama serve
编程大模型这里选择口碑极好的qwen3-coder:30b
ollama pull qwen3-coder:30b使用Python调用ollama非常容易,但是考虑到gitea的runner是一个docker环境,在同一的镜像中,运行Python和相关的库需要从网络拉取依赖包会导致一些麻烦。所以这里使用go静态编译,直接生成一个bin文件放在本地文件服务器上,runner直接拉取一个bin就可以工作,不需要任何依赖环境,流程更简洁速度也更快。
定义本地ollama地址和模型
var (ollamaURL = getEnv("OLLAMA_ENDPOINT", "http://ai.internal:11434")model = "qwen3-coder:30b")
获取diff信息:
funcgetGitDiff() (string, error) {cmd := exec.Command("git", "diff", "HEAD^", "HEAD")output, err := cmd.Output()if err != nil {return "", fmt.Errorf("获取 git diff 失败: %w", err)}return string(output), nil}
最后传递这样一个提示词
你是一个代码质量审查专家。请分析以下 Git Diff 代码变更,并严格按 JSON 格式返回结果。JSON 格式要求:{{ "score": (0-100的整数,代表代码质量和安全性), "summary": "简短的总结", "risks": ["风险点1", "风险点2"], "suggestions": ["改进建议1"]}}代码变更内容:{diff_text}静态编译后,放置在本地文件服务器上
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o ai-codereview ai-codereview.gorsync -vhP ai-codereview user@fileserver:/gitea/action/
现在万事俱备,只欠东风。先找一个不那么重要的项目进行实验,比如testcase项目,
首先在gitea的设置的action中,添加变量
OLLAMA_ENDPOINT=http://ai.internal:11434
然后创建工作流
# 创建工作流mkdir -p .gitea/workflowstouch ai-codereview.yaml在jobs中添加流程:
- name:AI Code Review env: OLLAMA_ENDPOINT:${{ secrets.OLLAMA_ENDPOINT }} run:| curl -sSL http://10.0.1.1/gitea/action/ai-codereview -o /tmp/ai-codereview chmod +x /tmp/ai-codereview /tmp/ai-codereview 2>&1 | tee ai_report.log提交代码,这个项目就已经具有AI智能代码审核功能了。
本次提交的AI评审报告:
---AI评审报告---得分:75总结:代码变更引入了新的AI审核机制,通过调用ollama模型进行代码质量分析。整体结构清晰,但存在安全和可维护性风险。风险:使用硬编码的默认 ollama 地址可能导致配置错误或安全漏洞,从外部 URL 下载可执行文件(/tmp/ai-codereview)存在执行未验证代码的风险,未对AI返回结果做充分校验,可能影响审核逻辑的准确性[结果] ✅ 代码质量合格。创建TUI的helloword代码,提交
--- AI 评审报告 ---得分: 65总结: 代码功能变更但存在安全隐患和可读性问题风险: 使用了非ASCII字符和特殊符号,可能导致终端显示异常或编码问题, 代码可读性差,难以维护和理解原始功能意图[结果] ✅ 代码质量合格。给项目增加个README
--- AI 评审报告 ---得分: 100总结: 本次变更主要涉及工作流名称的修改和README文件的更新,均为非核心代码变更,无安全风险。风险: [结果] ✅ 代码质量合格。
下面编写一个存在CVE漏洞的代码并提交,得到:
--- AI 评审报告 ---得分: 35总结: 代码存在严重安全漏洞,包括路径遍历攻击和不安全的文件操作风险: 路径遍历攻击漏洞:直接使用用户输入的文件名拼接路径,可访问任意文件, 使用已废弃的ioutil.ReadFile函数:应使用os.ReadFile替代, 缺少输入验证和过滤:未对用户输入进行任何安全检查[结果] ❌ 代码质量未达标,拒绝合并!实际效果达到预期
上述实验中使用的方法是通过Push 触发的 Action,代码是进入仓库后才执行的审核,无法实现高危代码拦截。 可以通过gitea的Pull Request工作流(简称PR)来实现合并代码前拦截,思路如下。
在gitea的设置/分支中,做如下设置:
开发流程稍作调整,本地在分支上开发,提交后创建PR,并由AI进行审核,审核通过后才可以合并到main
改进后的流程如下:
开发者 → feature分支 → 创建PR到main → 触发AI审核 → 通过才能合并 ↓ 失败则阻止合并这样就可以防止高危代码进入main分支了。
一些toB的AI商业产品也在做类似的事情,其实自己做一个实现也并不复杂。
实验证明,本地离线大模型确实可以识别风险代码,并对代码问题提出有价值的改进建议,使用4090显卡的话,30b大模型可以秒级完成代码审核(测试代码改动幅度小于一屏的条件下),完全值得你把它放到CICD流程中来。
A photorealistic image of an 18-year-old Asian code reviewer girl in a high-tech office, with a futuristic background.