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
-
Load
GITLAB_TOKEN
(highly recommended)For this create a file called
.env
in the project rootfrom dotenv import load_dotenvload_dotenv()GITLAB_TOKEN = os.environ["GITLAB_TOKEN"] -
Setup variables
Setting up necessary constants for the script.
GITLAB_URL = 'http://gitlab.example.com:8929' # update the gitlab link hereNAMESPACE = "basdemo" # update namespace here it could also be <group_name>/<sub_group_name>PROJECT_NAME = "batch-file-executor"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_branchNEW_BRANCH = "add_new_branch" # update branch name here#check if the branch exists, if not create itif 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 -
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 > Tokensfrom dotenv import load_dotenvimport os
load_dotenv()
GITLAB_TOKEN = os.environ["GITLAB_TOKEN"]
## Setup variablesimport gitlabimport base64
GITLAB_URL = 'http://gitlab.example.com:8929' # Update the gitlab link here
NAMESPACE = "basdemo"PROJECT_NAME = "automatic-mr"ASSIGNEE_USERNAME = "basdemo"
## Authenticate with Gitlabgl = gitlab.Gitlab(GITLAB_URL, private_token=GITLAB_TOKEN)
## Get the projectPROJECT_ID = f"{NAMESPACE}/{PROJECT_NAME}"project = gl.projects.get(PROJECT_ID)
## Create a new branch from default branchMAIN_BRANCH = project.default_branchNEW_BRANCH = "add_new_branch" # update branch name here
#check if the branch exists, if not create itif 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 IDuser = 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 filewith open(local_file, 'r') as file: file_content = file.read()
# Check if the file exists, if not, create ittry: 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 contentreadme_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 contentupdated_content = readme_content.replace(old_text, new_text)file.content = updated_contentfile.encoding = 'text'
# Append to the filesfiles.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-requestmerge_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}")
GITLAB_TOKEN=<your-token-here>
{ "string": "Text", "number": 1, "boolean": true}