Azure DevOps CI/CD: YAML pipeline stages
Tags: azure, devops, cicd
Published: 2020-05-03 19:40:53

---
title: Azure DevOps CI/CD: YAML pipeline stages
published: true
description: Azure pipeline YAML
tags: Azure, DevOps, CICD
---

Azure DevOps provides two ways to create CI pipelines and CD (release) pipelines. Classic editor and YAML. Classic editor provides a UI to create pipelines and this requires two steps.
   - Build pipeline
   - Release pipeline

Classic editor was the default way of creating pipelines and releases before YAML was introduced. However with classic editor creating separate release pipeline for each project is a tedious task compared to the single pipeline in YAML. 

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/mn39xrcfk6dm8x5oe8rx.png)

With YAML both CI and CD tasks can be version controlled unlike with the classic editor.

Using YAML is the new approach of creating pipelines where we can include both CI/CD steps in one YAML file.

By default YAML pipelines are created when creating a build pipeline. We can include CD steps by adding `stages`.

A simple pipeline with `build`, `test` and `publish to staging` looks like this, (focus only on number of `stages`, specifics in tasks doesn't matter in this context)

```yaml
trigger:
- master

variables:
  debug: true
  solution: '**/*.sln'
  buildPlatform: 'Any CPU'
  buildConfiguration: 'Release'
  iISDeploymentType: 'IISWebsite'

stages:
- stage: Build
  jobs:
    - job: Build
      pool:
        vmImage: 'windows-latest'

      steps:
      - task: NuGetToolInstaller@1

      - task: NuGetCommand@2
        inputs:
          restoreSolution: '$(solution)'

      - task: VSBuild@1
        inputs:
          solution: '$(solution)'
          msbuildArgs: '/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:PackageLocation="$(build.artifactStagingDirectory)"'
          platform: '$(buildPlatform)'
          configuration: '$(buildConfiguration)'

      - task: VSTest@2
        inputs:
          platform: '$(buildPlatform)'
          configuration: '$(buildConfiguration)'

      - task: PublishPipelineArtifact@1
        inputs:
          targetPath: '$(build.artifactStagingDirectory)\Test.Web.zip'
          artifact: 'drop'

- stage: DeployStaging
  displayName: 'Deploy to staging'
  dependsOn: 'Build'
  condition: succeeded()
  jobs:
  - deployment: DeployWeb
    displayName: Deploy Test API
    pool:
      vmImage: 'windows-latest'
    environment:
      name: test-stg
      resourceType: VirtualMachine
      tags: web
    strategy:
      runOnce:
        deploy:
          steps:
          - task: DownloadPipelineArtifact@2
            inputs:
              path: '$(System.ArtifactsDirectory)'
              artifactName: 'drop'

          - task: IISWebAppManagementOnMachineGroup@0
            displayName: 'IIS Web App Manage'
            inputs:
              IISDeploymentType: 'IISWebsite'
              ActionIISWebsite: 'CreateOrUpdateWebsite'
              WebsiteName: 'TestCloudTestDemo'
              websitePhysicalPath: '%SystemDrive%\inetpub\wwwroot'
              websitePhysicalPathAuth: 'WebsiteUserPassThrough'
              AddBinding: true
              protocol: 'http'
              iPAddress: 'All Unassigned'
              port: '85'
              Bindings:
              CreateOrUpdateAppPoolForWebsite: true
              AppPoolNameForWebsite: 'TestCloudTestDemo'
              ParentWebsiteNameForVD: '$(Parameters.WebsiteName)'
              virtualPathForVD:
              physicalPathForVD: '%SystemDrive%\inetpub\wwwroot'
              ParentWebsiteNameForApplication: '$(Parameters.WebsiteName)'
              VirtualPathForApplication: '$(Parameters.VirtualPathForApplication)'
              AppPoolName: '$(Parameters.AppPoolName)'
              appPoolNameForApplication:
              dotNetVersionForApplication: 'v4.0'
              pipeLineModeForApplication: 'Integrated'
              appPoolIdentityForApplication: 'ApplicationPoolIdentity'

          - task: IISWebAppDeploymentOnMachineGroup@0
            displayName: 'IIS Web App Deploy'
            inputs:
              WebSiteName: 'TestCloudTestDemo'
              package: '$(System.ArtifactsDirectory)\**\*.zip'
              XmlVariableSubstitution: True
```

This pipeline has two stages. `Build` stage builds, tests and publishes the artifact to next stage. This is quite important. Otherwise the next stage cannot access the build artifact, since it's going to deploy (CD stage) the artifact to the `staging` environment.

The `DeployStaging` stage downloads the build artifact from earlier stage and runs two tasks to deploy the artifact to IIS. Notice how `condition` is used in the last stage. Conditions can be used to control the execution of each stage in pipeline. For instance if we have 3 stages (test, staging and prod) and we need to only up to staging, conditions can be used to control the execution.

```yaml
condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/master'))
```

This condition refers to the branch on which the commit was made. Only if it was the master branch, this stage will get executed.

References: 
https://docs.microsoft.com/en-us/azure/devops/pipelines/get-started/pipelines-get-started?view=azure-devops

https://docs.microsoft.com/en-us/azure/devops/pipelines/yaml-schema?view=azure-devops&tabs=schema%2Cparameter-schema