GitLab's REST API is one of the most comprehensive in the DevOps world. You can manage repositories, trigger pipelines, review merge requests, manage issues, and automate your entire development workflow — all for free.
Why Use the GitLab API?
- Automate merge request workflows and code reviews
- Trigger pipelines from external events
- Build custom dashboards for project management
- Integrate GitLab with your existing tools
Getting Started
Get a Personal Access Token from Settings > Access Tokens:
export GITLAB_URL="https://gitlab.com/api/v4"
export GITLAB_TOKEN="glpat-xxxxxxxxxxxx"
# List your projects
curl -s -H "PRIVATE-TOKEN: $GITLAB_TOKEN" "$GITLAB_URL/projects?owned=true&per_page=5" | jq '.[] | {id: .id, name: .name, web_url: .web_url}'
# Get project details
curl -s -H "PRIVATE-TOKEN: $GITLAB_TOKEN" "$GITLAB_URL/projects/12345" | jq '{name: .name, default_branch: .default_branch, star_count: .star_count, forks_count: .forks_count}'
Python Client
import requests
class GitLabClient:
def __init__(self, url='https://gitlab.com', token=None):
self.url = f"{url}/api/v4"
self.headers = {'PRIVATE-TOKEN': token}
def get_projects(self, owned=True, per_page=20):
resp = requests.get(f"{self.url}/projects", params={'owned': owned, 'per_page': per_page}, headers=self.headers)
return resp.json()
def get_pipelines(self, project_id, per_page=10):
resp = requests.get(f"{self.url}/projects/{project_id}/pipelines", params={'per_page': per_page}, headers=self.headers)
return resp.json()
def trigger_pipeline(self, project_id, ref='main', variables=None):
payload = {'ref': ref}
if variables:
payload['variables'] = variables
resp = requests.post(f"{self.url}/projects/{project_id}/pipeline", json=payload, headers=self.headers)
return resp.json()
def get_merge_requests(self, project_id, state='opened'):
resp = requests.get(f"{self.url}/projects/{project_id}/merge_requests", params={'state': state}, headers=self.headers)
return resp.json()
def create_merge_request(self, project_id, source_branch, target_branch, title, description=''):
payload = {
'source_branch': source_branch,
'target_branch': target_branch,
'title': title,
'description': description
}
resp = requests.post(f"{self.url}/projects/{project_id}/merge_requests", json=payload, headers=self.headers)
return resp.json()
def create_issue(self, project_id, title, description='', labels=None):
payload = {'title': title, 'description': description}
if labels:
payload['labels'] = ','.join(labels)
resp = requests.post(f"{self.url}/projects/{project_id}/issues", json=payload, headers=self.headers)
return resp.json()
# Usage
gl = GitLabClient(token='your-token')
# Check pipeline status
for pipeline in gl.get_pipelines(12345):
print(f"Pipeline #{pipeline['id']}: {pipeline['status']} ({pipeline['ref']})")
Pipeline Automation
def deploy_with_approval(gl, project_id, version, environment='production'):
# Trigger deployment pipeline
pipeline = gl.trigger_pipeline(project_id, ref='main', variables=[
{'key': 'DEPLOY_VERSION', 'value': version},
{'key': 'DEPLOY_ENV', 'value': environment}
])
print(f"Pipeline #{pipeline['id']} triggered for {environment}")
# Monitor pipeline
import time
while True:
resp = requests.get(
f"{gl.url}/projects/{project_id}/pipelines/{pipeline['id']}",
headers=gl.headers
)
status = resp.json()['status']
if status in ('success', 'failed', 'canceled'):
print(f"Pipeline {status}!")
return status == 'success'
print(f" Status: {status}...")
time.sleep(10)
deploy_with_approval(gl, 12345, '2.1.0', 'staging')
Merge Request Automation
def auto_review_mr(gl, project_id):
mrs = gl.get_merge_requests(project_id, state='opened')
for mr in mrs:
mr_iid = mr['iid']
# Get MR changes
changes = requests.get(
f"{gl.url}/projects/{project_id}/merge_requests/{mr_iid}/changes",
headers=gl.headers
).json()
# Auto-label based on files changed
labels = set()
for change in changes.get('changes', []):
path = change['new_path']
if path.startswith('src/api/'):
labels.add('api')
elif path.startswith('tests/'):
labels.add('testing')
elif path.endswith('.md'):
labels.add('documentation')
elif 'migration' in path:
labels.add('database')
if labels:
requests.put(
f"{gl.url}/projects/{project_id}/merge_requests/{mr_iid}",
json={'labels': ','.join(labels)},
headers=gl.headers
)
print(f"MR !{mr_iid}: added labels {labels}")
auto_review_mr(gl, 12345)
Issue Management
def create_release_checklist(gl, project_id, version):
checklist = f"""## Release {version} Checklist
- [ ] All tests passing on main
- [ ] Changelog updated
- [ ] Version bumped in package.json
- [ ] Database migrations tested
- [ ] Staging deployment verified
- [ ] Performance benchmarks run
- [ ] Security scan passed
- [ ] Documentation updated
- [ ] Release notes drafted
"""
issue = gl.create_issue(
project_id,
title=f"Release {version}",
description=checklist,
labels=['release', 'process']
)
print(f"Release issue created: {issue['web_url']}")
return issue
create_release_checklist(gl, 12345, '2.1.0')
Real-World Use Case
A platform team built a "deploy bot" using GitLab API. Developers type /deploy staging v2.1 in a merge request comment. The bot triggers the staging pipeline, waits for it to pass, runs smoke tests, and comments back with the deployment URL. Production deploys require two approvals — the bot checks MR approvals before triggering. Deployment friction dropped from 30 minutes to 2 minutes.
What You Can Build
- Deploy bot triggered from MR comments
- Auto-labeler categorizing MRs by files changed
- Release manager automating version bumps and changelogs
- Pipeline dashboard showing build health across all projects
- Compliance checker ensuring MR policies are followed
Need custom DevOps automation? I build CI/CD tools and developer workflows.
Email me: spinov001@gmail.com
Check out my developer tools: https://apify.com/spinov001
Top comments (0)