Checklist

How to migrate CI without breaking your verdict

Moving CI should change how long you wait, never whether a change passes. This checklist moves pipelines one at a time, proves the new CI gives the same pass/fail verdicts on the same commits, and keeps a way back until you no longer need it.

Last reviewed 9 November 2026.

  1. Inventory what you have

    You cannot prove nothing changed if you never wrote down what there was.

    • List every workflow or pipeline, what triggers it (push, pull request, schedule, manual, tags) and which branches.
    • Write down the exact names of required checks in branch protection or rulesets. A renamed job silently stops blocking merges, or blocks every merge forever.
    • List secrets, environment variables, environments with approvals, and any cloud roles that trust your CI’s OIDC tokens.
    • Note self-hosted runners, service containers, artifacts passed between jobs, caches, and anything that deploys.
    • Record your baseline: p50 and p90 push-to-verdict, failure rate, flaky tests you already know about, and minutes billed, over a fixed window. How to measure it.
  2. Decide how much has to move

    The safest migration is the smallest one that solves your problem.

    • If the problem is waiting time and you are on GitHub Actions, you may not need a platform move at all: a runner layer such as Graphide CI, Blacksmith or Depot changes only runs-on.
    • If the problem is where builds may run (your own machines, your own cloud, a single-tenant platform), you are moving platforms: see the picks for self-hosted needs.
    • Move one repository first, ideally one with a good test suite and a team willing to report problems.
  3. Translate pipelines one at a time

    Keep the shape of the old pipeline so results can be compared job by job.

    • Use an importer where one exists: GitHub Actions Importer (gh actions-importer) audits and converts pipelines from Jenkins, CircleCI, GitLab and others into workflows. Treat its output as a draft and review every step.
    • Keep job and check names identical to the old ones wherever the new tool allows it.
    • Pin tool and runtime versions (Node, Python, Go, JDK, container images) to what the old CI used, so the only change is the CI.
    • Recreate secrets by hand in the new tool; never print them to logs to check them. Update OIDC trust policies for the new issuer.
    • Leave deploy jobs on the old CI until the test pipelines have been cut over and stable.
  4. Shadow-run on the same commits

    Run old and new side by side, with the old one still in charge.

    • Trigger the new pipeline on the same pushes and pull requests as the old one. The old one stays the required check.
    • Make the new one non-blocking, and keep it from deploying or publishing anything.
    • Run for a fixed window: long enough to cover your normal mix of changes, including dependency bumps and config changes.
  5. Compare verdicts before cutover

    Speed is the reason to move; the verdict is the reason not to.

    • For every commit in the window, record the old verdict and the new verdict, per required check. Count agreements and disagreements.
    • Sort every disagreement into one of three causes: a flaky test (it disagrees with itself on a re-run), an environment difference (versions, time zones, network, file system), or a real miss (the new CI passed something the old one failed).
    • Fix environment differences and re-run. Any real miss stops the migration until it is understood and fixed.
    • Compare p50 and p90 push-to-verdict and minutes billed against your baseline, on the same commits.
    • Agree the bar before you look: for example, “no unexplained disagreements and p90 no worse than today”. Decide in advance, not after seeing the numbers.
  6. Cut over

    Change what blocks merges in one deliberate step.

    • Announce a time. Freeze changes to CI config for the cutover window.
    • Make the new checks required in branch protection or rulesets, then make the old ones optional (not deleted).
    • Move deploy jobs last, with a manual approval on the first few deploys from the new CI.
    • Watch queue time, failure rate and re-run rate daily for the first two weeks.
  7. Keep a rollback ready

    A migration you cannot undo in minutes is a bet, not a migration.

    • Keep the old configuration in the repository and runnable until the decommission date.
    • Make rollback one action: reverting a pull request, or switching required checks back.
    • Write down what triggers it: a real miss, an outage of the new CI, or queue times above an agreed limit. Whoever is on call can pull it without a meeting.
    • Practise it once during the shadow period, so you know it works and how long it takes.
  8. Decommission the old CI

    Only after a full period with no rollback.

    • Remove old pipeline files, runners, webhooks and integrations; revoke the old CI’s tokens and cloud trust.
    • Export any build history or audit logs you are required to keep before cancelling.
    • Write down the before-and-after numbers with their window and scope, so the next person can check them.

Moving GitHub Actions jobs to Graphide CI

Graphide CI is the smallest move on this site: it is a runner layer for your existing GitHub Actions jobs, so steps 3 and most of 1 shrink to almost nothing. What it involves, from Graphide’s docs: