基于 GitLab CI/CD 与 Google Gemini 的 AI Code Review 自动化方案

项目成果演示:

1. 方案摘要

本方案旨在解决手动代码审查(Code Review)耗时耗力、标准不一的问题。通过利用 GitLab 自带的 CI/CD 功能,在开发者创建合并请求(Merge Request, MR)时自动触发一个流水线任务。该任务会提取 MR 中的代码变更,调用 Google Gemini Pro 模型的 API 进行分析,并将 AI 生成的审查意见以评论的形式自动发布回 MR 页面,从而为人工审查提供有价值的参考,提升代码质量和团队效率。

1.1 核心目标

  • 自动化:MR 创建或更新时,自动触发代码审查,无需人工干预。
  • 智能化:利用大语言模型的代码理解能力,发现潜在的 Bug、性能问题、不规范写法和安全漏洞。
  • 效率化:AI 优先进行第一轮审查,帮助人类审查者快速抓住重点,缩短整体审查周期。
  • 低成本:方案初期采用 Google 提供的免费 API 配额,无需支付额外费用即可验证其价值。

1.2 技术选型

  • 代码托管与CI/CD:GitLab
  • AI 模型服务:Google Gemini API (使用 gemini-1.5-flash-latest 模型,兼具速度与性能,且有慷慨的免费额度)
    • 需要确保gitlab的服务器能访问到google的服务
  • 执行环境:GitLab Runner 上的 Docker 环境 (使用官方 python:3.9-slim 镜像)
  • 核心脚本:Python 3

1.3 方案架构与流程

  1. 开发者提交代码到特性分支,并向主分支发起一个 Merge Request。
  2. GitLab 收到 MR 事件,根据 .gitlab-ci.yml 的配置,触发 CI/CD 流水线。
  3. GitLab Runner 启动一个名为 ai_code_review 的 Job。
  4. Job 内部执行 Python 脚本,脚本通过 GitLab API 获取该 MR 的代码变更(Diff)。
  5. 脚本将代码变更与预设的 Prompt(指令)结合,向 Google Gemini API 发起请求。
  6. Gemini API 返回分析结果(审查意见)。
  7. 脚本接收结果,并再次调用 GitLab API,将审查意见作为一条 Comment 发布到原始 MR 中。
  8. 开发者和审查者在 MR 页面直接看到 AI 的反馈。

2. 实施步骤

阶段一:准备工作

1. 获取 Google Gemini API 密钥:

  • 访问 Google AI Studio。
  • 使用 Google 账号登录。
  • 点击 "Get API key" -> "Create API key in new project"。
  • 立即复制并妥善保管生成的 API 密钥。

2. 获取 GitLab Access Token:

  • 登录 GitLab 账号。
  • 进入 右上角头像 -> Preferences -> Access Tokens。
  • Token name: ai_code_reviewer (或任何其他名字)。
  • Expiration date: 建议设置一个有效期。
  • Select scopes: 勾选 api 权限。api 权限已包含读取仓库和写入评论所需的所有权限。
  • 点击 "Create personal access token"。
  • 立即复制并妥善保管生成的 Token。

阶段二:GitLab 项目配置

进入需要集成此功能的 GitLab 项目:

  1. 导航到 Settings -> CI/CD。
  2. 展开 Variables 部分。
  3. 点击 "Add variable" 添加以下两个变量,用于安全地存储密钥:
  • Key: GEMINI_API_KEY
    • Value: [粘贴从 Google AI Studio 获取的 API 密钥]
    • Flags: 勾选 Protect variable 和 Mask variable。
  • Key: GITLAB_ACCESS_TOKEN
    • Value: [粘贴从 GitLab 创建的 Access Token]
    • Flags: 勾选 Protect variable 和 Mask variable。

阶段三:创建核心脚本和CI配置文件

在的项目代码库的根目录下,创建以下两个文件:

  1. 审查脚本: ai_review.py
python 复制代码
import os
import requests
import json

# --- 1. 从 CI/CD 环境变量中获取配置 ---
GITLAB_API_URL = os.environ.get("CI_API_V4_URL")
PROJECT_ID = os.environ.get("CI_PROJECT_ID")
MR_IID = os.environ.get("CI_MERGE_REQUEST_IID")
GITLAB_TOKEN = os.environ.get("GITLAB_ACCESS_TOKEN")
# 修改为 DeepSeek 的 API Key
DEEPSEEK_API_KEY = os.environ.get("DEEPSEEK_API_KEY")

def check_env_vars():
    """检查所有必要的环境变量是否存在"""
    if not all([GITLAB_API_URL, PROJECT_ID, MR_IID, GITLAB_TOKEN, DEEPSEEK_API_KEY]):
        print("Error: Missing one or more required environment variables.")
        exit(1)

# --- 2. 与 GitLab API 交互 (无变动) ---
def get_mr_changes():
    url = f"{GITLAB_API_URL}/projects/{PROJECT_ID}/merge_requests/{MR_IID}/changes"
    headers = {"PRIVATE-TOKEN": GITLAB_TOKEN}
    try:
        response = requests.get(url, headers=headers, timeout=20)
        response.raise_for_status()
        changes = response.json().get('changes', [])
        return "\n".join([change['diff'] for change in changes])
    except requests.exceptions.RequestException as e:
        print(f"Error fetching MR changes from GitLab: {e}")
        return None

def post_review_to_gitlab(comment):
    url = f"{GITLAB_API_URL}/projects/{PROJECT_ID}/merge_requests/{MR_IID}/notes"
    headers = {"PRIVATE-TOKEN": GITLAB_TOKEN}
    body = f"🤖 **AI Code Review (DeepSeek)** 报告:\n\n---\n\n{comment}"
    data = {"body": body}
    try:
        response = requests.post(url, headers=headers, data=data, timeout=20)
        response.raise_for_status()
        print("Successfully posted AI review comment to GitLab MR.")
    except requests.exceptions.RequestException as e:
        print(f"Error posting comment to GitLab: {e}")

# --- 3. 调用 DeepSeek API 进行审查 (核心替换部分) ---
def call_deepseek_api(code_diff):
    """调用 DeepSeek API 对代码 diff 进行审查"""
    api_url = "https://api.deepseek.com/chat/completions"

    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {DEEPSEEK_API_KEY}"
    }

    # Prompt 保持不变,但可以针对 Coder 模型进行微调
    prompt = f"""
    你是一名世界级的软件工程师和代码审查专家,对代码质量有近乎完美的苛刻要求。请严格、细致地审查以下代码变更(diff格式)。

    你的任务是:
    1.  **识别潜在的 Bug**:比如空指针、逻辑错误、边界条件问题。
    2.  **发现性能问题**:比如不必要的循环、低效的算法。
    3.  **检查代码风格和可读性**:是否遵循通用编码规范,命名是否清晰,注释是否必要。
    4.  **识别安全漏洞**:比如 SQL 注入、跨站脚本等。
    5.  **提出具体的改进建议**:对于每一个发现的问题,请提供清晰的解释,并给出"修改前"和"修改后"的代码片段对比,以便开发者能直接采纳你的建议。

    请以清晰的 Markdown 格式返回你的审查意见。如果发现多个问题,请用列表形式呈现。
    如果代码质量很高,没有发现任何问题,请回复 "代码质量非常高,未发现明显问题。LGTM! 👍"。

    以下是需要审查的代码变更:
    ```diff
    {code_diff}
    ```
    """

    payload = {
        "model": "deepseek-coder",  # 使用 DeepSeek 的代码专用模型
        "messages": [
            {"role": "user", "content": prompt}
        ],
        "temperature": 0.1, # 让输出更稳定、严谨
        "max_tokens": 4096,
        "stream": False
    }

    try:
        response = requests.post(api_url, headers=headers, data=json.dumps(payload), timeout=60) # 延长超时时间
        response.raise_for_status()
        result = response.json()
        review_content = result['choices'][0]['message']['content']
        return review_content
    except requests.exceptions.RequestException as e:
        detailed_error_message = f"**错误: 请求 DeepSeek API 失败。**\n\n**详情:**\n```\n{str(e)}\n```"
        print(f"Error calling DeepSeek API: {e}")
        return detailed_error_message
    except (KeyError, IndexError) as e:
        detailed_error_message = f"**错误: 解析 DeepSeek API 响应失败。**\n\n**详情:**\n```\n{str(e)}\n```\n**原始响应:**\n```\n{response.text}\n```"
        print(f"Error parsing DeepSeek response: {e}")
        return detailed_error_message


# --- 4. 主执行逻辑 (调用新函数) ---
if __name__ == "__main__":
    check_env_vars()
    print("Starting AI Code Review process with DeepSeek...")
    diff_content = get_mr_changes()

    if not diff_content or not diff_content.strip():
        print("No code changes found in this MR. Exiting.")
        exit(0)

    print("Fetching review from DeepSeek AI...")
    review_result = call_deepseek_api(diff_content) # 调用新的函数

    if review_result:
        post_review_to_gitlab(review_result)
    else:
        post_review_to_gitlab("从 DeepSeek AI 未获取到有效的审查结果。")
        exit(1)
  1. CI/CD 配置文件: .gitlab-ci.yml
yaml 复制代码
stages:
  - review

.python-base:
  image: python:3.9-slim
  before_script:
    # 使用阿里云的镜像源在线安装依赖
    - pip install -i https://mirrors.aliyun.com/pypi/simple/ requests

ai_code_review:
  extends: .python-base
  stage: review
  script:
    - python ai_review.py
  rules:
    # ------------------- 核心修正部分 -------------------
    # 将 CI_PIPILINE_SOURCE 修正为 CI_PIPELINE_SOURCE
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
   

阶段四:部署与测试

  1. 将 ai_review.py 和 .gitlab-ci.yml 这两个文件提交到的项目代码库的主分支。
  2. 从主分支创建一个新的特性分支,例如 feature/test-code-review。
  3. 在该分支上做一些代码修改。可以故意写一些有小问题的代码,比如:
  • 一个永远不会退出的循环。
  • 一个变量命名为 data1,data2。
  • 硬编码的密钥或密码。
  1. 提交并推送的特性分支。

  2. 在 GitLab UI 上,为这个分支创建一个新的 Merge Request。

  3. 创建 MR 后,GitLab 会自动启动一个新的流水线。

  4. 可以点击 MR 页面的 "Pipelines" 标签页,查看 ai_code_review job 的运行状态和日志。

  5. 几分钟后,刷新 MR 页面,在 "Overview" 页面的评论区看到一个来自的账户(因为用了你的 Token)、由 AI 生成的代码审查报告。

  6. 进阶与优化

  • Prompt 优化: ai_review.py 脚本中的 prompt 是整个系统的核心。可以根据团队的技术栈(如 Java, Go, Frontend)和编码规范,对 Prompt 进行深度定制,以获得更精准的审查结果。
  • 触发控制: 如果不希望每次提交都触发,可以修改 .gitlab-ci.yml 的 rules。例如,只在 MR 添加了特定标签(如 ai-review)时才运行。
  • 成本管理: 当决定从免费额度转向付费后,为了控制成本,可以进一步限制 diff 的大小,或者只对指向 main/master 分支的 MR 进行审查。
  • 通知: 可以或其他通知工具,在 AI 审查脚本执行失败时发送警报。
相关推荐
koo3644 小时前
李宏毅机器学习笔记17
人工智能·笔记·机器学习
心无旁骛~4 小时前
PIL与OpenCV图像读取的颜色格式陷阱:RGB vs BGR
人工智能·opencv·计算机视觉
程序员大雄学编程4 小时前
「深度学习笔记1」深度学习全面解析:从基本概念到未来趋势
人工智能·笔记·深度学习
sensen_kiss4 小时前
INT305 Machine Learning 机器学习 Pt.4
人工智能·机器学习
WWZZ20254 小时前
快速上手大模型:机器学习1
人工智能·深度学习·机器学习·计算机视觉·机器人·slam
沫儿笙5 小时前
川崎焊接机器人弧焊气体节约
人工智能·机器人
新知图书5 小时前
多模态大模型的应用场景
人工智能·大模型应用开发·大模型应用
Giser探索家5 小时前
遥感卫星升轨 / 降轨技术解析:对图像光照、对比度的影响及工程化应用
大数据·人工智能·算法·安全·计算机视觉·分类
Mr数据杨5 小时前
【ComfyUI】Animate单人物角色视频替换
人工智能·计算机视觉·音视频