GitLab CI/CD: Pipelines with Claude Code
GitLab CI/CD pipelines are YAML-driven workflows that run on every push, merge request, or schedule. Integrating Claude Code into GitLab pipelines means your code review, security checks, and auto-fixes happen automatically as part of your CI. This guide teaches how to wire Claude Code into GitLab runners, handle merge request approvals, manage artifacts, and compare GitLab's approach to GitHub Actions—both are powerful, but configuration and abstractions differ.
The key difference: GitLab pipelines are defined in .gitlab-ci.yml at the root of your repo, while GitHub uses .github/workflows/. Both support Docker runners (self-hosted or GitLab-managed), but GitLab's model is more unified—CI, CD, security, and compliance are all in one platform. If your team uses GitHub instead of GitLab, see GitHub Actions with Claude Code; to layer in time-based automation on top of pipeline triggers, see routines and scheduled automation.
GitLab Runner Setup and Configuration
A GitLab Runner is an agent that executes pipeline jobs. Set up via:
1. Register a runner:
1gitlab-runner register --url https://gitlab.com/ --registration-token YOUR_TOKEN --executor docker --docker-image ubuntu:22.042. Docker executor (recommended for Claude Code): - Runs each job in a fresh container. - Isolation: no side effects between jobs. - Caching: GitLab can cache dependencies (node_modules, pip cache).
3. Define in .gitlab-ci.yml:
1stages:2 - review3 - build4 - deploy5 6 claude-review:7 stage: review8 image: ubuntu:22.049 script:10 - apt-get update && apt-get install -y git curl11 - npm install -g claude-code12 - claude-code run "Review this MR for security issues"13 only:14 - merge_requestsGitLab-hosted runners are free for public repos; private repos get 400 CI minutes/month free. Self-hosted runners run on your infrastructure (VMs, Kubernetes, your laptop even).
Quick reference
- Runner tags: register runners with tags (e.g., 'docker', 'fast-gpu'); jobs specify required tags.
- Concurrency: configure how many jobs run simultaneously on one runner (default 1).
- Timeout: jobs have 1-hour timeout by default; override with timeout: 30m in the job.
- Docker image: specify the base image (ubuntu, alpine, node, python, etc.); Claude Code CLI must be available.
- Cache: declare artifacts to preserve across jobs (e.g., node_modules, build output).
Remember this
GitLab Runner executes pipeline jobs in Docker containers; register runners with tags; configure timeout, cache, and image per job.
Merge Request Automation and Pipelines
Merge requests (MRs) are GitLab's term for pull requests. When an MR is opened, GitLab automatically runs pipelines. Use this to invoke Claude Code:
1review-mr:2 stage: review3 script:4 - git fetch origin merge-requests/$CI_MERGE_REQUEST_IID/head:review-branch5 - git checkout review-branch6 - git diff origin/main...HEAD > /tmp/diff.txt7 - claude-code run "Review this MR diff for bugs and security issues"8 only:9 - merge_requests10 allow_failure: true # Don't block MR if review failsGitLab provides CI/CD variables like:
- $CI_MERGE_REQUEST_IID = MR number.
- $CI_MERGE_REQUEST_TITLE = MR title.
- $CI_MERGE_REQUEST_DESCRIPTION = MR description.
- $CI_COMMIT_SHA = commit hash.
Use these to provide context to Claude. After review, Claude posts findings as comments on the MR (via GitLab API) or as a note in the merge request discussion thread.
Quick reference
- Pipeline rules: use 'only' or 'rules' to specify when jobs run (on push, on MR, on schedule).
- Artifacts: save Claude's output (JSON report, markdown) as artifacts; available for download.
- Reports: GitLab supports SAST, DAST, dependency-scanning reports; parse Claude's output into these formats.
- Allow failure: set allow_failure: true so a failed review doesn't block the MR (it's optional feedback).
- Comments: use GitLab API (POST /projects/:id/merge_requests/:mr_iid/notes) to post comments on the MR.
Remember this
MR pipelines run automatically; use $CI_MERGE_REQUEST_* variables to provide MR context to Claude; post findings as MR comments via API.
Pipeline Stages and Job Orchestration
GitLab pipelines have stages. Jobs in the same stage run in parallel; subsequent stages wait for the previous stage to succeed.
Example pipeline:
1stages:2 - lint3 - test4 - review5 - build6 - deploy7 8lint:9 stage: lint10 script: npm run lint11 allow_failure: false # Blocks pipeline if lint fails12 13test:14 stage: test15 script: npm test16 allow_failure: false17 18claude-review:19 stage: review # Runs after test passes20 script:21 - npm install -g claude-code22 - claude-code run "Review code quality"23 allow_failure: true # Doesn't block deploy24 25build:26 stage: build27 script: npm run build28 29deploy:30 stage: deploy31 script: npm run deploy32 only:33 - main # Only deploy on main branchFlow: Lint → Test → Review (in parallel or after test) → Build → Deploy. If test fails, review and build are skipped.
Quick reference
- Parallel jobs: jobs in the same stage run simultaneously; depends_on can force sequential ordering.
- Manual jobs: set 'when: manual' to require a click to proceed (useful for deploy stages).
- Conditional: use 'only' (branch names, tags) or 'rules' (complex conditions) to trigger jobs selectively.
- Retry: set 'retry: 2' to auto-retry failed jobs (useful for transient failures).
- Timeout: each job has a timeout; override per-job with 'timeout: 30m'.
Remember this
Stages orchestrate job order; jobs in same stage run parallel; use allow_failure to make Claude review optional.
Artifact Handling and Reports
Artifacts are files saved from a job that can be downloaded or used by subsequent jobs.
1claude-analyze:2 stage: review3 script:4 - claude-code run "Analyze codebase" > analysis.json5 artifacts:6 paths:7 - analysis.json8 expire_in: 30 days9 reports:10 codequality: analysis.json # GitLab parses as code quality reportGitLab recognizes certain report formats: - sast (SAST findings, mapped to GitLab UI) - dast (DAST findings) - codequality (code quality issues) - dependency_scanning (dependency vulnerabilities)
If you output JSON in the codequality format, GitLab displays findings in the MR UI automatically.
Quick reference
- Artifact retention: configure how long artifacts are kept (expire_in: 30 days).
- Artifact size: artifacts larger than 100 GB may be rejected; split large outputs.
- Download: artifacts are downloadable from the GitLab UI (CI/CD > Pipelines).
- Pass to next job: use 'needs: [job-name]' to explicitly pass artifacts from one job to the next.
- Report parsing: GitLab auto-parses certain report formats; custom formats require manual upload.
Remember this
Artifacts preserve job output; use recognized report formats (codequality, sast) for automatic GitLab UI integration.
Status Checks and Approval Requirements
Make certain pipeline jobs required for merge. In GitLab project settings (Settings > Repository > Protected branches), set:
- Require Pipeline to Succeed: MR cannot be merged if any required job fails.
- Require Approval: Require specific users/teams to approve the MR.
Then in .gitlab-ci.yml, mark jobs as status checks:
1lint:2 stage: lint3 script: npm run lint4 5test:6 stage: test7 script: npm test8 9claude-security-review:10 stage: review11 script:12 - claude-code run "Check for security vulnerabilities"13 # This job must pass for MR to be mergeable14 allow_failure: false15 artifacts:16 reports:17 sast: security-report.jsonIf you set require pipeline success, the claude-security-review job must pass before merge. If Claude finds critical issues, the job fails, blocking merge until fixed.
Quick reference
- Protected branches: configure which branches require pipeline + approval (usually main).
- Approval rules: specify who can approve (e.g., 2 code owners, or any 2 team members).
- Pipeline status: GitLab shows pipeline status on the MR (green checkmark = pass, red X = fail).
- Status checks: some checks are optional (allow_failure: true), others are required.
- Re-run failed jobs: click 'Retry' in GitLab UI to re-run a failed job (e.g., if Claude times out).
Remember this
Mark critical jobs as required (allow_failure: false); configure protected branches to require pipeline success before merge.
Self-Hosted Runners and Advanced Setup
Self-hosted runners run on your infrastructure. Advantages: - No concurrency limits. - Full OS access (install custom software). - Private network access.
Disadvantages: - You maintain the runner software and OS. - Security risk if not isolated properly.
Setup on a VM or Kubernetes:
1# Download and install GitLab Runner2curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | bash3sudo apt-get install gitlab-runner4 5# Register the runner6sudo gitlab-runner register --url https://gitlab.com/ --registration-token YOUR_TOKEN --executor docker --tag-list "custom,docker" --docker-image ubuntu:22.04Then in your .gitlab-ci.yml, specify:
1claude-task:2 tags:3 - custom # Run on self-hosted runner with 'custom' tag4 script:5 - claude-code run "Task here"Best practices: - Use Docker executor for isolation. - Keep runner OS and runner software up to date. - Use separate runners for CI vs deploy (different permission levels). - Monitor runner health (CPU, memory, disk); alert if resources are low. - Rotate credentials regularly (registration tokens, API keys).
Quick reference
- Kubernetes executor: run GitLab Runner on Kubernetes clusters for dynamic scaling.
- Runner concurrency: configure how many jobs run simultaneously on a runner.
- Docker-in-Docker: if you need to build Docker images in CI, use docker-in-docker executor.
- Private runners: runners on your infrastructure can't be shared with other projects; more secure.
- Runner groups: group runners by purpose (fast, GPU, slow) and tag jobs to run on specific groups.
Remember this
Self-hosted runners: register on your VM, use Docker executor, tag jobs to route to specific runners, monitor runner health.
Real Example: Canary Deployment with Claude Review
Scenario: Deploy a new feature, but first run it on 10% of traffic for 1 hour. If no errors, roll out 100%.
Pipeline:
1stages:2 - build3 - canary-deploy4 - canary-verify5 - full-deploy6 7build:8 stage: build9 script: npm run build10 11canary-deploy:12 stage: canary-deploy13 script:14 - kubectl set image deployment/app app=myrepo/app:$CI_COMMIT_SHA --record15 - kubectl patch deployment/app -p '{"spec": {"strategy": {"canary": {"weight": 10}}}}'16 environment:17 name: production18 deployment_tier: production19 20canary-verify:21 stage: canary-verify22 script:23 - sleep 300 # Wait 5 min for canary to serve traffic24 - claude-code run "Check if canary metrics (error rate, latency) are acceptable"25 allow_failure: false # Block full deploy if canary fails26 27full-deploy:28 stage: full-deploy29 script:30 - kubectl set image deployment/app app=myrepo/app:$CI_COMMIT_SHA31 - kubectl rollout status deployment/app32 environment:33 name: production34 when: on_success # Only run if canary-verify passesClaude's role: After canary runs for 5 min, Claude checks metrics (error rate, latency, trace samples). If metrics look good, Claude gives a thumbs-up and full deploy proceeds. If metrics are bad, Claude reports the issue and blocks deploy.
Quick reference
- Canary weight: gradually increase traffic percentage (10% → 25% → 50% → 100%).
- Metrics: observe error rate, latency, CPU, memory; compare to baseline before the canary.
- Rollback: if canary metrics are bad, auto-rollback to the previous version.
- Feature flags: use feature flags to enable the new code only for canary traffic.
- Approval: even if canary metrics are good, require human approval before full deploy on critical systems.
Remember this
Canary deployment: deploy to 10% traffic, let Claude verify metrics are acceptable, then full deploy. This reduces risk of bad deployments.
GitLab CI/CD vs GitHub Actions
Both GitLab CI/CD and GitHub Actions are excellent. Key differences:
| Feature | GitLab CI/CD | GitHub Actions | |---------|------------|-----------------| | Config file | .gitlab-ci.yml | .github/workflows/.yml | | Platform | GitLab (all-in-one) | GitHub (part of GitHub ecosystem) | | Pricing | Free for public + 400 min/mo private | Free for public + 2000 min/mo private | | Concurrency | Limited by plan | Limited by plan | | Marketplace | Less extensive | Large, well-documented | | Integration | Built into GitLab issues/MRs | Separate from PR UI | | Learning curve | Slightly steeper | More intuitive for GitHub users | | Self-hosted* | Full app or runner only | Runner only |
Recommendation: - If using GitLab, use GitLab CI/CD (unified platform). - If using GitHub, use GitHub Actions (tighter integration). - If using both, set up runners on each and use platform-specific syntax.
Both can run Claude Code equally well; the choice is about ecosystem fit and team preference.
Quick reference
- Matrix builds: both support matrix (run on multiple OS/versions in parallel).
- Secret handling: both encrypt secrets; GitLab has more granular project-level controls.
- Caching: GitLab has more powerful caching (S3-backed); GitHub caching is simpler.
- Cost: GitLab has higher free tier (400 min); GitHub has 2000 min. For high volume, both require paid plans.
- Community: GitHub Actions has more public examples and integrations; GitLab is improving.
Remember this
GitLab CI/CD and GitHub Actions are similar in power; choose based on your git platform (GitLab vs GitHub) and team preference.
Key takeaway
GitLab CI/CD pipelines execute on every push and MR, making them ideal for continuous code quality checks. Wire Claude Code into pipelines for automated reviews, security checks, and canary deployments. The YAML syntax is straightforward; once you define one pipeline, copy and adapt for other repos.
Practice: Create a simple GitLab CI/CD pipeline with two stages: lint and claude-review. Lint stage runs a basic syntax check (e.g., npm run lint). Claude-review stage runs Claude Code to summarize the repo's main purpose in 2 sentences. Push to your repo; verify the pipeline runs and shows results in the GitLab UI. Expected: pipeline succeeds and shows Claude's 2-sentence summary in the job logs.
Polo Khan
Lead Author & Systems ArchitectSoftware engineer and distributed systems architect specializing in backend scalability, cloud-native infrastructure, databases, and AI engineering workflows. Author and maintainer of Core Concept Learning.
Related Articles
Explore this topic