← All playbooks
CI/CD migration

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.

Typical timeline12–28 business days48–105 hours active work
Statusneeds review
Source profileCircleCI configuration reference reviewed 2026-10-29
Destination profileGitLab CircleCI migration guide reviewed 2026-10-29
Documentation date
Review window
Evidence3 sources
This route needs review.Use it as a planning baseline, then verify the dated sources and test with representative data before production.
Before you migrate

Should you make this move?

Both platforms have a case. Compare what you gain with what you give up before scheduling the cutover.

Current platform

CircleCI

Reasons to stay
  • 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
Reasons to leave
  • 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
New platform

GitLab

What gets better
  • A comprehensive DevSecOps platform offers deep CI/CD and self-hosting options
  • Repository-centered workflows keep code, review, and automation close together
What gets worse
  • Breadth, upgrades, and administration can be heavy for smaller teams
  • Advanced governance and automation can become configuration-heavy
Best of the move

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.

Worst of the move

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
01At a glance

Know the shape of the move.

Transfer outcome12 features audited
Transfer outcome distributionClean transfer: 0, Partial transfer: 4, Manual rebuild: 5, Not transferred: 3.
Clean0
Partial4
Manual5
Lost3
Mapping route9 of 9 fields have a destination path

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.
02What transfers

What survives the move.

“Partial” and “manual” are not footnotes. They are work that must be scheduled and verified.

ItemOutcomeImpactWhat happensMitigation
Jobs and scriptspartialcriticalGitLab 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 stagespartialcriticalGitLab 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 workflowsmanualhighGitLab 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 jobsmanualhighCircleCI 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 filterspartialhighCircleCI 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.
CachespartialmediumGitLab 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.
ContextsmanualcriticalGitLab 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.
OrbsmanualcriticalGitLab 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 imagesmanualcriticalCircleCI 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 parallelismlosthighCircleCI 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 insightslostmediumCircleCI job history and insights stay in CircleCI.Export reports you still need for audit or sharding.
SSH rerun debugginglostmediumCircleCI SSH rerun is not a GitLab default.Use a debug job you control or reproduce on a self-managed runner.
03Field and feature mapping

Where each thing goes.

SourceDestinationMethodNotes
.circleci/config.yml.gitlab-ci.ymltransformKeep the file at the repo root unless you set a custom CI config path.
workflow plus requiresstagestransformSame-stage jobs stay parallel.
docker imageimagetransformGitLab can also set a global default image.
branches.only / ignorerulestransformTest both matching and excluded branches.
schedule triggerpipeline schedule plus rulesmanualCron lives in the GitLab UI.
approval jobwhen: manualmanualProtect the environment.
contextgroup CI/CD variablemanualRotate and mark protected or masked.
orbCI/CD component or includemanualNo automatic orb conversion.
machine or macos executorrunner tagmanualConfirm the runner exists before cutover.
04Before you begin

Make the move recoverable.

Backup procedure

Create the source-of-truth backup

Preserve pipeline YAML, variable names, runner needs, and merge-gate settings.

  1. Inventory projects, workflows, jobs, images, contexts, orbs, schedules, and approvals.
  2. Export each .circleci/config.yml from the production commit.
  3. List context and project variable names and the jobs that read them.
  4. Record current required pipelines on protected branches.
  5. Note runner OS, size, and tag requirements.

Proof to capture: A dated manifest lists every project, stage plan, variable consumer, and merge check.

Transformation · A workflow-to-stage worksheet

Stage graph

Keep parallel and sequential jobs honest.

  1. Draw every requires edge.
  2. Assign stages so dependents wait.
  3. 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.

Transformation · GitLab group variables and runner tags

Variable and runner rebuild

Replace contexts and executors without leaking secrets.

  1. Create group variables and rotate values.
  2. Attach runner tags that match each CircleCI executor.
  3. Mask and protect production variables.

Proof to capture: Save the input, output, command or tool settings, warnings, and final item counts.

05Handle with care

The things most likely to hurt.

These are operating limits. Treat every “Stop if” condition as a blocked migration, not a suggestion.

Pilot

Stages reorder a deploy

criticalpossible likelihood

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.

Cutover

A schedule fires twice

highpossible likelihood

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.

Configuration

Group variables are wider than the old context

criticalpossible likelihood

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.

06Precise timeline

Do the work in this order.

Estimate forOne GitLab group with up to 80 projects that already have CircleCI pipelines
Total elapsed12–28 business days
Active work48–105 hours
BufferAdd time for macOS runners, custom orbs, or a monorepo with many path filters.
01
Days 1–4Inventory and decisions2–4 days
02
Days 3–6Export and pin2–3 days
03
Days 5–16Translate and pilot6–12 days
04
Days 16–24Switch merge gates3–6 days
05
Days 22–28Observe and close5–8 days
  1. 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 checkpoint

    Pilot?

    Go when: Every critical pipeline has a stage map and an owner.

    Stop when: A deploy job has no GitLab environment owner.

  2. 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 checkpoint

    Transform?

    Go when: The manifest matches CircleCI projects.

    Stop when: A context consumer is unknown.

  3. 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 checkpoint

    Scale?

    Go when: Pilot jobs, variables, and artifacts match.

    Stop when: A critical job is red only on GitLab.

  4. 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 checkpoint

    Open production?

    Go when: GitLab is the only required pipeline and deploys run once.

    Stop when: Both systems deploy the same commit.

  5. 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 checkpoint

    Close rollback?

    Go when: No trigger fires through one release cycle.

    Stop when: A required path is missing.

07The point of change

Cut over with a way back.

Go live

Cutover

Make GitLab CI/CD the only required pipeline and the only deploy trigger.

Recommended window: A weekday after a green GitLab pipeline on the default branch.

  1. Freeze CircleCI config edits on the default branch.
  2. Merge the approved .gitlab-ci.yml on the compared commit.
  3. Require the GitLab pipeline on protected branches, then drop the CircleCI check.
  4. Disable CircleCI schedules and deploy jobs.
  5. 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.

Return to safety

Rollback

Return merge gates and deploys to CircleCI without a double release.

Deadline: Before the next production release and before CircleCI tokens are revoked.

  1. Stop GitLab deploy jobs and schedules.
  2. Restore the CircleCI required check.
  3. Re-enable CircleCI deploy and scheduled workflows.
  4. Disable the GitLab deploy job or environment.
  5. Run one CircleCI release path.

Proof to capture: CircleCI is the merge gate again and only one deploy ran.

Rollback immediately when
  • Required GitLab pipeline missing
  • Deploy ran twice
  • Secret exposure
  • Critical job red only on GitLab
  • Schedule fired on both systems
08Verification report

Prove the migration worked.

Every blocking check must pass. Capture the evidence before cleanup begins.

0%
Interactive report preview0 / 8 checks passed
PassIDCheckMethodExpected resultEvidence
V-01BlockingStage mapCompare every CircleCI requires edge to GitLab stages.Parallel and sequential jobs match the approved graph.Stage worksheet.
V-02BlockingSame-commit parityRun both systems on one frozen SHA.Tests and artifacts match.Pipeline logs.
V-03BlockingGroup variablesInspect protected, masked, and environment-scoped variables plus a fork pipeline.Untrusted pipelines cannot read production secrets.Variable audit.
V-04BlockingImages, runners, and cachesRun Linux, tagged, and cached jobs.Jobs land on the intended runner and the second run is a cache hit.Runner and cache logs.
V-05BlockingSchedules and manual jobsFire a test schedule and a manual deploy job.Each runs once, only from GitLab after cutover.Schedule and job logs.
V-06BlockingMerge gateAttempt a merge with GitLab failing.The protected branch stays closed.Protected-branch screenshot.
V-07BlockingDeploy onceRehearse the production environment job.One deploy, one set of notifications.Environment log.
V-08BlockingRollbackRestore the CircleCI check in a dry run.CircleCI can become authoritative again.Rollback note.
09Post-migration cleanup

Remove the scaffolding safely.

Safe after: One full release cycle, one GitLab schedule, and seven stable days.

  1. Archive CircleCI configs and the stage worksheet.
  2. Revoke CircleCI tokens used for the move.
  3. Remove unused CircleCI deploy keys.
  4. Keep the CircleCI org until billing review finishes.
  5. Update runbooks with GitLab job and environment names.
  6. Schedule the next component and variable review.
Sources and evidence

Verify against the primary material.

Platform behavior changes. Check these sources and the review dates above before executing a production migration.

  1. GitLab: migrate from CircleCIAccessed 2026-10-29
  2. CircleCI: configuration referenceAccessed 2026-10-29
  3. GitLab: CI/CD YAML syntaxAccessed 2026-10-29