Migrate from CircleCI to GitLab CI/CD

Moving CircleCI pipelines to self-managed GitLab CI/CD is a rewrite of configuration, runners and secrets, not an import. This page sets out what maps, what needs redesign, and how to sequence the work.

On this page

Migrate from CircleCI to GitLab CI/CD: what the move involves

Your repositories can move to self-managed GitLab with its documented importers, but your CircleCI pipelines do not carry over as configuration. Each one is rebuilt as GitLab CI/CD, with jobs and stages defined in .gitlab-ci.yml, runners that execute them and CI/CD variables that take the place of values held in CircleCI contexts. Most of the effort sits in that rebuild. How much work it is depends on the number of pipelines, the orbs they depend on, the number of contexts and whether you run custom executors. This section gives no duration or price, because an inventory of those four items is what sets them. The GitLab import documentation covers the repository side of the move.

Most CircleCI concepts have a GitLab counterpart, but the swap is rarely one to one. Orbs are reusable packages of jobs and commands, so the nearest GitLab equivalent is a set of includes, project or group templates, or components, depending on what your team wants to version and share. Executors describe the environment a job runs in. In GitLab that environment is set by the runner and the job image, so custom executors need a runner plan before any pipeline is rewritten. Caching and workspace passing also behave differently, so cache keys and artifacts need deliberate design. Ask your team to separate third-party orbs from internal ones, since that split largely determines how much you will build yourself.

Follow the GitLab migration guide for CI/CD as your sequence, and confirm its current steps with GitLab before you start, because the guidance changes and this section does not reproduce it. Begin with an inventory of every pipeline, including its orbs, contexts, executors, scheduled triggers and secrets. Decide which runner fleet will execute the jobs, and name the people who own the runners and the variables that hold credentials. Run old and new pipelines side by side on non-deploying branches, and move production deploys only after the new pipeline has passed on the same commits. Your platform team will want that plan written down before the rewrite starts.

Which CircleCI concepts map to GitLab CI/CD and which need redesign

This table pairs each CircleCI concept with its closest GitLab CI/CD equivalent and notes whether the move is a direct translation or a design decision. Read the rows marked as redesign first, because those are where pipeline structure, secrets handling and runner capacity need planning before any YAML is rewritten.

CircleCI conceptGitLab CI/CD equivalentMigration notes
config.yml jobs and workflowsStages and jobs in .gitlab-ci.ymlDirect translation for most jobs. Workflow ordering becomes stages plus needs, so map fan-out and approval gates explicitly rather than copying the sequence.
OrbsIncludes, CI/CD templates and componentsRedesign. Orbs bundle commands, jobs and executors, so choose which published components or internal templates replace each orb and confirm they are available in your GitLab version.
Custom or private orbsInternal CI/CD components or project templatesRedesign. Move shared logic into a versioned component project and pin versions, since there is no one-to-one orb registry.
Executors (docker, machine, macos)Runners with executors such as Docker or autoscaling, plus job imageDesign decision. Image choice carries over, but the machine and macOS executors need runners on hosts you operate, so size and isolate the fleet first.
ContextsGroup or project CI/CD variables with protected and masked settingsRedesign. Decide which contexts map to group scope and which to project scope, mark production values protected, and mask secrets before rotating them.
Restricted contexts and approval jobsProtected environments with deployment approvals, plus protected branches and tagsRedesign. Access rules move to environment and branch protection, so document who approved each context before cutover.
Caching (save_cache, restore_cache)cache keywordDirect translation for dependency caches. Cache keys and paths must be rewritten, and cache behaviour depends on runner storage, so test hit rates on your runners.
Workspaces (persist_to_workspace)artifacts keyword with needs or dependenciesDirect translation with rewrite. Artifacts expire and are passed by job dependency, so set expire_in deliberately.
Scheduled pipelinesPipeline schedulesDirect translation. Recreate each schedule with its branch and variables, and confirm the timezone and owner.
API-triggered pipelinesPipeline triggers and the pipeline APIDesign decision. Trigger tokens and API calls change, so update every caller and rotate credentials rather than copying them.
Dynamic configuration (setup workflows)Parent-child pipelines or dynamic child pipelinesRedesign. Setup workflows need a pipeline structure that generates child pipelines, so review generation logic with the team that owns it.

Which GitLab import paths apply to a CircleCI move

CircleCI work splits into two streams: source and history that GitLab can import, and pipeline configuration that you rebuild by hand. The cards below cover the documented GitLab paths for each stream, plus the runner and validation tools you will need before the first pipeline runs.

Repository import sources

GitLab's import documentation covers GitHub, Bitbucket, Gitea, other GitLab instances, Git repositories by URL or manifest, and Jira or FogBugz issues. CircleCI is not a source, so repositories must be imported from the Git host where they actually live, not from CircleCI. Confirm which upstream host holds each project before you pick an importer.

Merge request and issue history

Importers from supported Git hosts can bring over merge requests and issues, but the fields that survive vary by source. Check how comments, reviewers, labels and attachments map before promising history to auditors. Placeholder users will hold contributions until someone claims them.

Direct transfer between GitLab instances

When CircleCI projects already sit in another self-managed GitLab, direct transfer moves groups and projects with their issues and merge requests. It needs an administrator to enable the setting first. Confirm what is excluded, especially CI/CD variables and runner registrations, before scheduling the cutover.

File export and manifest import

File export lets you move a project's data as an archive between GitLab instances, and manifest import handles bulk Git repository lists. Both are useful when the source host is not supported by a direct importer. Test a single project end to end before running the full list.

Runner install and registration

CircleCI executors have no direct GitLab equivalent, so you will register a GitLab Runner with an executor that matches your build needs, such as shell, Docker or autoscaling. Keep the Runner major and minor versions aligned with GitLab. Confirm the registration steps and supported executors for your version in the Runner documentation.

Linting, includes and API scripting

GitLab CI/CD offers a pipeline linter and the include keyword for shared job definitions, which replace CircleCI orbs in most teams' designs. Variables and schedules can be created through the API, which suits bulk setup of many projects. Confirm which include forms and API endpoints your version supports before you script anything.

Why orbs, contexts and caching need design work, not a copy

A line-by-line translation of a CircleCI config produces a pipeline that runs but breaks under change, because CircleCI's reuse model and GitLab's are built on different assumptions. In CircleCI, an orb packages jobs, commands and executors into a versioned unit that a config pulls in by name and version. GitLab has no direct equivalent. Shared logic is expressed through include for files, project templates, and CI/CD components, each with its own versioning and ownership. Before rewriting anything, the team should inventory which orbs it actually uses, then decide which shared logic becomes a versioned component owned by a platform group, which stays as a plain include inside one project, and which is simply inlined. A component published by a platform group means its consumers pin a version and upgrade deliberately, so the platform group must own the release process, changelog and deprecation policy from the start. Confirm the component catalog and version pinning behavior against the GitLab CI/CD documentation for the version you will run.

Contexts are the part of a CircleCI migration most likely to leak secrets or fail silently. A CircleCI context is a named set of environment variables that a project opts into, and it is often shared across many repositories. GitLab has no single equivalent object. The closest mapping is CI/CD variables defined at instance, group or project level, combined with protected and masked settings and environment scopes. Each context should be split into explicit rules: which group or project may read it, which environments (such as staging or production) may use it, and whether it is protected so it only reaches protected branches or tags. Review this mapping with the security team before the first production pipeline runs, since broad group-level variables are an easy way to expose production credentials to every project beneath them.

Caching also needs rebuilding rather than copying. CircleCI cache keys, restore and save steps are written against its own cache store, and the same key strings do not behave the same way in GitLab. In GitLab, the cache keyword stores data in object storage or the runner's local cache, and cache hits depend on the key, the runner that executes the job and whether jobs share a runner. Self-managed runners with autoscaling executors may start with an empty local cache on each new machine, so a cache that looked fast in CircleCI can disappear. The team should decide which artifacts are worth caching, which should be rebuilt, and where cache data will live, then measure hit rates on the runner fleet they plan to operate. Confirm the cache storage settings for your runner version and object storage before setting cache keys for production.

Choosing runners for CircleCI executor types

Most CircleCI jobs that use the docker executor or a container image map to GitLab Runner's Docker executor, which starts each job in a fresh container from the image named in the job. The Docker autoscaling executor extends this model by creating and removing machines on demand, which suits teams with bursty pipeline load. Keep the Runner version aligned with your GitLab instance, since the Runner documentation advises matching major and minor versions.

  • Image mapping: Translate each CircleCI image or docker block into the job image and services keys, and confirm which images your CircleCI jobs pull from private registries.
  • Privileged mode: Builds that run Docker-in-Docker need privileged containers, which weakens isolation. Confirm whether you need that or can use a rootless builder.
  • Cache location: CircleCI's cache does not carry over automatically. Decide whether runner-local cache volumes or object storage will hold dependency caches.
  • Autoscaling capacity: Confirm the cloud or hypervisor account limits and the maximum concurrent jobs your pipelines will generate.

Confirm the host image, registry access and whether any job depends on a container running as root.

How to sequence the migration with a parallel run and cutover

This sequence moves CircleCI work into self-managed GitLab in controlled stages, so each pipeline is proven against real output before any production branch depends on it. Each stage ends with a sign-off that your own engineering, security and change owners give before the next one starts.

  1. Inventory pipelines, orbs, contexts and executors

    Your platform or DevOps team lists every CircleCI project, its config file, the orbs it calls, the contexts and environment variables it reads, the executors and images it uses, and the triggers that start it, including scheduled and API-driven runs. Security should review the contexts list, since it shows which secrets the old system holds. The step is done when the list is reconciled against the CircleCI project list and each item has an owner and a planned GitLab equivalent, such as a template, a component or a custom job.

  2. Stand up a pilot instance and runners

    Your infrastructure team installs a self-managed GitLab instance and at least one GitLab Runner in a pilot environment that is isolated from production. Choose the install method and runner executor with the team that will operate them, and confirm the hosting, network and identity decisions with your security lead. The step closes when a test pipeline runs end to end on your own runner, and the instance is recorded in your change system as a non-production system.

  3. Import repositories and convert one representative pipeline

    Import a small set of repositories into the pilot instance, choosing one that uses orbs, contexts and a realistic build and deploy path. Rewrite its CircleCI config as a GitLab CI/CD pipeline, mapping executors to runner images or tags and replacing orb calls with templates, components or explicit scripts. Engineering leads review the converted file with the pipeline owners. The step is complete when the pipeline runs on the pilot runner and its outputs match what CircleCI produces.

  4. Run both systems in parallel on non-production branches

    Keep CircleCI as the system of record for production while the GitLab pipeline runs on non-production branches of the same code. Compare build logs, test results, artifacts, image digests and cache behavior for each run, and record every difference with its cause. Your release and QA owners decide which differences are acceptable and which block cutover. The step closes when the agreed comparison checklist passes for the representative pipelines over the period your change board approves.

  5. Cut over by repository group with protections and variables

    Move repositories in groups that share owners and deploy targets, not one at a time across the estate. For each group, recreate the protected branch and tag rules, approval settings and CI/CD variables in GitLab, with protected and masked flags where the secret warrants it, and confirm the deploy environments accept the new runners. Security and the group's owners sign the cutover record before CircleCI triggers for those repositories are disabled. The step is done when a production-path pipeline has run successfully under GitLab for each group.

  6. Decommission CircleCI projects and rotate exposed secrets

    Once a group has run cleanly on GitLab, disable and then remove its CircleCI projects, webhooks and deploy keys, keeping a read-only export of configs and logs for the retention period your records policy requires. Rotate every secret that was stored in CircleCI contexts or project variables, including deploy keys, cloud credentials and registry tokens, because the old system held copies of them. Your security team verifies rotation against an inventory and confirms that the old values no longer authenticate. The step closes when the rotation record and decommission record are filed.

What drives the cost and duration of a CircleCI to GitLab move

This table lists the factors that move the effort of a CircleCI to GitLab CI/CD migration, how each one changes the work, and what to ask for in a written quote. Read it to decide where your scope will be large or small before you request a fixed-scope proposal. One-time rewrite, pilot and cutover work is separated from recurring runner, upgrade and licensing costs.

DriverEffect on effortWhat to ask for in a quote
Number and complexity of pipelinesEach config.yml workflow with branching, dynamic config or matrix builds is rewritten by hand, so effort grows with pipeline count and logic.A pipeline inventory with a per-pipeline complexity rating and the count of workflows included in scope.
Count of orbs and custom orbsOrbs have no direct equivalent in GitLab CI/CD. Each orb is replaced by a template, component or inline script, and custom orbs need their own rebuild.A list of every orb in use, marked as official, certified or custom, with the replacement approach for each.
Number of contexts and secretsContexts map to group or project CI/CD variables and environment scopes. Protected and masked settings must be re-created and value handoff needs controlled access.The count of contexts, variables and their scopes, plus who will supply secret values and how they will be transferred.
Executor variety and custom imagesDocker, machine and macOS executors map to different runner types. Each custom image must be rebuilt, tested and registered with the runner fleet.The executor types in use, the number of custom images, and whether runner images will be built and maintained in your registry.
Caching and artifact volumeCache keys, restore behavior and artifact retention need to be redesigned. Large artifacts and caches affect storage sizing and job duration.Typical cache and artifact sizes, retention needs and the object storage target for caches and artifacts.
Required runner infrastructureSelf-managed runners must be installed, registered, scaled and patched. Autoscaling design and network access to internal systems add design work.The runner architecture (Docker Autoscaler, Kubernetes or other), the target cloud or data center, and who operates runners after handover.
Approval and compliance evidenceRequired approvals, protected environments and audit trails must be re-modeled. Evidence for assessors is an extra deliverable with its own review cycle.The approval rules to reproduce, the evidence records expected by your assessor, and whether evidence collection is in scope.
Parallel run lengthRunning CircleCI and GitLab side by side doubles pipeline maintenance and comparison work for the length of the overlap.The planned overlap period, the pipelines that run in both systems, and the criteria for retiring CircleCI jobs.
Team experience with GitLabTeams new to GitLab CI/CD need training and more review of their rewritten pipelines, which lengthens the pilot and handover.Whether training and pairing sessions are included, and the number of your engineers who will own the pipelines afterward.
Recurring costs outside the migrationRunner compute, GitLab upgrades through required stops, and the GitLab license tier and support plan continue after cutover. The tier is set by the features you need.Separate line items for one-time migration work and recurring runner, upgrade and licensing costs, each priced from the written scope.

What usually goes wrong in CI/CD migrations and how to prevent it

Most CircleCI to GitLab CI/CD problems come from assumptions carried over unchanged: where secrets live, how runners reach the network, and what an orb quietly did. Each card names one failure pattern and a check your team can run before cutover.

Secrets copied into the wrong scope

CircleCI contexts and project environment variables often get copied into GitLab at the instance, group or project level without review. Values that were shared across many repositories can end up visible to more people than before. Before cutover, list every context and variable, assign each one to the narrowest GitLab group or project scope, and mark sensitive values as masked and protected. Then confirm that the old CircleCI values are revoked or rotated so that nothing stays active in both systems.

Runners built without network review

CircleCI's hosted executors gave jobs internet access by default, while a self-managed runner sits inside your network with its own routes, DNS and credentials. Teams often stand up runners without checking which registries, artifact stores and deployment targets a job must reach, or whether jobs should be isolated from one another. Document the outbound destinations for each pipeline, place runners in segments that match their trust level, and test a sample job from each runner network before moving production pipelines.

Pipelines that pass but deploy differently

A pipeline can go green in GitLab while deploying something other than what the CircleCI version deployed. Differences often come from default branch rules, rewritten rules: or only: conditions, changed variable precedence, or a deploy job that now runs on a merge request. Run both systems in parallel against the same commit for a defined set of branches, compare artifacts and deployment targets, and review every job that runs on protected branches or tags.

Caches that silently stop working

CircleCI cache keys, restore paths and save steps do not map one to one onto GitLab's cache: keys, paths and policies. A cache key that changes on every run, or a job on a runner without the expected cache storage, can make builds slower without any error. Check cache hit rates in the first runs after cutover, confirm which runners share a cache backend, and set keys from lockfiles so they change only when dependencies change.

Undocumented orb behavior

CircleCI orbs often bundle steps that install tools, set environment variables, cache dependencies or post results, and those effects are rarely written down in the pipeline file. When an orb is replaced with a GitLab template or component, those side effects can disappear. Before rewriting, expand each orb with its CircleCI config so you can see every command it runs, list the behavior it adds, and assign each item a visible replacement in the .gitlab-ci.yml file or an included component.

Version drift between GitLab and runners

GitLab Runner should match the GitLab instance on major and minor versions, and that alignment has to be maintained across upgrades. Teams that install runners once and forget them can end up with jobs failing after a GitLab upgrade, or with runner features the server does not expect. Record the GitLab and Runner versions in your runbook, align them when you plan each upgrade stop, and check the runner version as part of every upgrade rehearsal.

Questions teams ask before moving CircleCI pipelines to GitLab

How much does a CircleCI to GitLab CI/CD migration cost?

The cost depends on the size and complexity of your pipelines, not on a list price for the migration itself. Most of the spend is labor: someone must inventory pipelines, rewrite configuration, rebuild orbs as includes or components, recreate contexts as CI/CD variables, and validate outputs. The GitLab licence is a separate, recurring decision. GitLab Free costs 0 US dollars, Premium costs 29 US dollars per user per month billed annually according to the GitLab pricing page, and Ultimate is custom priced. Premium adds advanced CI/CD and priority support, and Ultimate adds application security testing and compliance features. Runner infrastructure is another recurring cost. Ask any provider for a quote built from a written scope that lists pipelines, orbs, executors and environments in scope.

How long does it take to move CircleCI pipelines to GitLab?

Duration is driven by the number of pipelines, how many orbs and custom executors they use, how many deployment targets depend on contexts, and how much test and approval evidence you must keep. A repository with a simple build and test job moves far faster than a monorepo with dozens of deployment stages. Plan separate time for building runners, because executors must be re-established on a runner fleet you operate. Parallel running, where CircleCI and GitLab both build the same commits, adds time but reduces cutover risk. We do not publish a fixed duration. Ask for a timeline tied to a pipeline inventory and a list of unknowns, such as custom images or private orb sources.

Can our own team migrate CircleCI pipelines without a partner?

Yes, many teams do this internally, especially when pipelines are small and the engineers know both systems. The work goes well when the team starts with an inventory of every config file, orb, context, environment variable and scheduled trigger, and when it has a Runner fleet ready before the first job moves. Your team must provide repository access, a test environment that can run real builds, owners who can approve deployment changes, and a rollback plan. Consider a partner when many teams share pipelines, when regulated deployment evidence must be retained, or when the internal team cannot spare engineers for parallel running.

Can CircleCI orbs be converted to GitLab automatically?

We do not assume a supported automatic conversion. Orbs bundle commands, executors and jobs that GitLab does not package in the same way, so each orb usually needs to be understood and then replaced with a GitLab CI/CD template, include, or component, or with plain script blocks. Confirm this against the orb list in your own repositories and against the current GitLab migration guidance before you rely on any tool. Expect manual review for orbs that set environment, caching or deployment behavior, and treat each replacement as a change that needs its own test.

What should we check in CircleCI executors and contexts before moving?

Start by listing every executor, including Docker images, machine executors and macOS or Windows jobs, and mapping each one to a GitLab Runner executor you can operate. Shell, Docker and autoscaling executors are the main options in the GitLab Runner documentation. For contexts, record which secrets and variables each one provides, which projects can use it, and whether protected branches gate access. Recreate those values as GitLab CI/CD variables with protection and masking set deliberately. Do not copy secret values into repositories. Confirm that each Runner has the same major and minor version as your GitLab instance.

Should a partner run the parallel period after the cutover?

A partner can run the parallel period, but the decision depends on what must be proven and who will own the pipelines afterward. During parallel running, both systems build the same commits, outputs are compared, and failures are investigated before CircleCI is switched off. DeployOpen implements, hardens, supports and documents self-hosted platforms inside your infrastructure, and most engagements are fixed-scope with deliverables agreed in writing before work starts. Ask any partner to define the exit criteria for parallel running, who signs them off, and how long CircleCI access stays available for audit.

How DeployOpen scopes and delivers a CircleCI to GitLab migration

DeployOpen plans and delivers CircleCI to GitLab CI/CD migrations inside infrastructure you control, following the GitLab migration guide as the baseline. We start by inventorying your pipelines, orbs, contexts and runners, then build, test and document the GitLab equivalents in a fixed-scope engagement agreed in writing before work starts.

How we scope

  • We inventory every CircleCI config, orb, context and executor that the migration must replace.
  • The written scope lists which pipelines move, which are retired and which runners will execute them.
  • We agree in writing how cache keys, secrets and environment variables map into GitLab before any rewrite begins.
  • Engagements are fixed-scope, and ongoing support after handover is available as a retainer.

How we build

  • We rewrite pipelines as GitLab CI/CD configuration, using includes or components where shared logic exists.
  • We design runner placement and executor type for each workload in your own cloud accounts or data centers.
  • We test migrated pipelines against the same commits and artifacts used in CircleCI, comparing results job by job.
  • We rebuild caching and secrets handling so that credentials stay scoped to the jobs and environments that need them.

How we hand over

  • You receive a mapping document showing each CircleCI construct and its GitLab counterpart, with the reasoning for each choice.
  • Runbooks cover runner registration, version alignment with GitLab, and how to add a new pipeline.
  • We walk your platform and development teams through the pipelines, runners and variables before cutover.
  • Cutover steps, rollback criteria and the decommissioning order for CircleCI projects are written down and agreed.

How we support

  • Post-cutover support covers failing jobs, runner capacity questions and pipeline changes raised by your teams.
  • Upgrades to GitLab follow its required upgrade stops, and we plan runner upgrades to stay aligned with GitLab versions.
  • Ongoing support, upgrades and continuous testing are available as retainers agreed separately from the migration scope.
  • Ask your quote to name which items are one-time work and which recur under a retainer.

Talk to our team.

Tell us what you're working on, whether it's a deployment, an audit, a security test or a cyber range. You'll speak with an engineer who can help you scope it.

  • 30-minute call: free, with no obligation.
  • NDA on request: we can sign before you share details.
  • Clear next steps: a scope and plan after the call.