Release apps with Azure Pipelines
Learn to release apps with Azure Pipelines in this hands-on Azure tutorial. Master pipelines for continuous delivery, automate releases, troubleshoot common issues, and discover what to study next.
Focus: release apps with azure pipelines
You've built a solid CI pipeline that compiles code and runs tests on every push — but your users are still waiting weeks for a manual deployment. The gap between a green build and a live update is where releases stall, and teams resort to copy-pasting artifacts and praying they remembered every environment variable. In this lesson, you'll close that gap by using Azure Pipelines to release apps automatically — turning a finished build into a production deployment with repeatable, auditable steps.
The problem this lesson solves
Manual releases are slow, error-prone, and opaque. A single forgotten configuration value or a slightly different runtime environment can turn a 'known good' build into an outage. When you release apps with Azure Pipelines, you replace those copy-paste rituals with a defined, automated process that runs the same way every time.
The pain is real: 60% of deployment failures trace back to manual steps or environment drift. Every time a human is in the loop, you introduce risk — typos, skipped steps, or 'it works on my machine' assumptions. Azure Pipelines gives you a release pipeline that deploys your artifact to any target — virtual machines, containers, Kubernetes, or app services — with gates, approvals, and rollback strategies built in.
By the end of this lesson, you'll be able to automate a release from a build artifact to a live environment, and you'll know exactly when to use a multi-stage YAML pipeline versus a classic release definition.
Core concept / mental model
Think of a release pipeline as a conveyor belt that carries your build artifact from the packaging station (CI) to the loading dock (production). Each stage — Dev, Test, Staging, Prod — is a stop on that belt where you inspect, approve, and sign off before the artifact moves on.
Azure Pipelines offers two complementary models:
- Classic release pipelines: A visual designer where you define stages, approvals, and gates in the Azure DevOps UI. Great for quick setups or when you want to avoid YAML.
- Multi-stage YAML pipelines: The same YAML file that defines your build and release, enabling pipeline-as-code. Everything lives in your repo, versioned and reviewable.
Pro tip: Think of the 'release' as everything that happens after the build artifact is ready. CI answers 'does it compile and pass tests?' Release answers 'is it safe to put in front of users?' — a different question with different answers.
Key vocabulary:
- Artifact: The packaged output of your build (e.g., a
.zip, a Docker image, a.jar). This is the thing your release pipeline consumes. - Stage: A logical environment in your release (Dev, QA, Prod). Stages run sequentially by default and can have approvals.
- Approval: A manual check before a stage runs — a human gate that says 'yes, deploy here.'
- Gate: An automated check that polls a service (e.g., a monitoring endpoint) before allowing the release to continue.
How it works step by step
- Build completes and publishes an artifact — your CI pipeline produces a package and uploads it as a pipeline artifact.
- Release pipeline triggers — automatically when a new build artifact is available, or manually.
- Stages execute in order — Dev deploys, runs smoke tests; if that passes, Test deploys with automated integration tests; then Staging and Prod follow.
- Approvals gate the production stage — a human (or automated gate) reviews the test results and gives the green light.
- Deployment happens — the pipeline runs your deployment scripts or uses a built-in task (like
AzureWebApporKubernetesManifest) to push the artifact. - Post-deployment validation — health checks or monitoring confirm the app is live and healthy.
Each step is a cause → effect chain: a failed test in stage 2 stops the belt, so bad code never reaches production. This is the power of continuous delivery (CD) — you're always one approval away from shipping.
Hands-on walkthrough
Let's build a release pipeline from scratch. We'll use a multi-stage YAML pipeline because it's versionable and the modern default. The example deploys a simple web app to an Azure App Service, but the pattern applies to any target.
1. Structure your repository
Assume your azure-pipelines.yml contains a CI stage that builds and publishes an artifact. Here's a minimal CI setup that produces a deployable zip:
# azure-pipelines.yml (root)
trigger:
branches:
include:
- main
stages:
- stage: Build
jobs:
- job: BuildJob
pool:
vmImage: 'ubuntu-latest'
steps:
- script: |
echo "Building the app..."
# Your actual build commands here
mkdir -p output
echo 'Hello from release!' > output/index.html
displayName: 'Build and package'
- publish: output
artifact: webapp
2. Add release stages
Extend that same file with a deployment job that pushes the artifact to a pre-configured App Service. The deployment keyword creates an environment where approvals and gates live.
stages:
- stage: Build
jobs:
- job: BuildJob
steps:
# ... build steps from above ...
- stage: DeployToDev
dependsOn: Build
jobs:
- deployment: DeployWebApp
environment: 'dev'
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: webapp
- task: AzureWebApp@1
inputs:
azureSubscription: '<your-service-connection>'
appName: 'myapp-dev'
package: '$(Pipeline.Workspace)/webapp/**/*.zip'
Add a production stage with an approval. To require a human gate, navigate to Pipelines → Environments → prod → Approvals and checks, and add an approval. The YAML references that environment:
- stage: DeployToProd
dependsOn: DeployToDev
jobs:
- deployment: DeployWebAppToProd
environment: 'prod'
strategy:
runOnce:
deploy:
steps:
- download: current
artifact: webapp
- task: AzureWebApp@1
inputs:
azureSubscription: '<your-service-connection>'
appName: 'myapp-prod'
package: '$(Pipeline.Workspace)/webapp/**/*.zip'
When you push this file, the pipeline runs the Build stage, deploys to Dev automatically, then pauses at Prod until you approve it. That's release apps with Azure Pipelines in action.
Expected output in the Azure DevOps UI: the Build stage shows green, DeployToDev runs and completes, then DeployToProd shows 'Waiting for approval'. Approve it, and the prod deployment executes.
3. Classic release pipeline (alternative)
If you prefer point-and-click, create a Release Pipeline in the Releases tab. Add an artifact source (your build pipeline), define stages (Dev, Prod), and add deployment tasks like Azure App Service deploy. The workflow is identical, just managed through the UI instead of YAML.
Compare options / when to choose what
| Option | Best for | Pros | Cons |
|---|---|---|---|
| Multi-stage YAML | Teams that treat CI/CD as code | Versionable, reviewable, reuses build YAML, natively tracks environments | Requires YAML knowledge; approvals are configured in the UI (not fully in YAML) |
| Classic release pipeline | Quick setups, non-developers | Visual drag-and-drop, familiar UI, approvals are part of the definition | Harder to version, drift between environments, separate from build YAML |
| Azure DevOps Starter / built-in templates | Simple apps or demos | Fastest setup | Limited customization, not suitable for complex release logic |
When to choose what: Start with multi-stage YAML for any real project. It forces you to define releases as code, which pays off in auditability and reproducibility. Use classic only when you need a one-off or your team isn't comfortable with YAML yet.
Troubleshooting & edge cases
- "No agent found" for deployment jobs: Your self-hosted agent may lack required software (e.g., Docker, .NET). Ensure the agent pool has the necessary runtimes for your deployment tasks.
- Approval never completes: Approvals are assigned to specific users or groups. If the approver doesn't have permissions on the environment, the pipeline waits forever. Check the environment security settings.
- Artifact not found: The
download: currentstep fails if the artifact name doesn't match. Verify thepublishname in the build stage. - AzureWebApp task fails with 'Package not found': Your
packagepath is wrong. Use$(Pipeline.Workspace)/**!(*.zip)or the exact zip name—test the path in a debug step. - Multiple apps, one service connection: Four different App Services each need a separate
appName; don't reuse one stage for all. - YAML stages running in parallel: If you forgot
dependsOn, stages may run concurrently. Set explicitdependsOnto keep the order. - Security: Your service connection credentials are stored in Azure DevOps — don't hardcode passwords; use variables and secret variable groups.
What you learned & what's next
You now understand how to release apps with Azure Pipelines: from creating a multi-stage pipeline, to deploying an artifact to Dev and Production with approvals, to troubleshooting common failures. You've met both learning objectives — you can explain the core idea (automated, gated deployments from build artifacts) and complete a practical exercise (the YAML walkthrough above).
Next in the Azure tutorial path, you'll explore how to monitor and observe those deployed apps—turning telemetry into proactive alerts, so you're not just releasing fast but also confidently. Keep your pipeline green, and the next lesson will keep it healthy.
Practice recap
Extend the example pipeline: add a Test stage that runs a simple integration test (e.g., curl the dev web app) before deploying to production. Then configure an approval on the prod environment and run the pipeline. Observe the behavior when the test fails — does the release stop?
Common mistakes
- Forgetting to publish the build artifact — the release pipeline has nothing to download, and the deployment fails with 'artifact not found'.
- Skipping the
dependsOnin YAML stages — stages run in parallel, so production can deploy before dev finishes. - Hardcoding secrets in the pipeline YAML — use secret variables or Azure Key Vault instead.
- Approvals configured on the wrong environment — the pipeline waits forever if the approver isn't in the security group.
Variations
- Use a classic Release Pipeline in the Azure DevOps UI for a no-YAML approach.
- Deploy to Kubernetes using the
KubernetesManifesttask instead of App Service. - Add automated gates (e.g., monitoring query) before the production stage instead of a manual approval.
Real-world use cases
- Automate deployment of a web app to Azure App Service with separate Dev/Prod slots.
- Roll out a containerized microservice to Azure Kubernetes Service using a multi-stage YAML pipeline.
- Manage compliance by requiring manual approval before every production release for regulated industries.
Key takeaways
- A release pipeline consumes build artifacts and deploys them through stages.
- Multi-stage YAML is the modern, versionable approach; classic releases are the visual alternative.
- Approvals and gates protect production environments from unverified changes.
- Always publish an artifact in CI so the release can download it.
- Set
dependsOnexplicitly to control stage order and avoid parallel mistakes. - Use service connections and secret variables to keep credentials safe.
Keep learning
Related tutorials, quizzes, and articles for this topic.
Discussion
Questions, corrections, and tips help everyone reading this page.
0 comments
Add a comment
No comments yet — start the thread.