Post

📋 Migrate from Classic to YAML Pipelines in Azure DevOps

In my previous blog, I explained why you should migrate from Classic Pipelines to YAML. This blog dives deeper into the steps for a smooth migration.

Why switch to YAML?

Migrating from Classic Pipelines to YAML is more than just rewriting in YAML. YAML pipelines work fundamentally differently and may seem complex at first. However, this approach offers key benefits:

  • Pipelines as code: Better version control and collaboration.
  • Reusability: Less duplicate code with YAML templates.
  • Improved reviews: Integration with pull requests for better control.

How to migrate to YAML?

It depends on whether you’re just starting or if you’re down to the last remaining pipelines. If you’re starting fresh, follow the steps below. If you already have YAML pipelines, you can skip some steps.

Step 1: 🚀 Create new pipelines in YAML

Avoid future migration work by setting up new pipelines directly in YAML. Microsoft’s documentation provides sufficient guidance on YAML pipelines.

Step 2: ⚙️ Prevent new Classic Pipelines

Disable the creation of Classic Pipelines to ensure teams don’t accidentally continue using outdated methods. You can do this via: Project Settings > Pipelines > Settings > Disable creation of classic pipelines

Disable creation of classic pipelines Disable creation of classic pipelines

Step 3: 🗺️ Map out your existing pipelines

  • How many Classic Pipelines exist?
  • What do they do?
  • Are they Build or Release pipelines?
  • What dependencies do they have (Service Connections, approvals, variables)?
  • Are Task Groups or other reusable components used?

This helps plan the migration and prevents surprises.

Step 4: 🍳 Start simple

Begin with a small, simple pipeline. For Build pipelines, you can export YAML via: More actions > Export as YAML

Export as YAML Export as YAML

This provides a good starting point, but keep in mind that exports are not always complete and often require manual adjustments.

Release pipelines require more manual effort since there’s no direct YAML export option. Start with simple deployments and expand step by step.

1
2
3
4
5
6
7
8
jobs:
- job: Job_1
  displayName: Agent job 1
  pool:
    vmImage: windows-latest
  steps:
  - checkout: self
  - task: ...

Step 5: ♻️ Reuse with YAML templates

If you have repetitive tasks, convert them into templates to avoid duplicate code and simplify maintenance. YAML supports templates for stages, jobs, steps, variables, or even entire pipelines.

1
2
3
4
5
6
7
8
9
stages:
  - stage: Build
    jobs:
      - template: templates/build.yml
  - stage: Deploy
    jobs:
      - template: templates/deploy.yml
        parameters:
          environment: dev

Templates can be included to incorporate specific sections in your pipeline, or you can extend from a template. The latter determines the pipeline structure, allowing customization through parameters. This approach enables the creation of more secure pipelines.

Step 6: 🧱 Create multistage pipelines

Classic Pipelines separate build and release, but with YAML, you can manage everything in a single pipeline. Use stages, deployment jobs, and environments for more flexibility, reducing overhead.

Stages in Classic vs. YAML

In Classic Release Pipelines, you configure approvals and gates per stage using the UI. In YAML, things work differently.

YAML pipelines introduce new components: environments and deployment jobs. Deployment jobs are similar to jobs, as they consist of multiple tasks. However, a deployment job always runs in an environment, allowing you to define different deployment strategies.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
stages:
- stage: DeployToProduction
  jobs:
  - deployment: Deploy
    environment: Production
    strategy:
      runOnce:
        preDeploy:
          steps:
          - script: |
              echo "Create backup"
              ...
        deploy:
          steps:
          - script: |
              echo "Deploying to Production"
              ./runDeployment.sh ...
        on:
          failure:         
            steps:
            - script: |
              echo "Restore backup"
              ...

At first, this may seem complex, but it has significant benefits. Environments are reusable. You only need to configure who can approve deployments once, and this prevents releases without approval. This also works well when combined with template extensions.

Step 7: 🏎️ Speed up migration with Yamlizr

Yamlizr is a useful CLI tool for converting Classic Pipelines to YAML. It generates YAML based on the tasks and settings used.

It’s not a one-click migration tool, but it can significantly speed up your transition. Yamlizr automatically generates YAML code for all your pipelines, which you can easily use to quickly assemble your YAML pipelines. You’ll have to figure out much less on your own and get a great kick-start for converting parts of your pipeline quickly.

How does it work?

Check out the Yamlizr GitHub page for details, but in short:

  1. Install Yamlizr.
  2. Create a PAT, select a project, and run:

    yamlizr generate -pat <your PAT here> -org <your AzDO Organisation Uri> -proj <your AzDO project name> -out <Your output location>

  3. Review and adjust the generated YAML as needed.

Although Yamlizr automates a lot of the work, it’s important to thoroughly review the generated YAML. Specific settings or custom tasks may require manual adjustments.

Note on Release Pipelines:

Yamlizr converts everything into jobs by default. If you have approvals in your current release flow, you must manually convert them to deployment jobs and configure environments.

Step 8: 🧪 Validate and test

Run YAML pipelines in parallel with Classic Pipelines, then compare logs and outputs. This ensures a safe migration without risks.

Seeing unexpected results? Check your pipeline thoroughly. Conditions or expressions may behave differently than expected.

Step 9: 🧹 Migrate and clean up

Once the YAML pipeline is stable, remove the Classic Pipeline or move it to a restricted folder. This prevents accidental reuse.

Also, update documentation so your team understands the new YAML workflow.

Final tips

  • Test YAML with Validate YAML.
  • Use the “task assistant to explore task input fields.
  • Utilize variables and variable groups for reusability.
  • Use parameters to control pipeline input values.

Need help with your migration? Feel free to reach out! 🚀

This post is licensed under CC BY 4.0 by the author.