Search for "migrate Jenkins to GitHub Actions" and you get GitHub's documentation and a dozen engineer-written tutorials. All useful, all answering the same question: how do I convert this pipeline?
None of them answer the question a CTO actually has: how big is this, what will it cost, and what breaks while we do it?
This is the buyer's version. If you are approving the budget rather than writing the YAML, start here.
TL;DR
- Scope is driven by pipeline count and plugin depth, not by lines of Groovy. Twenty simple pipelines are easier than three that orchestrate deployments.
- GitHub's Actions Importer automates the first pass and leaves a meaningful remainder. Treat its output as a draft, not a migration.
- The long pole is almost always secrets, credentials and deployment targets, not build steps.
- Run both systems in parallel for a period. A big-bang cutover on CI is how teams lose a release week.
- Self-hosted runners are still free. GitHub postponed the per-minute charge announced for March 2026, and hosted-runner prices fell up to 39% in January.
Why teams move
Four reasons come up repeatedly, in roughly this order:
- Maintenance burden. Jenkins is infrastructure you own — servers, plugin updates, security patching, and usually one person who understands it.
- Plugin fragility. The plugin ecosystem is Jenkins's strength and its liability. Version conflicts after an upgrade are a familiar outage.
- Proximity to code. Workflows living in
.github/workflows/alongside the repo get reviewed like code, which Jenkins configuration usually is not. - Hiring. The pool of engineers who want to maintain Jenkins is shrinking. That is a real staffing cost, and it compounds.
Reasons that do not justify a migration on their own: cost (Jenkins on your own hardware is often cheaper), and "everyone else is doing it". If your Jenkins is stable, well-documented and owned by someone who is staying, the honest answer may be to leave it.
How to scope it
Migration effort scales with pipeline complexity, not pipeline count. Sort yours into three tiers before asking anyone for a quote:
| Tier | Characteristics | Typical effort per pipeline |
|---|---|---|
| Simple | Build, test, publish an artefact. No deployment, few plugins. | 0.5–1 engineer-day |
| Moderate | Multi-stage, matrix builds, some shared libraries, deploys to one environment. | 2–4 engineer-days |
| Complex | Orchestrates multi-service deploys, custom Groovy shared libraries, approval gates, cross-job coordination. | 5–15 engineer-days |
Those figures are a planning heuristic drawn from how the work decomposes, not a published market benchmark. Use them to size the exercise and get a fixed quote against your actual inventory.
Add a fixed overhead of 5–15 engineer-days for the work that happens once regardless of pipeline count: runner provisioning, secret migration, org-level policy, reusable workflow design, and the parallel-run period.
A typical mid-market estimate: 25 pipelines skewing simple-to-moderate, one shared library, two deployment environments — roughly 6–10 engineer-weeks including parallel running.
What the automated importer does and does not do
GitHub ships an Actions Importer that converts Jenkins pipelines to workflow YAML. It has a dry-run mode that outputs the converted file and a migrate mode that opens a pull request.
It genuinely helps, and it is a first pass. Plan for manual work on:
- Custom Groovy shared libraries. The heart of most mature Jenkins estates and the least translatable construct. Groovy logic maps to composite actions or reusable workflows, and the mapping is a design decision, not a conversion.
- Plugin-specific steps. Anything depending on a Jenkins plugin needs an Actions equivalent found, or the behaviour rebuilt.
- Agent and node selectors. Jenkins agent labels do not map cleanly to runner labels.
- Credentials. Jenkins credential bindings become GitHub secrets or OIDC, and this is a redesign opportunity rather than a copy.
- Complex conditional logic and approval gates.
The honest rule: the importer handles the pipelines you were not worried about. Budget your engineering time for the three or four that keep you awake.
The parts that actually cause trouble
Secrets and credentials. Consistently the longest pole. Jenkins estates accumulate credentials over years, often undocumented, sometimes shared across pipelines nobody owns. Migration forces an audit, which is valuable and slow. Where you are deploying to a cloud provider, move to OIDC federation rather than copying long-lived keys — you will not get a better opportunity.
Deployment targets. Build conversion is mechanical. Deployment is where a mistake costs a production incident, which is why deployment pipelines should move last, after the build pipelines have proven the runner setup.
Self-hosted runner capacity. If your Jenkins agents had specific hardware, network access or software, that needs replicating. Teams routinely underestimate the network-access piece — a runner that cannot reach an internal artefact repository fails in ways that look like a workflow bug.
The undocumented pipeline. Every estate has one. It runs monthly, nobody owns it, and it turns out to be load-bearing. Find it during inventory, not during cutover.
Running both in parallel
Do not cut over in one weekend. The pattern that works:
- Inventory and tier every pipeline. Identify owners. Flag anything nobody claims.
- Migrate one simple, low-risk pipeline end to end to prove runners, secrets and permissions.
- Run both systems on the same commits. Compare outputs. Discrepancies here are cheap; discrepancies after cutover are not.
- Move build pipelines, then deployment pipelines.
- Freeze Jenkins — read-only, still running — for a release cycle or two before decommissioning.
- Decommission, capturing the configuration in version control first.
Step 5 is the one teams skip to save money, and it is the cheapest insurance in the plan. Jenkins running in read-only mode costs a server; discovering in week three that a compliance report came from a pipeline you deleted costs considerably more.
What this costs to buy in
Three delivery models, with the trade-offs:
| Model | Fits when | Watch for |
|---|---|---|
| Internal team | You have DevOps capacity and no deadline | It becomes the thing that never finishes |
| Contract engineers | Defined scope, you keep the knowledge | Needs an internal owner to hand back to |
| Managed migration | No internal DevOps, want it done | Knowledge transfer must be contractual |
The failure mode with an external migration is not technical. It is a team that ends up with 40 workflows nobody internally understands. Whichever model you choose, make documentation and a handover session explicit deliverables, and have one of your own engineers in the pull requests throughout.
For how contract DevOps engineers are priced, see our DevOps rate benchmark; for the in-house versus managed decision more broadly, DevOps as a service vs in-house.
A note on runner costs
Budget planning for this migration got easier in 2026. GitHub cut hosted-runner prices by up to 39% on 1 January. The $0.002 per minute charge for self-hosted runners, announced for 1 March, was postponed within 48 hours after community backlash and has not been reinstated — self-hosted usage remains free as of August 2026.
Model both anyway. The postponement is a delay, not a guarantee, and a CI estate sized on the assumption that self-hosted compute stays free forever is carrying an unpriced risk. We cover the detail in the GitHub Actions pricing change.
FAQ
How long does a Jenkins to GitHub Actions migration take?
For a mid-market estate of roughly 25 pipelines with two deployment environments, 6–10 engineer-weeks including a parallel-run period. Complexity per pipeline matters far more than count — three deployment-orchestrating pipelines can outweigh twenty simple build jobs.
Can GitHub's Actions Importer do the migration automatically?
It converts pipelines and can open pull requests, and it handles straightforward cases well. Custom Groovy shared libraries, plugin-specific steps, agent selectors and credentials need manual work. Treat its output as a first draft.
What is the hardest part of migrating from Jenkins?
Secrets and credentials, followed by deployment targets. Jenkins estates accumulate undocumented credentials over years, and migration forces an audit that is valuable but slow.
Should we cut over all at once?
No. Prove the setup on one low-risk pipeline, run both systems on the same commits to compare, move builds before deployments, and keep Jenkins read-only for a release cycle before decommissioning.
Is GitHub Actions cheaper than self-hosted Jenkins?
Not necessarily. Jenkins on hardware you already own is often cheaper in direct compute. The saving from Actions is in maintenance, plugin management, patching and the engineer time those consume. Migrate for maintenance burden, not compute cost.
Do we still need self-hosted runners?
Only if you need specific hardware, internal network access, or compliance isolation. Self-hosted runner usage remains free after GitHub postponed the announced per-minute charge, but model both scenarios when sizing.
Planning a CI/CD migration? First Bridge Consulting places DevOps contractors who do this work with knowledge transfer as a deliverable, not an afterthought — and we will tell you when your Jenkins estate is stable enough to leave alone. See our DevOps engineering services, or get a staffing proposal in 48 hours →
Related reading: DevOps Engineer Hourly Rate 2026 · DevOps as a Service vs In-House · How to Hire AWS DevOps Engineers in 2026 · DevOps Engineering services
Sources
Effort figures are First Bridge planning heuristics based on how the work decomposes, stated as such. Product facts below are from GitHub's own documentation and changelog.
- Migrating from Jenkins with GitHub Actions Importer — GitHub Docs (importer capabilities and documented limitations)
- Migrating from Jenkins to GitHub Actions — GitHub Docs (construct mapping, stages to jobs)
- Update to GitHub Actions pricing — GitHub Changelog (January price reduction and the postponed self-hosted charge)
