← All playbooks
CI/CD migration

CircleCI → GitHub Actions

Move CircleCI workflows, jobs, orbs, contexts, caches, and service containers into GitHub Actions. Split one config.yml into one workflow file per workflow. Map requires to needs. Rebuild test parallelism, Docker Layer Caching, and contexts yourself.

Typical timeline12–30 business days50–110 hours active work
Statusneeds review
Source profileCircleCI configuration and Jenkins-adjacent CI model reviewed 2026-10-29
Destination profileGitHub Actions CircleCI migration guide and Actions Importer 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

GitHub Actions

What gets better
  • Automation lives beside the repository with an enormous reusable action ecosystem
  • Repository-centered workflows keep code, review, and automation close together
What gets worse
  • Large workflows can become slow, opaque, and expensive to debug
  • Advanced governance and automation can become configuration-heavy
Best of the move

GitHub Actions: Automation lives beside the repository with an enormous reusable action ecosystem. 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: Large workflows can become slow, opaque, and expensive to debug.

Jump to a section
01At a glance

Know the shape of the move.

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

This timeline assumes

  • Up to 80 repositories, 120 workflows, 40 contexts, and 20 orbs across one GitHub organization.
  • You control CircleCI org settings, project API tokens, GitHub Actions, secrets, environments, and required checks.
  • CircleCI stays connected until GitHub Actions has passed one representative release path on every critical repo.
  • A pilot covers Docker jobs, service containers, caches, matrix builds, scheduled workflows, and a deploy job.
  • 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
Workflows and job graphspartialcriticalGitHub says CircleCI can declare several workflows in one config.yml. Actions needs one workflow file per workflow. CircleCI requires becomes Actions needs.Inventory every workflow name and dependency, then create one YAML file under .github/workflows for each.
Automatic test parallelismlostcriticalGitHub states CircleCI can group tests from rules or historical timing. That behavior is not built into Actions.Split the suite with a matrix, a shard script, or a third-party action and compare wall-clock time on the same commit.
OrbsmanualcriticalOrbs are reusable YAML. Actions are JavaScript or Docker components. The importer leaves unknown orbs as manual work.List every orb and version. Replace each with a pinned action, a composite action, or inline steps.
Contexts and project environment variablesmanualcriticalGitHub's importer lists contexts and project-level environment variables as manual tasks. They do not become Actions secrets automatically.Export context names and consumers. Recreate organization, repository, and environment secrets. Rotate every value.
CircleCI convenience imagespartialhighGitHub warns those images set USER to circleci and collide with Actions container permissions. It recommends leaving the convenience images.Use GitHub-hosted runners or images that keep the default user. Drop the USER instruction from your own Dockerfiles.
Docker Layer CachinglosthighGitHub says Actions has no equivalent of CircleCI Docker Layer Caching.Cache buildx layers or registry tags yourself and measure cold versus warm image builds.
Workspaces between jobspartialhighpersist_to_workspace and attach_workspace become upload-artifact and download-artifact. Retention and size limits differ.Name every artifact, pin actions/upload-artifact and actions/download-artifact, and fail the job if a required file is missing.
Service containerspartialhighCircleCI treats the first docker image as the primary job image. Actions splits container and services and reaches the database by service hostname.Move env vars onto the job, add a health check, and wait on the service name rather than localhost.
CachespartialmediumBoth systems cache files from YAML. Key syntax changes from checksum to hashFiles. Cross-workflow automatic caches do not import.Rewrite cache keys, restore-keys, and paths. Confirm a second run on the same lockfile is a hit.
SSH rerun debugginglostmediumCircleCI can open an SSH session on a failed job. Actions does not ship that as a first-class product feature.Add tmate only on a labelled debug workflow, or reproduce the job on a self-hosted runner you control.
Build history, insights, and test timingslostmediumHistorical timings that feed CircleCI parallelism and insights stay in CircleCI.Export required reports before you cancel the plan and accept a new Actions baseline.
Scheduled workflows and approvalsmanualhighCircleCI schedules and approval jobs need Actions cron triggers, environments, and required reviewers.Recreate each schedule in on.schedule and each approval as an environment protection rule.
03Field and feature mapping

Where each thing goes.

SourceDestinationMethodNotes
CircleCI config.yml workflow.github/workflows/*.yml filetransformOne Actions file per CircleCI workflow.
requiresneedstransformKeep the same job graph and fail-fast policy.
orbaction, composite action, or inline stepsmanualUnknown orbs stay manual after the importer.
context or project env varActions secret or variablemanualRotate and scope to org, repo, or environment.
restore_cache / save_cacheactions/cachetransformRewrite keys with hashFiles.
persist_to_workspaceactions/upload-artifacttransformSet retention and required paths.
docker primary image plus secondary imagescontainer plus servicestransformUse the service hostname and a health check.
test parallelismmatrix or shard scriptmanualActions does not group tests from historical timing.
approval jobenvironment protection rulemanualRequired reviewers replace type: approval.
04Before you begin

Make the move recoverable.

Backup procedure

Create the source-of-truth backup

Keep every pipeline definition, secret consumer, orb pin, and required-check mapping before Actions becomes authoritative.

  1. Inventory repositories, workflows, jobs, orbs, contexts, env vars, schedules, approval gates, caches, and deploy targets.
  2. Export .circleci/config.yml from the production commit and record the CircleCI org and project slugs.
  3. List every context and project variable name, not the secret values, and note which jobs read them.
  4. Download recent test reports and timing data you still need for sharding.
  5. Record current required status checks on every protected branch.

Proof to capture: A dated manifest lists every repo, workflow, orb, context consumer, secret name, and required check.

Transformation · GitHub Actions Importer

Importer dry run

See what the official converter can emit before you trust a pull request.

  1. Run audit on the CircleCI organization if you have an org token.
  2. Dry-run one representative project.
  3. Treat contexts, project variables, and unknown orbs as a manual ledger.

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

Transformation · .github/workflows

Workflow file split

Match Actions' one-file-per-workflow rule.

  1. Create one YAML file for each CircleCI workflow name.
  2. Translate requires to needs.
  3. Pin every third-party action to a commit SHA.

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.

Cutover

Required checks still point at CircleCI

criticalpossible likelihood

A protected branch accepts a merge without the new Actions workflow.

Consequence
Untested code reaches the default branch.
Mitigation
Add the Actions check, watch it go green, then remove the CircleCI check.

Stop if: Any production branch can merge without the approved Actions workflow.

Pilot

Convenience images break permissions

highpossible likelihood

A Docker job fails on checkout or cache because USER is circleci.

Consequence
The suite looks red for a permissions bug, not a product bug.
Mitigation
Leave CircleCI convenience images and fix USER in your own Dockerfiles.

Stop if: A critical job only passes after chmod 777 of the workspace.

Configuration

Secrets leak across jobs

criticalpossible likelihood

A forked-pull-request workflow can read an org secret, or one job can see another context.

Consequence
Credentials leave the intended environment.
Mitigation
Scope secrets per environment and disable secret access on untrusted forks.

Stop if: Any untrusted workflow can read a production secret.

06Precise timeline

Do the work in this order.

Estimate forOne GitHub org with up to 80 repositories and mixed Docker, cache, and deploy workflows
Total elapsed12–30 business days
Active work50–110 hours
BufferAdd time for custom orbs, self-hosted runners, or a large monorepo with historical test sharding.
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 required checks3–7 days
05
Days 22–30Observe and close5–8 days
  1. Days 1–4 · inventory

    Inventory and decisions

    8–16 hours active2–4 days elapsedOwner review waiting
    • Inventory workflows, orbs, contexts, secrets, and required checks.
    • Pick the importer or a manual rewrite per repo.

    Depends on: CircleCI and GitHub admin access

    Stop / go checkpoint

    Pilot?

    Go when: Every critical workflow has an owner and a destination file plan.

    Stop when: A production deploy job has no owner.

  2. Days 3–6 · backup

    Export and pin

    6–12 hours active2–3 days elapsedToken and report export waiting
    • Archive config.yml, orb pins, and secret-name ledgers.
    • Export timing reports you still need.

    Depends on: Approved inventory

    Stop / go checkpoint

    Transform?

    Go when: The manifest matches CircleCI projects and protected branches.

    Stop when: A required check or context consumer is missing.

  3. Days 5–16 · pilot

    Translate and pilot

    20–50 hours active6–12 days elapsedFirst Actions runs waiting
    • Dry-run the importer on one repo.
    • Rewrite caches, services, and deploy jobs.
    • Compare results with CircleCI on the same SHA.

    Depends on: Verified backup

    Stop / go checkpoint

    Scale?

    Go when: Pilot jobs, secrets, and artifacts match the approved CircleCI result.

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

  4. Days 16–24 · cutover

    Switch required checks

    10–22 hours active3–7 days elapsedBranch-protection updates waiting
    • Enable Actions on remaining repos.
    • Move required checks.
    • Keep CircleCI running in parallel for one cycle.

    Depends on: Passed pilot

    Stop / go checkpoint

    Open production?

    Go when: Actions is the only required check and deploys run once.

    Stop when: CircleCI and Actions both deploy the same commit.

  5. Days 22–30 · observe

    Observe and close

    6–10 hours active5–8 days elapsedScheduled and release workflows waiting
    • Watch scheduled, fork, and release paths.
    • Revoke CircleCI tokens only after the observation window.

    Depends on: Verified cutover

    Stop / go checkpoint

    Close rollback?

    Go when: No rollback trigger fires through one release cycle.

    Stop when: A required path is missing or a secret is over-scoped.

07The point of change

Cut over with a way back.

Go live

Cutover

Make GitHub Actions the only required CI and the only deploy trigger.

Recommended window: A weekday after a green Actions run on the default branch, with release owners on call.

  1. Freeze CircleCI config edits on the default branch.
  2. Merge the approved Actions workflows on the same commit you compared.
  3. Add the Actions check to branch protection, then remove the CircleCI check.
  4. Disable CircleCI deploys and scheduled workflows.
  5. Run the production release path once and keep CircleCI recoverable.

Proof to capture: Actions owns required checks and deploys. CircleCI cannot ship production. Counts of jobs and artifacts match the pilot.

Return to safety

Rollback

Return required checks and deploys to CircleCI without a double release.

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

  1. Stop Actions deploy jobs and environment approvals.
  2. Restore the CircleCI required check on protected branches.
  3. Re-enable CircleCI scheduled and deploy workflows.
  4. Disable the Actions deploy workflow or the environment.
  5. Run one CircleCI release path and confirm it is the only writer.

Proof to capture: CircleCI is the required check again and only one deploy ran.

Rollback immediately when
  • Actions required check missing
  • Deploy ran twice
  • Secret exposure
  • Critical job red only on Actions
  • Branch protection accepts an untested merge
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-01BlockingWorkflow and job mapCompare every CircleCI workflow to an Actions file and every requires edge to needs.Every production job has one destination.Workflow map.
V-02BlockingSame-commit parityRun CircleCI and Actions on one frozen SHA for the pilot repo.Tests, artifacts, and deploy dry-runs match.Job logs and artifact hashes.
V-03BlockingContext and environment scopeInspect org, repo, and environment secrets and a fork pull request.Least privilege. No production secret on an untrusted workflow.Secret audit.
V-04BlockingImages, services, and cachesExercise Docker jobs, database services, and a warm cache run.Services become healthy and the second run is a cache hit.Service and cache logs.
V-05BlockingTest shardingTime the full suite and each shard.Approved duration without silent test drops.Timing report.
V-06BlockingRequired checksAttempt a merge with Actions failing and with CircleCI removed.Only the approved Actions check can satisfy the branch.Branch-protection screenshot.
V-07BlockingDeploy onceRun the production deploy path in a rehearsal.One deploy, one set of notifications.Deploy log.
V-08BlockingRollbackRestore the CircleCI required 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 scheduled workflow, and seven stable days.

  1. Archive CircleCI configs and the importer reports.
  2. Revoke CircleCI personal API tokens used for the importer.
  3. Remove unused CircleCI project keys and deploy users.
  4. Keep the CircleCI org until billing and audit review finish.
  5. Update runbooks with the new required-check names.
  6. Schedule the next Actions pin and secret review.
10Experiences from the field

When the plan met reality.

First-hand accounts are preferred. Vendor case studies are labeled, and every note below is an editorial paraphrase—follow the link for the full context.

First-person accountJonas Kemper · Jonas Kemper

My Journey from CircleCI to GitHub Actions: The Good, The Bad, and The Workaround2025

Jonas Kemper describes his company moving every GitHub repository from CircleCI to GitHub Actions. He missed CircleCI SSH reruns so much that he kept developing jobs on CircleCI, then copied stable YAML to Actions. He found Actions easier for conditional Slack alerts, and found the Actions UI and config validator less intuitive than CircleCI's.

What they recommend
  • Keep CircleCI available for SSH debugging until you have an Actions debug path you trust.
  • Treat a green Actions Slack alert as a bonus, not proof that debugging and config tooling match CircleCI.
Worth noticing
  • The painful gap was interactive runner debugging, not the YAML job graph.
  • A dual-running workaround can work while CircleCI credits are still allowed.
First-person accountIlya Cherepanov and Travis Turner · Evil Martians

The journey from CircleCI to GitHub Actions2022

Evil Martians walked Ruby on Rails and Node.js projects from CircleCI to GitHub Actions and compared wall-clock time. They found the YAML models close enough to move with small edits. Dropping containers in favor of hosted-runner actions cut total workflow time below their CircleCI baseline. They warn that you lose container-level repeatability when you do that.

What they recommend
  • Time the CircleCI workflow on a frozen commit before you rewrite it, then time the Actions version on the same commit.
  • Look at each container step and replace it with a pinned action only when you accept runner-image drift.
Worth noticing
  • Rails and Node jobs can move with almost no logic change if you accept GitHub's one-file-per-workflow rule.
  • Beating CircleCI duration came from leaving containers, not from a literal YAML translation.
First-person accountShioashi · ZOZO TECH BLOG

What we did when we moved Rails tests from CircleCI to GitHub Actions2024

WEAR's backend team at ZOZO moved Rails automated tests from CircleCI to GitHub Actions so they could store octocov coverage in Actions artifacts and trigger both push and pull_request events without calling CircleCI's API. They had to rebuild timing-based test splitting, failed-test reruns, and a TESTS-tab style failure list. After the move they still lacked CircleCI-style flaky-test insights and an easy pull-request coverage view.

What they recommend
  • Rebuild timing-based shards and failed-test reruns before you delete CircleCI, because Actions does not ship those.
  • If coverage diffs need both push and pull_request triggers, prefer Actions events over a CircleCI API bridge.
Worth noticing
  • Company-wide Actions adoption was a reason to move, not just a feature checklist.
  • Test insights and flaky-test detection do not arrive automatically with the YAML rewrite.
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. GitHub: migrate from CircleCIAccessed 2026-10-29
  2. GitHub: migrate from CircleCI with Actions ImporterAccessed 2026-10-29
  3. CircleCI: configuration referenceAccessed 2026-10-29