DEV Community

Cover image for GitLab Merge Review with Ollama [Python]
Pepe
Pepe

Posted on • Edited on

GitLab Merge Review with Ollama [Python]

In today's fast-paced software development world, ensuring high-quality code while keeping up with rapid release cycles can be a challenge. Code reviews play a crucial role in maintaining code quality, but they can also be time-consuming and inconsistent, especially in large teams.

What if you could automate the first layer of code review using AI? By integrating GitLab Merge Request Reviews with Ollama, you can streamline the review process, catch potential issues early, and get AI-powered suggestions for improving your code.

In this blog post, we’ll explore how to build an AI-driven Merge Request reviewer that analyzes code changes, provides structured feedback, and even incorporates context from Jira tasks. Whether you're working with large-scale projects or just looking to enhance your DevOps workflows, this solution can save time and improve overall code quality.

Let’s dive into how you can set up this AI-powered reviewer in GitLab! 🚀


Overview

This setup consists of multiple Python scripts that:

  • Connect to GitLab to fetch Merge Requests and their diffs.
  • Extract Jira ticket references from MRs and retrieve ticket details.
  • Use AI (Ollama) to analyze code changes and generate structured feedback.
  • Post review comments back to GitLab automatically.

Let’s dive into the components that make this work!


1. Connecting to GitLab

The gitlab_client.py script provides a GitLabClient class that interacts with GitLab using the python-gitlab library.

Features:

  • Authenticates with GitLab.
  • Retrieves MR details and diffs.
  • Adds review comments to an MR.
import logging
import gitlab
from config import GITLAB_URL, GITLAB_PRIVATE_TOKEN, GITLAB_PROJECT_ID

class GitLabClient:
    def __init__(self):
        """Gitlab login."""
        self.gl = gitlab.Gitlab(GITLAB_URL, private_token=GITLAB_PRIVATE_TOKEN)
        self.gl.auth()
        self.project = self.gl.projects.get(int(GITLAB_PROJECT_ID))
        logging.info(f"Connected to GitLab project {GITLAB_PROJECT_ID}")

    def get_merge_request(self, mr_id):
        """Fetching Merge Request information."""
        return self.project.mergerequests.get(int(mr_id))

    def get_merge_request_diff(self, mr_id):
        """Fetching diff for the Merge Request."""
        mr = self.get_merge_request(mr_id)
        changes = mr.changes()
        return "\n".join([change["diff"] for change in changes["changes"]])

    def add_comment_to_mr(self, mr_id, comment):
        """Adding a review comment to the Merge Request."""
        mr = self.get_merge_request(mr_id)
        mr.notes.create({"body": comment})
        logging.info(f"Added review comment to MR {mr_id}.")
Enter fullscreen mode Exit fullscreen mode

2. Integrating with Jira

The jira_utils.py script helps extract and retrieve Jira ticket details from MR titles or descriptions.

Features:

  • Extracts Jira ticket IDs from MR titles/descriptions.
  • Fetches issue details from Jira.
import logging
import re
from jira import JIRA
from config import JIRA_URL, JIRA_USER, JIRA_API_TOKEN, JIRA_PROJECT_KEY

# Jira Authentication
jira = None
if JIRA_URL and JIRA_USER and JIRA_API_TOKEN:
    try:
        jira_options = {"server": JIRA_URL}
        jira = JIRA(options=jira_options, basic_auth=(JIRA_USER, JIRA_API_TOKEN))
        logging.info("Connected to Jira successfully.")
    except Exception as e:
        logging.error(f"Failed to connect to Jira: {e}")

# Extract Jira Ticket ID
def extract_jira_ticket(mr_title, mr_description):
    pattern = rf"{JIRA_PROJECT_KEY}-\d+"
    match = re.search(pattern, f"{mr_title} {mr_description}")
    return match.group(0) if match else None

# Get Jira Ticket Details
def get_jira_ticket_details(ticket_id):
    if not jira:
        return None
    try:
        issue = jira.issue(ticket_id)
        return f"Jira Ticket: {ticket_id}\nSummary: {issue.fields.summary}\nDescription: {issue.fields.description}"
    except Exception as e:
        logging.error(f"Failed to fetch Jira details for {ticket_id}: {e}")
        return None
Enter fullscreen mode Exit fullscreen mode

3. AI-Powered Code Review

The main.py script brings everything together. It fetches the MR diff, retrieves Jira context, and uses Ollama to analyze code changes.

Features:

  • Validates required configuration variables.
  • Retrieves MR details and diffs.
  • Fetches Jira ticket context.
  • Generates structured review feedback using AI.
  • Posts comments back to GitLab.
import logging
import ollama
from config import LLM_MODEL, GITLAB_MR_ID
from gitlab_client import GitLabClient
from jira_utils import extract_jira_ticket, get_jira_ticket_details

def review_code(diff, jira_context=None):
    """Analyze code changes with AI."""
    prompt = f"""
    You are a senior software engineer reviewing a code change.
    Analyze the following changes and provide a structured review:
    {diff}
    {f'Jira Context: {jira_context}' if jira_context else ''}
    """
    response = ollama.chat(model=LLM_MODEL, messages=[{"role": "user", "content": prompt}])
    return response["message"]["content"] if response else "No response from AI."

def main():
    logging.info(f"Starting review for MR {GITLAB_MR_ID}.")
    gitlab_client = GitLabClient()
    diff = gitlab_client.get_merge_request_diff(GITLAB_MR_ID)
    if diff:
        jira_ticket = extract_jira_ticket(mr.title, mr.description)
        jira_context = get_jira_ticket_details(jira_ticket) if jira_ticket else None
        review = review_code(diff, jira_context)
        gitlab_client.add_comment_to_mr(GITLAB_MR_ID, review)
Enter fullscreen mode Exit fullscreen mode

4. Configuration & Setup

Environment variables are loaded using config.py, making configuration flexible and secure.

import os
from dotenv import load_dotenv

load_dotenv()

LLM_MODEL = os.getenv("LLM_MODEL")
GITLAB_URL = os.getenv("GITLAB_URL")
GITLAB_PRIVATE_TOKEN = os.getenv("GITLAB_PRIVATE_TOKEN")
GITLAB_PROJECT_ID = os.getenv("GITLAB_PROJECT_ID")
JIRA_URL = os.getenv("JIRA_URL")
JIRA_USER = os.getenv("JIRA_USER")
JIRA_API_TOKEN = os.getenv("JIRA_API_TOKEN")
JIRA_PROJECT_KEY = os.getenv("JIRA_PROJECT_KEY")
Enter fullscreen mode Exit fullscreen mode

Installing Dependencies

pip install -r requirements.txt
Enter fullscreen mode Exit fullscreen mode

Running the Bot

python main.py
Enter fullscreen mode Exit fullscreen mode

Conclusion

This AI-powered GitLab bot streamlines code reviews by automating feedback generation using AI while integrating Jira for issue tracking. With this setup, teams can save time, improve code quality, and maintain better project visibility.

In the next post, we’ll dive into integrating these Python scripts with GitLab CI/CD to automate the review process. We’ll set up a .gitlab-ci.yml pipeline to trigger AI-powered code reviews on every merge request, fetch Jira context, and post structured feedback directly in GitLab. This will streamline the development workflow, ensuring automated and consistent code quality checks.

Sentry image

Hands-on debugging session: instrument, monitor, and fix

Join Lazar for a hands-on session where you’ll build it, break it, debug it, and fix it. You’ll set up Sentry, track errors, use Session Replay and Tracing, and leverage some good ol’ AI to find and fix issues fast.

RSVP here →

Top comments (0)

Some comments may only be visible to logged-in visitors. Sign in to view all comments. Some comments have been hidden by the post's author - find out more

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more