Skip to main content
Cloud DevOps Solutions
Get a quote Talk to an engineer

Azure DevOps

Migrating from Jenkins or GitHub Actions to Azure Pipelines

Migrating to Azure Pipelines means inventorying existing jobs, deciding which to convert, retire or redesign, rebuilding them as reusable YAML, moving secrets and agents, and running old and new side by side before cutover. We migrate in waves by risk, so delivery continues throughout.

Key takeaways

  • Inventory first: many Jenkins jobs are unused and should be retired, not converted.
  • A line-by-line translation of a Jenkinsfile usually produces a poor pipeline, so we redesign around templates.
  • Secrets and credentials need a clean move, not a copy, which is a chance to remove old ones.
  • Run old and new pipelines in parallel for a period and compare outputs before switching.
  • Migrate in waves, with low-risk services first and critical release pipelines later.

Why teams leave Jenkins, and why migrations stall

The reasons are consistent. A Jenkins server that nobody wants to upgrade, plugins with security advisories, pipelines written in Groovy by someone who has left, and a controller that is a single point of failure. Teams that already use Azure Boards, Repos or Artifacts also want one system for planning, code and delivery.

Migrations stall for a different reason: they are treated as translation. Someone starts converting the largest Jenkinsfile line by line, hits a plugin with no equivalent and the project loses momentum. This page describes the method we use as part of our Azure DevOps consulting to avoid that. If you are leaving Jenkins for a different target, our guide to migrating Jenkins to GitHub Actions covers that route, and the wider picture is in our CI/CD pipeline service.

What good looks like

  • Every job in scope is classified: convert, redesign or retire.
  • New pipelines are built from shared templates, not copied YAML.
  • No credential is copied across unchanged; each is reviewed, rotated or removed.
  • Old and new pipelines run side by side until results match.
  • Developers know what changed for them and where to look.
  • The old server has a decommission date and it is met.

How it works in practice

Inventory before anything else

We export the job list, the Jenkinsfiles and shared library code, the installed plugins, the credentials store and the agent definitions. Then we ask for each job: when did it last run, who owns it, and what depends on its output? In most estates a meaningful share of jobs have not run for months. Retiring them is the cheapest migration work there is.

Mapping concepts

JenkinsAzure Pipelines
Jenkinsfile (declarative)azure-pipelines.yml
Stages and stepsStages, jobs and steps
Shared libraryTemplate repository
Credentials storeService connections and Key Vault
Agents and labelsAgent pools and demands
Post actionsConditions such as succeeded() and always()
Multibranch pipelineBranch triggers and pull request validation

The mapping is a guide, not a recipe. A Jenkins shared library with many functions is usually better expressed as pipeline templates with parameters.

A before and after

A simple declarative stage:

stage('Test') {
  steps { sh 'npm ci && npm test' }
  post { always { junit 'reports/*.xml' } }
}

becomes, in the target design:

- job: Test
  steps:
    - script: npm ci && npm test
      displayName: Test
    - task: PublishTestResults@2
      condition: always()
      inputs:
        testResultsFormat: JUnit
        testResultsFiles: "reports/*.xml"

The translation is easy here. The real work is in everything around it: caching, artefact handling, deployment and credentials. See multi-stage YAML design for the structure we aim for.

Agents and credentials

Jenkins agents often have tools installed by hand. We replace them with Microsoft-hosted agents where possible, and with self-hosted agent pools where network access or tooling demands it. Credentials move into Key Vault and service connections rather than being copied. This is the best moment to find and revoke the ones nobody recognises.

Coming from GitHub Actions

Workflows map to pipelines, jobs to jobs, reusable workflows to templates, and secrets to variable groups or Key Vault. Marketplace actions need an equivalent task, extension or script, and hosted runner labels become pool selections. The decision to move should rest on a real need, such as consolidating on Azure DevOps. If the repositories stay on GitHub, Azure Pipelines can still build them through a GitHub service connection.

Parallel running

For each wave, the new pipeline runs alongside the old one. We compare produced artefacts, test results, deployment outcomes and timings. Only when they agree for an agreed number of runs do we disable the Jenkins trigger. Deployments should be made by one system only at a time, to avoid both pushing to the same target.

Sequencing the waves

We order services by risk rather than by team. The first wave is internal tools and libraries whose failure affects few people. The second is customer-facing services with simple deployments. The last is the release pipelines that touch production databases or have strict change controls, because by then the templates, agents and credential patterns have been proven. Each wave ends with a short review: what broke, which template needed a parameter, which plugin had no equivalent. The findings feed the next wave, so effort per service falls as the migration proceeds.

Decisions and trade-offs

Redesign or lift and shift? Lift and shift is faster for a handful of stable jobs. For a large estate, templates pay back quickly because later waves reuse them.

Big bang or waves? Waves cost more calendar time but keep risk low. Big bang only suits small estates with few release pipelines.

Hosted or self-hosted agents? Hosted is simpler to run. Self-hosted gives network reach and custom tooling.

When not to migrate. If Jenkins is stable, patched and well understood, and nothing about Azure DevOps solves a problem you have, the cost may not be justified. Migration should buy something specific.

Common failure modes

  • Converting dead jobs. Effort spent on pipelines nobody uses.
  • Hidden plugin dependencies. A job quietly relies on a plugin side effect.
  • Credential copying. Old secrets carried over unchanged.
  • Double deployment. Both systems deploy during overlap.
  • No decommission date. Jenkins lives on beside Azure DevOps for years.

Delivery and handover

You receive the inventory and classification, a template library, converted pipelines with owners, a parallel-run comparison log, a cutover checklist and a decommission record showing credentials revoked. Developer notes explain the differences in daily workflow. To scope your migration, contact us.

How to tell it is working

Build and deploy success rates match or beat the old system, the Jenkins server is switched off on schedule, new services start from templates rather than copied files, and nobody asks where to find a build log.

References

How we deliver it

  1. 01

    Inventory and classify

    We list every job, trigger, plugin, credential and agent, then classify each as convert, redesign or retire.

  2. 02

    Design the target

    Repository layout, template library, agent pools, service connections and naming are decided before any conversion starts.

  3. 03

    Build a pilot

    One representative service is converted end to end to prove patterns and expose plugin gaps.

  4. 04

    Convert in waves

    Services move in groups, using the shared templates, with owners reviewing their own pipelines.

  5. 05

    Run in parallel

    Old and new pipelines produce the same artefacts and deployments are compared before the old trigger is disabled.

  6. 06

    Cut over and decommission

    Triggers are switched, Jenkins is made read-only for a retention period, then retired with credentials revoked.

Tools and technologies

Azure PipelinesJenkinsGitHub ActionsAzure Key VaultAzure ArtifactsDockerTerraformAzure Container RegistryPipeline templates

Frequently asked questions

Is there an automatic tool to convert a Jenkinsfile to Azure Pipelines?
There are converters and importers that handle simple cases, and they are a useful starting point for inventory. They rarely produce good pipelines for real estates because plugins, shared libraries and credentials do not translate directly. We use tooling to speed discovery, then rebuild around templates and review each result.
How long does a Jenkins to Azure DevOps migration take?
It depends on the number of distinct pipeline patterns more than the number of jobs. Fifty jobs that follow three patterns are quicker than ten bespoke ones. After a short inventory we can give a realistic estimate, because plugin use and custom shared libraries are the main unknowns.
Can we keep some Jenkins jobs after migrating?
Yes. A phased migration often leaves a few awkward or rarely used jobs on Jenkins for a while. The important thing is to set an end date, otherwise the old server lingers with unpatched plugins and outdated credentials, which is both a cost and a security risk.
What happens to our Jenkins plugins?
Each plugin is matched to a built-in task, a marketplace extension, a script or a retirement decision. Many plugins exist only to work around Jenkins itself and are no longer needed. Plugins for niche tools may need a script wrapper, which we document and test.
Is GitHub Actions to Azure Pipelines a sensible move?
Sometimes, for example when a company standardises on Azure DevOps for boards, artefacts and governance. The concepts map well, but marketplace actions need equivalents and reusable workflows become templates. If you are unsure which platform to use, we compare them before you commit.

Talk to an engineer about migrate jenkins to azure devops

Book a free 30-minute call. We review your current setup and tell you honestly whether and how we can help.

Written by Saddique Khan, DevOps / SRE / Cloud Consultant Engineer. Last updated 2026-10-08.