Continuous deployment to Azure from Azure DevOps
Tags: csharp, dotnet, azure, devops
Published: 2019-11-18 08:02:58

---
title: Continuous deployment to Azure from Azure DevOps
published: true
description: Tutorial on setting up continuous deployment from Azure DevOps to an Azure website. The post shows how to utilize DevOps release management.
tags: csharp, dotnet, azure, devops
cover_image: https://blog.elmah.io/content/images/2019/04/continuous-deployment-to-azure-from-azure-devops.png
canonical_url: https://blog.elmah.io/continuous-deployment-to-azure-in-visual-studio-team-service/
---

Hosting on Azure and building on Azure DevOps? You should utilize the (now) wonderful release management tool built into DevOps. I've written about continuous deployment in the past here: [Configure and deploy Azure Functions with Kudu](https://blog.elmah.io/configure-and-deploy-azure-functions-with-kudu/) and [Continuous Deployment of Azure Functions with Slots](https://blog.elmah.io/continuous-deployment-of-azure-functions-with-slots/). Since writing those posts, we have switched entirely to DevOps release management. In this post, I'll show you how to set up the full pipeline, using one of our websites as an example.

![Continuous deployment to Azure from Azure DevOps](https://blog.elmah.io/content/images/2019/04/continuous-deployment-to-azure-from-azure-devops.png)

I assume that you store your source code in some sort of source control system. Whether or not you are using Git or not, it doesn't really matter for this tutorial. We use Git and love it. To tell DevOps to pick up new commits to your repository and build/deploy it, go to DevOps | Build and release | Builds and click the *+ New* button. This will show the creation wizard:

![Select a source](https://blog.elmah.io/content/images/2018/08/vsts-select-a-source.png)

Select your repository using one of the sources in the top and hit *Continue*. Now select a template:

![Select a template](https://blog.elmah.io/content/images/2018/08/vsts-select-a-template.png)

DevOps comes with a great set of default build configurations. For this tutorial, I'll select *ASP.NET*, since the website to build and deploy are built using ASP.NET Web API. Click *Apply*. A build configuration for your project is created:

![Build template](https://blog.elmah.io/content/images/2018/08/vsts-build-template.png)

To make sure that DevOps picks up new commits and builds them, go to the *Triggers* tab and enable the *Enable continuous integration* checkbox:

![Enable continuous integration](https://blog.elmah.io/content/images/2018/08/vsts-enable-continuous-integration.png)

Let's quickly go through each build step. The first step tells DevOps to use a specific version of NuGet. You can click the *Always download the latest matching version* if you'd like:

![NuGet tool installer](https://blog.elmah.io/content/images/2018/08/vsts-nuget-tool-installer.png)

The *NuGet restore* step automatically scans for all solution files and restores NuGet dependencies. We use the internal NuGet server available in DevOps, which is why we tell DevOps to look for packages there as well as on nuget.org:

![Restore NuGet packages](https://blog.elmah.io/content/images/2018/08/vsts-restore-nuget-packages.png)

In the *Build solution* step, DevOps builds all solutions in your repository (you only have one, right?). As part of the build, MSBuild packages the website as a zip file:

![Build solution](https://blog.elmah.io/content/images/2018/08/vsts-build-solution.png)

This step is important for the release management system to work, so remember to add the arguments if they are not already there.

We love writing unit tests, which is why we want to keep the *Test Assemblies* step just as it were. As long as you postfix the name of your test assembly/assemblies with *test*, you should be fine.

The *Publish symbols path* step lets you publish symbols to the built-in symbol server. If you want to debug a release built, you will need this step.

Finally, the *Publish Artifact* step copies the zip file, just built to a folder visible for other parts of DevOps (like release management).

That's it. Clicking *Save & queue*, let's you test to see that everything is working as expected.

Now for the release part. On the recent successful release, click the *Release* button:

![Successful build](https://blog.elmah.io/content/images/2018/08/vsts-successful-build.png)

This will launch the release management template. As I want to release the newly build website to Azure, I select the *Azure App Service deployment* template and click *Apply*. Finally, I name the environment *Staging*, which results in the following pipeline:

![Release pipeline](https://blog.elmah.io/content/images/2018/08/vsts-pipeline.png)

Notice how DevOps automatically picked up the output from the build. In order to tell DevOps where to deploy the code, click the *1 phase, 1 task* link on the Staging environment:

![Deploy to azure](https://blog.elmah.io/content/images/2018/08/vsts-deploy-to-azure.png)

On this screen, you want to configure the Azure Web App to deploy to. In order to be able to show everything on a single screenshot, I've clicked the *Unlink all* link and set up all the choices on the *Deploy Azure App Service* release step:

![Deployment slot](https://blog.elmah.io/content/images/2018/08/vsts-deployment-slot.png)

Notice how I've selected *Deploy to slot* and selected the *staging* slot on my Azure web app. We are using a deployment slot for all of our user-facing websites, in order for us to be able to do a final manual test before deploying to production. If you want to deploy directly to production, you should simply name the environment *Production* and uncheck the *Deploy to slot* checkbox.

After a manual test, I want DevOps to deploy the website to production. To do so, add an additional environment by going back to the pipeline and click the *+ Add* button below the Staging environment. I'm going to select the *Empty process* template since I want to add the next release step manually. Finally, I name the new environment *Production* and the pipeline now looks like this:

![Pipeline with production](https://blog.elmah.io/content/images/2018/08/vsts-pipeline-with-production.png)

The reason I selected *Empty process* over *Azure App Service deployment* is, that I don't want DevOps to deploy the website again. Azure deployment slots already have swapping between staging and production built in. To swap, click the *1 phase, 0 task* link on the Production environment and add the *Azure App Service Manage* task:

![Swap websites](https://blog.elmah.io/content/images/2018/08/vsts-swap-websites.png)

Like previously, I've filled in the nessecary Azure specific variables.

We're almost there. The only thing missing is to implement a gate between deploying to staging and production. With the current setup, all deployments to staging are automatically published to production. Since I want a manual test on staging, I'll add a *Pre-deployment approval* step on deployment to Production. Go back to the pipeline and click the small avatar icon on the left side of the production environment. This show the *Pre-deployment conditions* tab. Enable the *Pre-deployment approvals* toggle and input the user(s) that should be allowed to approve the deployment:

![Pre-deployment approval](https://blog.elmah.io/content/images/2018/08/vsts-pre-deployment-approval.png)

That's it folks! All commits are now automatically built and deployed to staging. After a manual test, you go to Release Management in DevOps and hit the *Approve* button next to the release and the Staging and Production sites on Azure are swapped.

## Would your users appreciate fewer errors?

elmah.io is the easy error logging and uptime monitoring service for .NET. Take back control of your errors with support for all .NET web and logging frameworks.

➡️ [Error Monitoring for .NET Web Applications](https://elmah.io/?utm_source=devto&utm_medium=social&utm_campaign=devtoposts) ⬅️

This article first appeared on the elmah.io blog at https://blog.elmah.io/continuous-deployment-to-azure-in-visual-studio-team-service/