Azure DevOps Pipelines: A Complete Guide

Azure DevOps Pipelines: A Complete Guide

Master Azure DevOps Pipelines to build, test, and deploy your applications automatically with YAML pipelines, environments, and deployment gates.

Azure DevOps Pipelines provides a comprehensive CI/CD platform integrated with Azure. In this guide, we’ll build a complete pipeline that includes building, testing, and deploying a containerized application to AKS.

Pipeline Structure

A well-structured Azure DevOps pipeline follows this pattern:

Trigger → Build → Test → Publish → Deploy (Dev) → Deploy (Staging) → Deploy (Prod)

Multi-Stage YAML Pipeline

# azure-pipelines.yml
trigger:
  branches:
    include:
      - main
      - release/*
  paths:
    exclude:
      - README.md
      - docs/**

variables:
  containerRegistry: 'myacr.azurecr.io'
  imageRepository: 'myapp'
  dockerfilePath: '$(Build.SourcesDirectory)/Dockerfile'
  tag: '$(Build.BuildId)'

stages:
  - stage: Build
    displayName: 'Build & Test'
    jobs:
      - job: BuildAndTest
        pool:
          vmImage: 'ubuntu-latest'
        steps:
          - task: UseDotNet@2
            inputs:
              packageType: 'sdk'
              version: '8.x'
          
          - script: dotnet restore
            displayName: 'Restore dependencies'
          
          - script: dotnet build --no-restore --configuration Release
            displayName: 'Build'
          
          - script: dotnet test --no-build --configuration Release --logger trx
            displayName: 'Run Tests'
          
          - task: PublishTestResults@2
            inputs:
              testResultsFormat: 'VSTest'
              testResultsFiles: '**/*.trx'
          
          - task: Docker@2
            displayName: 'Build & Push Docker image'
            inputs:
              command: buildAndPush
              repository: $(imageRepository)
              dockerfile: $(dockerfilePath)
              containerRegistry: 'myACRConnection'
              tags: |
                $(tag)
                latest

Deployment to AKS

  - stage: DeployDev
    displayName: 'Deploy to Development'
    dependsOn: Build
    condition: succeeded()
    variables:
      - group: dev-variables
    jobs:
      - deployment: DeployToDev
        displayName: 'Deploy to AKS Dev'
        environment: 'development.default'
        strategy:
          runOnce:
            deploy:
              steps:
                - task: KubernetesManifest@1
                  displayName: 'Deploy to Kubernetes'
                  inputs:
                    action: 'deploy'
                    connectionType: 'azureResourceManager'
                    azureSubscriptionConnection: 'My Azure Subscription'
                    azureResourceGroup: 'myapp-dev-rg'
                    kubernetesCluster: 'myapp-dev-aks'
                    manifests: |
                      $(Pipeline.Workspace)/manifests/deployment.yaml
                      $(Pipeline.Workspace)/manifests/service.yaml
                    containers: '$(containerRegistry)/$(imageRepository):$(tag)'

Environment Approval Gates

For production deployments, use approval gates:

  - stage: DeployProd
    displayName: 'Deploy to Production'
    dependsOn: DeployStaging
    condition: and(succeeded(), eq(variables['Build.SourceBranch'], 'refs/heads/main'))
    jobs:
      - deployment: DeployToProd
        displayName: 'Deploy to AKS Production'
        environment: 'production.default'  # Has manual approval configured
        strategy:
          runOnce:
            deploy:
              steps:
                - task: KubernetesManifest@1
                  inputs:
                    action: 'deploy'
                    manifests: '$(Pipeline.Workspace)/k8s/production/**'
                    containers: '$(containerRegistry)/$(imageRepository):$(tag)'

Pipeline Templates

Create reusable templates to avoid code duplication:

# templates/deploy-to-aks.yml
parameters:
  - name: environment
    type: string
  - name: imageTag
    type: string
  - name: kubernetesServiceConnection
    type: string

steps:
  - task: KubernetesManifest@1
    displayName: 'Deploy ${{ parameters.environment }}'
    inputs:
      action: 'deploy'
      kubernetesServiceConnection: '${{ parameters.kubernetesServiceConnection }}'
      namespace: '${{ parameters.environment }}'
      manifests: '$(Pipeline.Workspace)/manifests/**'
      containers: '$(containerRegistry)/$(imageRepository):${{ parameters.imageTag }}'

Security Best Practices

  1. Use variable groups for sensitive configuration
  2. Enable secret scanning with Azure Defender
  3. Implement branch policies to require PR reviews
  4. Use service principals with minimum required permissions
  5. Rotate secrets regularly using Azure Key Vault integration

Conclusion

Azure DevOps Pipelines provides everything you need for enterprise-grade CI/CD. By using multi-stage pipelines, approval gates, and reusable templates, you can build reliable, automated deployment processes that scale with your organization.