TL;DR
A comprehensive guide to implementing CI/CD pipelines using Azure DevOps, including best practices, templates, and advanced deployment strategies
Azure DevOps Pipeline: Complete CI/CD Implementation Guide
Azure DevOps Pipelines provides a robust platform for implementing continuous integration and continuous delivery (CI/CD) workflows. This guide explores how to build efficient, secure, and scalable pipelines for your applications.
$1
`` graph TB
subgraph "Source Control"
A["Git Repository"]
B["Branch Policies"]
C["Pull Requests"]
end
subgraph "Build Pipeline"
D["Build Agent"]
E["Build Steps"]
F["Artifacts"]
end
subgraph "Release Pipeline"
G["Environments"]
H["Approvals"]
I["Deployment"]
end
A --> D
B --> D
C --> D
D --> E
E --> F
F --> G
G --> H
H --> I
classDef azure fill:#0078D4,stroke:#fff,color:#fff
class A,B,C,D,E,F,G,H,I azure
mermaid
`
$1
| Component | Description | Purpose |
|---|---|---|
| Triggers | Event-based pipeline initiation | Automation |
| Stages | Logical grouping of jobs | Organization |
| Jobs | Series of steps | Execution |
| Steps | Individual tasks | Implementation |
$1
$1
` trigger:
branches:
include:
- main
- develop
paths:
exclude:
- docs/*
- '*.md' variables:
solution: '*/.sln'
buildPlatform: 'Any CPU'
buildConfiguration: 'Release' stages:
jobs:
- job: BuildJob
pool:
vmImage: 'ubuntu-latest'
steps:
- task: DotNetCoreCLI@2
inputs:
command: 'restore'
projects: '$(solution)'
- task: DotNetCoreCLI@2
inputs:
command: 'build'
projects: '$(solution)'
arguments: '--configuration $(buildConfiguration)'
- task: DotNetCoreCLI@2
inputs:
command: 'test'
projects: '*/*Tests/.csproj'
arguments: '--configuration $(buildConfiguration)'
- task: DotNetCoreCLI@2
inputs:
command: 'publish'
publishWebProjects: true
arguments: '--configuration $(buildConfiguration) --output $(Build.ArtifactStagingDirectory)'
- task: PublishBuildArtifacts@1
inputs:
pathtoPublish: '$(Build.ArtifactStagingDirectory)'
artifactName: 'drop'
yaml
`azure-pipelines.yml
$1
` trigger:
branches:
include:
- main variables:
dockerRegistry: 'myregistry.azurecr.io'
imageName: 'myapp'
tag: '$(Build.BuildId)' stages:
jobs:
- job: BuildJob
pool:
vmImage: 'ubuntu-latest'
steps:
- task: Docker@2
inputs:
containerRegistry: 'ACR'
repository: '$(imageName)'
command: 'buildAndPush'
Dockerfile: '/Dockerfile'
tags: |
$(tag)
latest
yaml
`container-pipeline.yml
$1
$1
| Environment | Approval Type | Deployment Strategy |
|---|---|---|
| Development | Automated | Direct |
| Staging | Manual | Blue-Green |
| Production | Gated | Canary |
$1
` stages:
jobs:
- deployment: BlueGreen
environment: staging
strategy:
blueGreen:
deploy:
steps:
- task: AzureWebApp@1
inputs:
azureSubscription: 'Azure'
appName: '$(webAppName)-staging'
package: '$(Pipeline.Workspace)/drop/*/.zip'
routeTraffic:
steps:
- task: AzureAppServiceManage@0
inputs:
azureSubscription: 'Azure'
action: 'Swap Slots'
webAppName: '$(webAppName)'
sourceSlot: 'staging'
targetSlot: 'production'
postRouteTraffic:
steps:
- task: AppInsightsAlerts@0
inputs:
applicationInsightsWebTestId: '$(webTestId)'
alertRule: 'Availability < 99%'
yaml
`deployment-strategies.yml
$1
$1
` trigger:
branches:
include:
- main variables:
sonarQubeProject: 'myproject'
steps:
inputs:
SonarQube: 'SonarQube'
scannerMode: 'MSBuild'
projectKey: '$(sonarQubeProject)'
inputs:
command: 'build'
yaml
security-pipeline.yml
inputs:
cwd: '$(System.DefaultWorkingDirectory)'
inputs:
azureSubscription: 'Azure'
KeyVaultName: '$(keyVaultName)'
SecretsFilter: '*'
`
$1
| Check Type | Tool | Purpose |
|---|---|---|
| Code Quality | SonarQube | Static Analysis |
| Security | WhiteSource | Dependency Scanning |
| Compliance | Azure Policy | Policy Enforcement |
$1
$1
` const analyticsConfig = {
metrics: {
pipeline: {
successRate: 'percentage',
duration: 'minutes',
frequency: 'daily'
},
quality: {
coverage: 'percentage',
bugs: 'count',
vulnerabilities: 'count'
},
performance: {
buildTime: 'minutes',
deploymentTime: 'minutes',
failureRate: 'percentage'
}
},
alerts: [
{
name: 'PipelineFailure',
condition: 'successRate < 80%',
severity: 'high'
},
{
name: 'LongDuration',
condition: 'duration > 60',
severity: 'medium'
}
]
};
typescript
`
$1
| Metric | Target | Action if Exceeded |
|---|---|---|
| Build Time | < 10 minutes | Optimize build steps |
| Deployment Time | < 5 minutes | Review deployment strategy |
| Success Rate | > 95% | Investigate failures |
$1
$1
1. Template Usage
` # template.yml
parameters:
environment: ''
serviceConnection: ''
steps:
- task: AzureWebApp@1
inputs:
azureSubscription: ${{ parameters.serviceConnection }}
appName: '$(webAppName)'
deployToSlotOrASE: true
resourceGroupName: '$(resourceGroup)'
slotName: ${{ parameters.environment }}
yaml
`
2. Variable Management
` variables:
- group: common-vars
- group: ${{ parameters.environment }}-vars
- name: buildConfiguration
value: 'Release'
- name: solution
value: '*/.sln'
yaml
``
$1
$1
| Issue | Cause | Solution |
|---|---|---|
| Build Failures | Dependencies | Update packages |
| Deployment Errors | Permissions | Check service connections |
| Test Failures | Environment issues | Verify test configuration |
$1
1. [Azure DevOps Documentation](https://docs.microsoft.com/azure/devops)
2. [YAML Schema Reference](https://docs.microsoft.com/azure/devops/pipelines/yaml-schema)
3. [Pipeline Best Practices](https://docs.microsoft.com/azure/devops/pipelines/best-practices)
4. [Security and Compliance](https://docs.microsoft.com/azure/devops/pipelines/security)
5. [Pipeline Analytics](https://docs.microsoft.com/azure/devops/pipelines/reports)
6. [Deployment Strategies](https://docs.microsoft.com/azure/devops/pipelines/release)
$1
Why This Matters
Understanding the business and technical context helps you make informed decisions rather than blindly following patterns.
Trade-offs to Consider
Every architectural decision involves trade-offs. Consider your specific requirements, team expertise, and scale when evaluating options.
When NOT to Use This
Knowing when a solution doesn't apply is as valuable as knowing when it does. Consider alternatives for your specific situation.
Decision Framework
Use this framework to evaluate whether this approach is right for your use case based on your specific constraints and requirements.