Continuous Deployment to Azure
Extend the pipeline with a deployment stage that pushes the build artifact to an App Service slot, runs smoke tests, and swaps to production on approval.
Continuous Deployment to Azure is a free Cloud & IT Cert Prep lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Cloud & IT Cert Prep learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.
What Is Continuous Deployment?
Continuous Deployment (CD) automatically releases every change that passes CI tests to production without manual intervention. Continuous Delivery is the softer version — it automates deployment up to a staging environment and requires a human approval gate before production. Both practices are built on the same pipeline infrastructure. In Azure Pipelines, CD is implemented by adding deployment stages after the CI stage, targeting Azure environments with approval gates as needed.
Multi-Stage Pipeline: CI + CD
A complete CI/CD pipeline has at least three stages: Build (compile, test, publish artifact), Deploy to Staging (deploy artifact to a non-production slot), and Deploy to Production (swap slot or deploy after approval). Stages pass the artifact forward via pipeline artifact storage. The staging stage runs integration or smoke tests automatically; the production stage waits for manual approval before proceeding.
# azure-pipelines.yml: multi-stage CI/CD
trigger:
branches:
include: [main]
pool:
vmImage: ubuntu-latest
stages:
- stage: Build
jobs:
- job: BuildApp
steps:
- script: npm ci && npm run build
- task: PublishPipelineArtifact@1
inputs: {targetPath: dist, artifactName: webapp}
- stage: DeployStaging
dependsOn: Build
jobs:
- deployment: StagingDeploy
environment: Staging
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
inputs: {appName: myapp-staging, package: '$(Pipeline.Workspace)/webapp'}
- stage: DeployProduction
dependsOn: DeployStaging
jobs:
- deployment: ProductionDeploy
environment: Production # Has manual approval gate
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
inputs: {appName: myapp, package: '$(Pipeline.Workspace)/webapp'}Deployment Jobs and Environments
Use deployment jobs (not regular job) for deployment stages. Deployment jobs support deployment strategies (runOnce, rolling, canary), track deployment history per environment, and are required to reference Azure DevOps Environments. An environment records which pipeline runs deployed to it, what version is currently live, and provides approval gates, checks, and resource health status in a single dashboard.
# Deployment job with rolling strategy
- job: RollingDeploy
strategy:
rolling:
maxParallel: 2 # Deploy to 2 targets at a time
preDeploy:
steps:
- script: echo 'Pre-deploy checks'
deploy:
steps:
- task: AzureWebApp@1
inputs:
appName: myapp
package: '$(Pipeline.Workspace)/webapp'
postRouteDeploy:
steps:
- script: curl -f https://myapp.azurewebsites.net/healthDeploying to Azure App Service
The AzureWebApp@1 task deploys a web application to Azure App Service. It supports deploying to a specific slot (e.g., staging), deploying ZIP packages, Docker images, or JAR/WAR files. After deploying to a staging slot, use the AzureAppServiceManage@0 task to swap the staging slot into production — the preferred zero-downtime deployment pattern for App Service.
# Deploy to staging slot, then swap to production
steps:
- task: AzureWebApp@1
displayName: 'Deploy to staging slot'
inputs:
azureSubscription: 'AzureProductionSC'
appType: webAppLinux
appName: myUniqueWebApp
deployToSlotOrASE: true
resourceGroupName: MyRG
slotName: staging
package: '$(Pipeline.Workspace)/webapp/app.zip'
runtimeStack: 'NODE|18-lts'
- task: AzureAppServiceManage@0
displayName: 'Swap staging into production'
inputs:
azureSubscription: 'AzureProductionSC'
action: Swap Slots
webAppName: myUniqueWebApp
resourceGroupName: MyRG
sourceSlot: stagingSmoke Tests in the CD Pipeline
After deploying to staging, run smoke tests — a minimal set of tests that verify the deployment succeeded and the application is responding correctly. Smoke tests typically call key API endpoints and verify expected status codes and response content. If smoke tests fail, the pipeline stops before swapping to production or requesting approval, preventing a broken release from reaching users.
# Smoke test step after staging deployment
- script: |
MAX_RETRY=10
COUNT=0
until curl -sf https://myUniqueWebApp-staging.azurewebsites.net/health; do
COUNT=$((COUNT+1))
if [ $COUNT -ge $MAX_RETRY ]; then
echo 'Health check failed after $MAX_RETRY attempts'
exit 1
fi
echo 'Waiting for app to start... attempt '$COUNT
sleep 10
done
echo 'App is healthy'
displayName: 'Smoke test: health endpoint'Environment Approval Gates
Add approval gates to Azure DevOps Environments to require manual sign-off before deployments proceed. Navigate to the environment settings and add Approvals — specify users or groups who must approve. When the pipeline reaches a deployment job targeting that environment, it pauses and sends an email notification. Approvers can view the deployment details and approve or reject in the Azure DevOps portal or the notification email link.
# Pipeline YAML: deployment to production environment
# (Approval configured in Azure DevOps portal on 'Production' environment)
- stage: DeployProduction
displayName: 'Deploy to Production'
dependsOn: DeployStaging
condition: succeeded('DeployStaging')
jobs:
- deployment: ProdDeploy
environment: Production # <-- Triggers approval gate configured in portal
strategy:
runOnce:
deploy:
steps:
- task: AzureWebApp@1
inputs:
appName: myapp-prod
package: '$(Pipeline.Workspace)/webapp/app.zip'Deploying to Azure Kubernetes Service
Deploy containerised applications to AKS using the KubernetesManifest@0 task. This task applies Kubernetes YAML manifests to the cluster, with built-in support for imagePullSecrets and canary deployments. Connect to the AKS cluster using a Kubernetes service connection configured in Azure DevOps. The task uses kubectl apply under the hood and waits for the rollout to complete before marking the step successful.
# AKS deployment step in Azure Pipelines
- task: KubernetesManifest@0
displayName: 'Deploy to AKS'
inputs:
action: deploy
kubernetesServiceConnection: 'AKS-Production-SC'
namespace: production
manifests: |
k8s/deployment.yaml
k8s/service.yaml
containers: 'mycontainerregistry.azurecr.io/myapp:$(Build.BuildId)'
imagePullSecrets: acr-secretImage Tagging Strategy
Tag container images with the build ID ($(Build.BuildId)) or Git commit SHA ($(Build.SourceVersion)) so you can always trace a running container back to the exact code revision that built it. Avoid using the latest tag in production — Kubernetes caches it and may not pull the new version. Store the specific image tag as a pipeline variable and inject it into Kubernetes manifests at deploy time using envsubst or sed.
# Tag and push image with build ID in CI stage
- script: |
IMAGE='mycontainerregistry.azurecr.io/myapp'
TAG='$(Build.BuildId)'
docker build -t $IMAGE:$TAG -t $IMAGE:latest .
az acr login --name mycontainerregistry
docker push $IMAGE:$TAG
docker push $IMAGE:latest
echo "##vso[task.setvariable variable=imageTag;isOutput=true]$TAG"
name: BuildImage
displayName: 'Build and push container image'Rollback Strategies
Define a rollback strategy for production deployments so you can recover quickly from a bad release. For App Service, rollback means swapping the production slot back to the previous staging version. For AKS, use kubectl rollout undo. Build a dedicated rollback pipeline or add a manual rollback job that can be triggered from the Azure DevOps portal. Document the rollback procedure and practice it regularly — an untested rollback is not a rollback.
# Rollback job triggered manually
- job: Rollback
condition: and(failed(), eq(variables['Build.Reason'], 'Manual'))
steps:
# App Service rollback: swap production back to previous
- task: AzureAppServiceManage@0
inputs:
azureSubscription: 'AzureProductionSC'
action: Swap Slots
webAppName: myUniqueWebApp
resourceGroupName: MyRG
sourceSlot: production # Swap production back to staging version
targetSlot: stagingDeployment Notifications and Monitoring
After each production deployment, automatically run a monitoring check to confirm the new version is healthy. Use the AzureMonitor@1 pipeline check to query Azure Monitor metrics — if error rates are elevated post-deployment, block further pipeline progression and trigger a rollback. Send deployment notifications to Microsoft Teams or Slack via webhook tasks so the team knows when a deployment completes and what version is live.
# Send Teams notification on deployment completion
- task: InvokeRestAPI@1
displayName: 'Notify Teams channel'
inputs:
connectionType: connectedServiceName
serviceConnection: 'TeamsWebhookSC'
method: POST
body: '{
"text": "Deployed **$(Build.BuildId)** to Production. Committed by $(Build.RequestedFor). <br>View: https://myapp.contoso.com"
}'
waitForCompletion: falseCD Best Practices
Follow these continuous deployment best practices: deploy frequently (small batches reduce risk), use feature flags to decouple deployment from release, automate all quality gates before production, practise production-like staging so differences don't mask bugs, monitor deployment windows with automated health checks, and always have a tested rollback plan. A mature CD pipeline makes deployment a non-event rather than a high-stress operation.
Quick Check
Test your understanding of Microsoft Azure Fundamentals (AZ-900) concepts from this lesson.
Lesson Recap
In this lesson you learned: multi-stage YAML pipelines chain Build, Staging, and Production stages with artifact passing, deployment jobs with Environments enable approval gates and deployment tracking, and smoke tests after staging deployment prevent broken releases from reaching production. Next up we explore GitHub Actions on Azure.
Frequently asked questions
Is the “Continuous Deployment to Azure” lesson free?
Yes — the full text of “Continuous Deployment to Azure” is free to read here on the web, and the Cloud & IT Cert Prep course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Cloud & IT Cert Prep course, upgrade to CoddyKit PRO.
What will I learn in “Continuous Deployment to Azure”?
Extend the pipeline with a deployment stage that pushes the build artifact to an App Service slot, runs smoke tests, and swaps to production on approval. You practise Cloud & IT Cert Prep with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.
Do I need any experience to start Cloud & IT Cert Prep?
No prior experience is required. Cloud & IT Cert Prep on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.
How long does the “Continuous Deployment to Azure” lesson take?
Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.
Can I write and run code in this Cloud & IT Cert Prep lesson?
Yes. Every Cloud & IT Cert Prep lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.
All lessons in this course
- Azure DevOps Services Overview
- Building a CI Pipeline with Azure Pipelines
- Continuous Deployment to Azure
- GitHub Actions on Azure