CircleCI → GitLab
Move CircleCI jobs, workflows, images, caches, contexts, and orbs into GitLab CI/CD. Translate workflows into stages and rules. Replace contexts with group variables and orbs with CI/CD components. Keep CircleCI up until GitLab is the merge gate.
Should you make this move?
Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.
CircleCI
- YAML pipelines, orbs, contexts, and SSH debugging make hosted CI approachable for growing engineering teams
- Repository-centered workflows keep code, review, and automation close together
- Usage credits, contexts, and orb-specific behavior create lock-in that does not map one-to-one onto other runners
- Advanced governance and automation can become configuration-heavy
GitLab
- A comprehensive DevSecOps platform offers deep CI/CD and self-hosting options
- Repository-centered workflows keep code, review, and automation close together
- Breadth, upgrades, and administration can be heavy for smaller teams
- Advanced governance and automation can become configuration-heavy
GitLab: A comprehensive DevSecOps platform offers deep CI/CD and self-hosting options. This removes a major source-side concern: Usage credits, contexts, and orb-specific behavior create lock-in that does not map one-to-one onto other runners.
What you lose: YAML pipelines, orbs, contexts, and SSH debugging make hosted CI approachable for growing engineering teams. What you inherit: Breadth, upgrades, and administration can be heavy for smaller teams.
Jump to a section
Know the shape of the move.
This timeline assumes
- Up to 80 projects, 120 pipelines, 40 shared variable groups, and a mix of instance and self-managed runners.
- Repositories already live on GitLab, or you are moving code hosting in a separate project. This playbook covers the pipeline cutover.
- You control CircleCI, GitLab CI/CD variables, runners, protected branches, and environments.
- A pilot covers parallel jobs, a sequential deploy, a schedule, a manual job, and a cache.
- We record evidence for every blocking verification check.
What survives the move.
“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.
| Item | Outcome | Impact | What happens | Mitigation |
|---|---|---|---|---|
| Jobs and scripts | partial | critical | GitLab maps CircleCI jobs to .gitlab-ci.yml jobs. checkout is unnecessary because GitLab fetches the repo. Script commands still need the same packages on the runner. | Port each run step, pin images, and compare the job log on the same commit. |
| Workflows versus stages | partial | critical | GitLab says CircleCI workflows become stages. Jobs in one stage run in parallel. The next stage waits. A failed job skips later stages unless you allow failure. | Draw the CircleCI requires graph, then assign stages so the same jobs stay parallel or sequential. |
| Scheduled workflows | manual | high | GitLab schedules live in the UI plus rules on $CI_PIPELINE_SOURCE == "schedule". CircleCI cron in YAML is not a drop-in import. | Recreate each cron in GitLab schedules and add the matching rules filter. |
| Manual approval jobs | manual | high | CircleCI type: approval becomes when: manual on a GitLab job, usually on a protected environment. | Recreate each approval as a manual deploy job with environment protection. |
| Branch filters | partial | high | CircleCI branches.only becomes GitLab rules on $CI_COMMIT_BRANCH or a regex. | Translate every only and ignore filter and test a matching and a non-matching branch. |
| Caches | partial | medium | GitLab cache keys and paths differ from restore_cache and save_cache. GitLab also distinguishes cache from artifacts. | Rewrite keys, keep artifacts for job output, and confirm a second pipeline is a cache hit. |
| Contexts | manual | critical | GitLab says CircleCI Contexts map to group CI/CD variables, not to a one-click import. | Create the group, copy variable names, rotate values, and mask protected variables. |
| Orbs | manual | critical | GitLab compares orbs to CI/CD components. There is no orb installer. | Replace each orb with a component, a template include, or inline script. |
| Executors and machine images | manual | critical | CircleCI machine and macos executors become runner tags. GitLab.com Windows and macOS instance runners are documented as beta. | Inventory OS, Xcode, and size needs. Attach tags and verify the job lands on the intended runner. |
| Automatic test parallelism | lost | high | CircleCI can split tests from timing data. GitLab parallel and parallel:matrix do not import that history. | Set parallel count yourself and check every shard still runs tests. |
| Build history and insights | lost | medium | CircleCI job history and insights stay in CircleCI. | Export reports you still need for audit or sharding. |
| SSH rerun debugging | lost | medium | CircleCI SSH rerun is not a GitLab default. | Use a debug job you control or reproduce on a self-managed runner. |
Where each thing goes.
| Source | Destination | Method | Notes |
|---|---|---|---|
| .circleci/config.yml | .gitlab-ci.yml | transform | Keep the file at the repo root unless you set a custom CI config path. |
| workflow plus requires | stages | transform | Same-stage jobs stay parallel. |
| docker image | image | transform | GitLab can also set a global default image. |
| branches.only / ignore | rules | transform | Test both matching and excluded branches. |
| schedule trigger | pipeline schedule plus rules | manual | Cron lives in the GitLab UI. |
| approval job | when: manual | manual | Protect the environment. |
| context | group CI/CD variable | manual | Rotate and mark protected or masked. |
| orb | CI/CD component or include | manual | No automatic orb conversion. |
| machine or macos executor | runner tag | manual | Confirm the runner exists before cutover. |
Make the move recoverable.
Create the source-of-truth backup
Preserve pipeline YAML, variable names, runner needs, and merge-gate settings.
- Inventory projects, workflows, jobs, images, contexts, orbs, schedules, and approvals.
- Export each .circleci/config.yml from the production commit.
- List context and project variable names and the jobs that read them.
- Record current required pipelines on protected branches.
- Note runner OS, size, and tag requirements.
Proof to capture: A dated manifest lists every project, stage plan, variable consumer, and merge check.
Stage graph
Keep parallel and sequential jobs honest.
- Draw every requires edge.
- Assign stages so dependents wait.
- Mark jobs that must keep running after a failure.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
Variable and runner rebuild
Replace contexts and executors without leaking secrets.
- Create group variables and rotate values.
- Attach runner tags that match each CircleCI executor.
- Mask and protect production variables.
Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.
The things most likely to hurt.
These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.
Stages reorder a deploy
A deploy job shares a stage with tests or runs before a required build.
- Consequence
- An untested artifact ships.
- Mitigation
- Keep deploy in a later stage and require the test stage.
Stop if: A deploy job can start before the approved test job finishes.
A schedule fires twice
CircleCI cron and a GitLab pipeline schedule both run.
- Consequence
- Duplicate deploys or duplicate customer messages.
- Mitigation
- Disable CircleCI scheduled workflows before you enable the GitLab schedule.
Stop if: The same cron job runs on both systems.
Group variables are wider than the old context
A fork pipeline or an unprotected branch can read a production variable.
- Consequence
- Credentials leak.
- Mitigation
- Use protected, masked, environment-scoped variables.
Stop if: An untrusted pipeline can print or use a production secret.
Do the work in this order.
- Days 1–4 · inventory
Inventory and decisions
8–14 hours active2–4 days elapsedOwner review waiting- Inventory jobs, stages, contexts, orbs, and runners.
- Decide which projects move first.
Depends on: CircleCI and GitLab admin access
Stop / go checkpointPilot?
Go when: Every critical pipeline has a stage map and an owner.
Stop when: A deploy job has no GitLab environment owner.
- Days 3–6 · backup
Export and pin
5–10 hours active2–3 days elapsedVariable review waiting- Archive config.yml and variable-name ledgers.
- Record merge checks and runner tags.
Depends on: Approved inventory
Stop / go checkpointTransform?
Go when: The manifest matches CircleCI projects.
Stop when: A context consumer is unknown.
- Days 5–16 · pilot
Translate and pilot
18–48 hours active6–12 days elapsedFirst GitLab pipelines waiting- Write .gitlab-ci.yml for one project.
- Rebuild caches, schedules, and a manual deploy.
- Compare results with CircleCI on the same SHA.
Depends on: Verified backup
Stop / go checkpointScale?
Go when: Pilot jobs, variables, and artifacts match.
Stop when: A critical job is red only on GitLab.
- Days 16–24 · cutover
Switch merge gates
10–22 hours active3–6 days elapsedProtected-branch updates waiting- Roll out remaining projects.
- Move required pipelines.
- Disable CircleCI deploys and schedules.
Depends on: Passed pilot
Stop / go checkpointOpen production?
Go when: GitLab is the only required pipeline and deploys run once.
Stop when: Both systems deploy the same commit.
- Days 22–28 · observe
Observe and close
5–11 hours active5–8 days elapsedScheduled and manual jobs waiting- Watch schedules, forks, and release jobs.
- Revoke CircleCI tokens after the window.
Depends on: Verified cutover
Stop / go checkpointClose rollback?
Go when: No trigger fires through one release cycle.
Stop when: A required path is missing.
Cut over with a way back.
Cutover
Make GitLab CI/CD the only required pipeline and the only deploy trigger.
- Freeze CircleCI config edits on the default branch.
- Merge the approved .gitlab-ci.yml on the compared commit.
- Require the GitLab pipeline on protected branches, then drop the CircleCI check.
- Disable CircleCI schedules and deploy jobs.
- Run one production deploy from GitLab and keep CircleCI recoverable.
Proof to capture: GitLab owns merge gates and deploys. CircleCI cannot ship. Job results match the pilot.
Rollback
Return merge gates and deploys to CircleCI without a double release.
- Stop GitLab deploy jobs and schedules.
- Restore the CircleCI required check.
- Re-enable CircleCI deploy and scheduled workflows.
- Disable the GitLab deploy job or environment.
- Run one CircleCI release path.
Proof to capture: CircleCI is the merge gate again and only one deploy ran.
- Required GitLab pipeline missing
- Deploy ran twice
- Secret exposure
- Critical job red only on GitLab
- Schedule fired on both systems
Prove the migration worked.
Every blocking check must pass. Capture the evidence before cleanup begins.
| Pass | ID | Check | Method | Expected result | Evidence |
|---|---|---|---|---|---|
V-01Blocking | Stage map | Compare every CircleCI requires edge to GitLab stages. | Parallel and sequential jobs match the approved graph. | Stage worksheet. | |
V-02Blocking | Same-commit parity | Run both systems on one frozen SHA. | Tests and artifacts match. | Pipeline logs. | |
V-03Blocking | Group variables | Inspect protected, masked, and environment-scoped variables plus a fork pipeline. | Untrusted pipelines cannot read production secrets. | Variable audit. | |
V-04Blocking | Images, runners, and caches | Run Linux, tagged, and cached jobs. | Jobs land on the intended runner and the second run is a cache hit. | Runner and cache logs. | |
V-05Blocking | Schedules and manual jobs | Fire a test schedule and a manual deploy job. | Each runs once, only from GitLab after cutover. | Schedule and job logs. | |
V-06Blocking | Merge gate | Attempt a merge with GitLab failing. | The protected branch stays closed. | Protected-branch screenshot. | |
V-07Blocking | Deploy once | Rehearse the production environment job. | One deploy, one set of notifications. | Environment log. | |
V-08Blocking | Rollback | Restore the CircleCI check in a dry run. | CircleCI can become authoritative again. | Rollback note. |
Remove the scaffolding safely.
Safe after: One full release cycle, one GitLab schedule, and seven stable days.
- Archive CircleCI configs and the stage worksheet.
- Revoke CircleCI tokens used for the move.
- Remove unused CircleCI deploy keys.
- Keep the CircleCI org until billing review finishes.
- Update runbooks with GitLab job and environment names.
- Schedule the next component and variable review.
Verify against the primary material.
Platform behavior changes. Check these sources and the review dates above before executing a production migration.
- GitLab: migrate from CircleCIAccessed 2026-10-29
- CircleCI: configuration referenceAccessed 2026-10-29
- GitLab: CI/CD YAML syntaxAccessed 2026-10-29