Building a YAML pipeline

Basic

We define a trigger, in the case below we trigger the pipeline when main branch is updated.

An ubuntu agent is selected for the job.

We define stages that contain jobs which intern contain steps.

These may include arguments such as like displayName, isSkippable, & dependsOn

trigger:
- main

pool:
  vmImage: 'ubuntu-latest'

stages:
- stage: Build
  displayName: 'Build Stage'
  jobs:
  - job: BuildJob
    displayName: 'Build Job'
    steps:
    - script: |
        echo "Restoring project dependencies..."
      displayName: 'Restore dependencies'
    - script: |
        echo "Compile code"
      displayName: 'Compile code'
- stage: Test
  displayName: 'Test Stage'
  dependsOn: Build
  isSkippable: false
  jobs:
  - job: TestJob
    displayName: 'Test Job'
    steps:
    - script: |
        echo "Running unit tests..."
      displayName: 'Run unit tests'

Deploy to Non-Prod

When deploying to stages it is typical that you will include a timeoutInMinutes, this allows you to determine if you want the pipeline to proceed to the next stage

- stage: DeployToStaging
  displayName: 'Deploy to Staging'
  dependsOn: Test
  jobs:
  - job: DeployStagingJob
    displayName: 'Deploy to Staging Job'
    pool:
      vmImage: 'ubuntu-latest'
    steps:
    - script: |
        echo "Build staging job..."
      displayName: 'Build and deploy to staging'

  - job: DeployStagingJobWithValidation
    pool: server
    timeoutInMinutes: 4320 # job times out in 3 days
    displayName: 'Deploy to Staging Job'
    steps:
    - task: ManualValidation@1
      timeoutInMinutes: 1440 # task times out in 1 day
      inputs:
        notifyUsers: user@example.com
        instructions: 'Please validate the stage configuration and resume'
        onTimeout: 'resume'

Deploy to Prod

- stage: DeployToProduction
  displayName: 'Deploy to Production'
  dependsOn: DeployToStaging
  lockBehavior: sequential
  condition: and(succeeded(), in(variables['Build.SourceBranch'], 'refs/heads/main', 'refs/heads/release'))
  jobs:
  - job: DeployProductionJob
    displayName: 'Deploy to Production Job'
    steps:
    - script: |
        echo "Deploying to production..."
        # Add your deployment commands here
      displayName: 'Run deployment commands'
  - job: waitForValidation
    displayName: Wait for external validation
    pool: server
    timeoutInMinutes: 4320 # job times out in 3 days
    steps:
    - task: ManualValidation@1
      timeoutInMinutes: 1440 # task times out in 1 day
      inputs:
        notifyUsers: user@example.com
        instructions: 'Please validate the build configuration and resume'
        onTimeout: 'resume'

Rollback

Upon success you may want to deploy to the remaining machines

- stage: DeployToAlternateProduction
  displayName: 'Deploy to Alternate Production'
  condition: succeeded()
  trigger: manual
  jobs:
  - job: DeployAlternateProductionJob
    displayName: 'Deploy to Alternate Production Job'
    steps:
    - script: |
        echo "Deploying to alternate production..."
        # Add your deployment commands here
      displayName: 'Run deployment commands'

Upon a failure you may want to include a manually triggered rollback

- stage: Rollback
  displayName: 'Rollback Stage'
  trigger: manual
  jobs:
  - job: RollbackJob
    displayName: 'Rollback Job'
    steps:
    - script: |
        echo "Rolling back the deployment..."
        # Add your rollback commands here
      displayName: 'Run rollback commands'