Skip to content
Home

Create GITLAB merge request programmatically

Introduction

Here is an easy way to programmatically create a merge-request in GITLAB.

This comes in handy, when you have to update multiple projects simulatenously.

Jump to complete code here

Prepare script environment

I will be using poetry. check out installation details here

Setup a poetry project using the command poetry init

Add the required packages

poetry add python-gitlab python-dotenv

Script

  1. Load GITLAB_TOKEN (highly recommended)

    For this create a file called .env in the project root

    from dotenv import load_dotenv
    load_dotenv()
    GITLAB_TOKEN = os.environ["GITLAB_TOKEN"]
  2. Setup variables

    Setting up necessary constants for the script.

    GITLAB_URL = 'http://gitlab.example.com:8929' # update the gitlab link here
    NAMESPACE = "basdemo" # update namespace here it could also be <group_name>/<sub_group_name>
    PROJECT_NAME = "batch-file-executor"
    ASSIGNEE_USERNAME = "basdemo"
  3. Authenticate with Gitlab

    gl = gitlab.Gitlab(GITLAB_URL, private_token=GITLAB_TOKEN)
  4. Get the project

    PROJECT_ID = f"{NAMESPACE}/{PROJECT_NAME}"
    project = gl.projects.get(PROJECT_ID)
  5. Create a new branch from default branch

    MAIN_BRANCH = project.default_branch
    NEW_BRANCH = "add_new_branch" # update branch name here
    #check if the branch exists, if not create it
    if not any(branch.name == NEW_BRANCH for branch in project.branches.list()):
    project.branches.create({"branch": NEW_BRANCH, "ref": MAIN_BRANCH})
    print(f"Branch '{NEW_BRANCH}' created.")
  6. Get User ID

    user = gl.users.list(username=ASSIGNEE_USERNAME)[0]
    assignee_id = user.id
  7. Create merge-request

    merge_request = project.mergerequests.create({
    "source_branch":NEW_BRANCH,
    "target_branch":MAIN_BRANCH,
    "title":"feat/adding automatic merge request",
    "description":"This merge request is created programmatically",
    "assignee_id": assignee_id
    })
    print(f"Merge Request created: {merge_request.web_url}")

Complete code

Folder structure

  • Directorysrc
    • info.json
  • .env
  • automatic-merge-request.py
  • pyproject.toml
## Load Gitlab Token from User > Prefrence > Tokens
from dotenv import load_dotenv
import os
load_dotenv()
GITLAB_TOKEN = os.environ["GITLAB_TOKEN"]
## Setup variables
import gitlab
import base64
GITLAB_URL = 'http://gitlab.example.com:8929' # Update the gitlab link here
NAMESPACE = "basdemo"
PROJECT_NAME = "automatic-mr"
ASSIGNEE_USERNAME = "basdemo"
## Authenticate with Gitlab
gl = gitlab.Gitlab(GITLAB_URL, private_token=GITLAB_TOKEN)
## Get the project
PROJECT_ID = f"{NAMESPACE}/{PROJECT_NAME}"
project = gl.projects.get(PROJECT_ID)
## Create a new branch from default branch
MAIN_BRANCH = project.default_branch
NEW_BRANCH = "add_new_branch" # update branch name here
#check if the branch exists, if not create it
if not any(branch.name == NEW_BRANCH for branch in project.branches.list()):
project.branches.create({"branch": NEW_BRANCH, "ref": MAIN_BRANCH})
print(f"Branch '{NEW_BRANCH}' created.")
## Get User ID
user = gl.users.list(username=ASSIGNEE_USERNAME)[0]
assignee_id = user.id
## Add files (optional)
files = []
local_file = "src/info.json"
remote_file_path = "demo/info.json"
# Read the file content from local file
with open(local_file, 'r') as file:
file_content = file.read()
# Check if the file exists, if not, create it
try:
file = project.files.get(file_path=remote_file_path, ref=NEW_BRANCH)
print(f"File '{remote_file_path}' already exists in '{NEW_BRANCH}'.")
except gitlab.exceptions.GitlabGetError:
# Create the file in the new branch
files.append({
'action': 'create',
'file_path': remote_file_path,
'content': file_content
})
## Update Readme (optional)
file_path = 'README.md'
file = project.files.get(file_path=file_path, ref=NEW_BRANCH)
# Read the content
readme_content = base64.b64decode(file.content).decode('utf-8')
old_text = "# automatic-mr"
new_text = f"# automatic-mr\n - Adding `info.json` using automatic merge request"
# Update the content
updated_content = readme_content.replace(old_text, new_text)
file.content = updated_content
file.encoding = 'text'
# Append to the files
files.append({
'action': 'update',
'file_path': file_path,
'content': updated_content
})
## Create commit (optional)
if len(files) > 0:
commit_message = 'Update multiple files - info.json and README.md'
commit_data = {
'branch': NEW_BRANCH,
'commit_message': commit_message,
'actions': files,
}
commit = project.commits.create(commit_data)
print(f"Commit created: {commit.id} - {commit_message}")
## Create merge-request
merge_request = project.mergerequests.create({
"source_branch":NEW_BRANCH,
"target_branch":MAIN_BRANCH,
"title":"feat/adding automatic merge request",
"description":"This merge request is created programmatically",
"assignee_id": assignee_id
})
print(f"Merge Request created: {merge_request.web_url}")