GitLab Duo: GitLab’s suite of AI-powered features including code suggestions, merge request summaries, vulnerability explanations, and automated code review—powered by Anthropic’s Claude and other models.
Tier
AI Features Available
Free
Basic CI/CD, limited Duo
Premium
Duo Chat, MR summaries
Ultimate
Full Duo, security scanning
Option 1: GitLab Duo (Native)
Available on Premium and Ultimate tiers.
Enable GitLab Duo
1
2
3
4
5
6
7
8
# In your GitLab instance settings# Settings → AI Features → Enable GitLab Duo# Or via gitlab-rails consoleGitlab::CurrentSettings.update!(gitlab_duo_enabled:true,duo_features_enabled:true)
# scripts/ai_review.pyimportosimportjsonimportrequestsfromopenaiimportOpenAIdefget_mr_changes():"""Get changed files from GitLab API"""project_id=os.environ["CI_PROJECT_ID"]mr_iid=os.environ["CI_MERGE_REQUEST_IID"]token=os.environ["CI_JOB_TOKEN"]url=f"https://gitlab.com/api/v4/projects/{project_id}/merge_requests/{mr_iid}/changes"headers={"JOB-TOKEN":token}response=requests.get(url,headers=headers)returnresponse.json()["changes"]defanalyze_changes(changes:list)->list:"""Use GPT-4 to analyze code changes"""client=OpenAI()all_issues=[]forchangeinchanges:ifnotchange.get("diff"):continueresponse=client.chat.completions.create(model="gpt-4",messages=[{"role":"system","content":"""Analyze this code diff for:
1. Security vulnerabilities
2. Logic errors
3. Performance issues
Return JSON array of issues with fields:
- line: line number in new file
- severity: critical/high/medium/low
- message: description of issue
- suggestion: how to fix"""},{"role":"user","content":f"File: {change['new_path']}\n\n{change['diff']}"}],response_format={"type":"json_object"})result=json.loads(response.choices[0].message.content)forissueinresult.get("issues",[]):issue["file"]=change["new_path"]all_issues.append(issue)returnall_issuesdefpost_mr_comment(issues:list):"""Post review comments to MR"""project_id=os.environ["CI_PROJECT_ID"]mr_iid=os.environ["CI_MERGE_REQUEST_IID"]token=os.environ["GITLAB_TOKEN"]url=f"https://gitlab.com/api/v4/projects/{project_id}/merge_requests/{mr_iid}/notes"headers={"PRIVATE-TOKEN":token}ifnotissues:body="AI Review: No issues found."else:body="## AI Code Review\n\n"forissueinissues:body+=f"### {issue['file']}:{issue.get('line','?')}\n"body+=f"**{issue['severity'].upper()}**: {issue['message']}\n"ifissue.get("suggestion"):body+=f"\n> Suggestion: {issue['suggestion']}\n"body+="\n"requests.post(url,headers=headers,json={"body":body})defmain():changes=get_mr_changes()issues=analyze_changes(changes)post_mr_comment(issues)# Exit with error if critical issues foundcritical=[iforiinissuesifi["severity"]=="critical"]ifcritical:print(f"Found {len(critical)} critical issues")exit(1)if__name__=="__main__":main()
Discussion Comments on Specific Lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
defpost_line_comment(project_id:str,mr_iid:str,issue:dict,token:str):"""Post comment on specific line of code"""url=f"https://gitlab.com/api/v4/projects/{project_id}/merge_requests/{mr_iid}/discussions"headers={"PRIVATE-TOKEN":token}payload={"body":f"**{issue['severity'].upper()}**: {issue['message']}\n\n{issue.get('suggestion','')}","position":{"base_sha":os.environ["CI_MERGE_REQUEST_DIFF_BASE_SHA"],"start_sha":os.environ["CI_MERGE_REQUEST_DIFF_BASE_SHA"],"head_sha":os.environ["CI_COMMIT_SHA"],"position_type":"text","new_path":issue["file"],"new_line":issue["line"]}}response=requests.post(url,headers=headers,json=payload)returnresponse.status_code==201
Option 3: Security Scanning
GitLab Ultimate includes SAST, DAST, and dependency scanning.
# Require security team approval if vulnerabilities foundsecurity-approval:stage:.postimage:curlimages/curlscript:- | VULNS=$(curl -s --header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/vulnerability_findings?pipeline_id=$CI_PIPELINE_ID" \
| jq '. | length')
if [ "$VULNS" -gt "0" ]; then
echo "Found $VULNS vulnerabilities, requiring security approval"
# Set MR to require security team approval
curl --request PUT \
--header "PRIVATE-TOKEN: $GITLAB_TOKEN" \
"https://gitlab.com/api/v4/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID" \
--data "labels=needs-security-review"
firules:- if:$CI_PIPELINE_SOURCE == "merge_request_event"
Option 4: Third-Party Integrations
CodeRabbit for GitLab
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# Install via GitLab OAuth integration# Then configure in repo# .coderabbit.yamlreviews:auto_review:enabled:truedrafts:falsesecurity:enabled:trueseverity:mediumignore:paths:- "**/*.test.*"- "**/fixtures/**"
# .gitlab-ci.ymlstages:- lint- test- security- ai-review- deploydefault:cache:key:${CI_COMMIT_REF_SLUG}paths:- node_modules/variables:FF_USE_FASTZIP:"true"ARTIFACT_COMPRESSION_LEVEL:"fast"# Fast checkslint:stage:lintimage:node:20-slimscript:- npm ci --prefer-offline- npm run lint- npm run typecheckrules:- if:$CI_PIPELINE_SOURCE == "merge_request_event"# Teststest:stage:testimage:node:20parallel:4script:- npm ci- npm test -- --shard=$CI_NODE_INDEX/$CI_NODE_TOTAL --coveragecoverage:'/Statements\s*:\s*(\d+\.?\d*)%/'artifacts:reports:coverage_report:coverage_format:coberturapath:coverage/cobertura-coverage.xmlrules:- if:$CI_PIPELINE_SOURCE == "merge_request_event"# Securityinclude:- template:Security/SAST.gitlab-ci.yml- template:Security/Secret-Detection.gitlab-ci.yml- template:Security/Dependency-Scanning.gitlab-ci.ymlsemgrep:stage:securityimage:semgrep/semgrepscript:- semgrep ci --config auto --config p/security-auditrules:- if:$CI_PIPELINE_SOURCE == "merge_request_event"allow_failure:false# AI Reviewai-review:stage:ai-reviewimage:python:3.11-slimbefore_script:- pip install --quiet openai requestsscript:- python scripts/ai_review.pyrules:- if:$CI_PIPELINE_SOURCE == "merge_request_event"allow_failure:true# Deploy to staging on mergedeploy-staging:stage:deployscript:- echo "Deploying to staging..."environment:name:stagingrules:- if:$CI_COMMIT_BRANCH == "main"
FAQ
Is GitLab Duo worth the cost of Ultimate?
For larger teams, yes. The security scanning alone often justifies the cost. For smaller teams, the Premium tier with third-party tools (Semgrep, CodeRabbit) provides similar capabilities at lower cost.
How do I migrate from GitHub Actions to GitLab CI?
Most concepts map directly: workflows become pipelines, jobs remain jobs, steps become script lines. The main differences are syntax and built-in features. GitLab has more native security scanning.
Can I use GitLab CI with self-hosted GitLab?
Yes, all features work on self-hosted. GitLab Duo requires connectivity to GitLab’s AI services, but can be configured with private endpoints on Ultimate.
How do I handle secrets in GitLab CI?
Use CI/CD Variables (Settings → CI/CD → Variables). Mark as “Masked” and “Protected” for sensitive values. Never hardcode secrets in gitlab-ci.yml.
Conclusion
Key Takeaways
GitLab Duo provides native AI code review on Premium/Ultimate
Custom CI pipelines work on any GitLab tier
Use GitLab’s built-in security templates for scanning
Third-party tools (CodeRabbit, Semgrep, Snyk) fill gaps
Configure CODEOWNERS for automatic reviewer assignment
Set up approval rules based on security findings
Cache dependencies and parallelize for speed
Make AI review informational, security checks blocking