Continuous Integration and Deployment of a Web application from Visual Studio Team Services to a Azure VM

Posted by: Subodh Sohoni , on 4/14/2016, in Category VSTS & TFS (Azure DevOps)
Views: 25283
Abstract: Overview of a basic scenario for continuous integration, continuous deployment of web apps in Azure VM, which is part of the DevOps

Microsoft is taking long strides in the field of cloud computing via the Azure platform. Azure is ably supported with Visual Studio Team Services (aka. Team Services or VSTS) for software development. Many organizations are now considering to move their applications to Azure, and their software development services to Team Services. Today, I am starting a series of articles about Continuous Integration Continuous Deployment from Visual Studio Team Services to Azure. It will address various scenarios for various application types and targets. The first one amongst them is focused on the scenario of a web application to be deployed on virtual machine in Azure. It can be extended to deployment on multiple environments like Testing, Staging and Production where the application has to be deployed.


In this scenario, we have kept the application code in version control of Team Services. We will develop this scenario as follows:

1. We will create a build definition for the application

2. We will assume that the application already exists on the target VM. It was created when it was deployed for the first time, may be manually. Now we need to update it time to time as the development progresses. Usually this is a manual process. As a manual process, required files are deployed by XCOPY operation from the location where build has dropped it or from developer's machine (if server build is not present) to the VM where application is being hosted.

3. For our example, we will consider only one environment containing one VM. This case can be extended for more environments and more VMs in each environment.

4. The VMs are created in the Resource Group using Resource Manager in Azure.

5. We will set triggers for Continuous Integration and Continuous Deployment at the end.

6. We will use alternate credentials of the account on Team Services. For guidance related to how to set the alternate credentials read this article.

Build the Web Application on VSTS

To begin with, let us create a build definition and set the output to be in the single package of .zip file. To do so, click the Build node on the Team Services and then the + icon at the top of the left pane. This will open a wizard to create a new build definition. Select the Visual Studio template.


Figure 1: Create Build Definition for Web Application

Now click on the Next button and then select the branch and the folder that contains the web application solution. Here we find the option to target either the source under TFVC or Git or surprisingly, Subversion! We have the option to select Continuous Integration at this moment but we will do that at the end when build and release succeed manually. Keep the selected option of Hosted for the default agent queue. Click the Create button to create the build definition.


Figure 2: Build Step – Visual Studio Build

In the Publish Build Artifacts step, we will create a build artifact named ‘Publish’ which will contain the compiled web application.


Figure 3: Build Step – Publish build artifacts

Save the step and the build definition. You may execute the build but it will not create accessible output. It will create the artifacts on the Hosted agent which we cannot access directly, but we can see that under the Artifacts Explorer of the build results.


Figure 4: Publish artifact details


Prerequisites for Release

Now we are ready to configure the release. For this release to work and the application to get deployed, there are few prerequisites.

1. VMs should have PowerShell Remoting enabled – Since we have created the VMs using Resource Manager under a Resource Group, this prerequisite is already fulfilled.

2. Azure Subscription should be created as mentioned below.

We have to create an End Point in VSTS to connect to Azure. To do so, select the team project under VSTS and open the settings for that. Select Services tab. Then add a new Service End Point. We will have to provide certain Azure account information. When we click the OK button after providing that information, the Azure Service Endpoint will be created which will be visible in the Services tab of Team Services.


Figure 5: Creating the Azure Service Endpoint

For getting the required information, run the following PowerShell script which is available at

    [Parameter(Mandatory=$true, HelpMessage="Enter Azure Subscription name. You need to be Subscription Admin to execute the script")]
    [string] $subscriptionName,

    [Parameter(Mandatory=$true, HelpMessage="Provide a password for SPN application that you would create")]
    [string] $password,

    [Parameter(Mandatory=$false, HelpMessage="Provide a SPN role assignment")]
    [string] $spnRole = "owner"

$ErrorActionPreference = "Stop"
$VerbosePreference = "SilentlyContinue"
$userName = $env:USERNAME
$newguid = [guid]::NewGuid()
$displayName = [String]::Format("VSO.{0}.{1}", $userName, $newguid)
$homePage = "http://" + $displayName
$identifierUri = $homePage

#Initialize subscription
$isAzureModulePresent = Get-Module -Name AzureRM* -ListAvailable
if ([String]::IsNullOrEmpty($isAzureModulePresent) -eq $true)
    Write-Output "Script requires AzureRM modules to be present. Obtain AzureRM from Please refer for recommended AzureRM versions." -Verbose

Import-Module -Name AzureRM.Profile
Write-Output "Provide your credentials to access Azure subscription $subscriptionName" -Verbose
Login-AzureRmAccount -SubscriptionName $subscriptionName
$azureSubscription = Get-AzureRmSubscription -SubscriptionName $subscriptionName
$connectionName = $azureSubscription.SubscriptionName
$tenantId = $azureSubscription.TenantId
$id = $azureSubscription.SubscriptionId

#Create a new AD Application
Write-Output "Creating a new Application in AAD (App URI - $identifierUri)" -Verbose
$azureAdApplication = New-AzureRmADApplication -DisplayName $displayName -HomePage $homePage -IdentifierUris $identifierUri -Password $password -Verbose
$appId = $azureAdApplication.ApplicationId
Write-Output "Azure AAD Application creation completed successfully (Application Id: $appId)" -Verbose

#Create new SPN
Write-Output "Creating a new SPN" -Verbose
$spn = New-AzureRmADServicePrincipal -ApplicationId $appId
$spnName = $spn.ServicePrincipalName
Write-Output "SPN creation completed successfully (SPN Name: $spnName)" -Verbose

#Assign role to SPN
Write-Output "Waiting for SPN creation to reflect in Directory before Role assignment"
sleep 20
Write-Output "Assigning role ($spnRole) to SPN App ($appId)" -Verbose
New-AzureRmRoleAssignment -RoleDefinitionName $spnRole -ServicePrincipalName $appId
Write-Output "SPN role assignment completed successfully" -Verbose

#Print the values
Write-Output "`nCopy and Paste below values for Service Connection" -Verbose
Write-Output "***************************************************************************"
Write-Output "Connection Name: $connectionName(SPN)"
Write-Output "Subscription Id: $id"
Write-Output "Subscription Name: $connectionName"
Write-Output "Service Principal Id: $appId"
Write-Output "Service Principal key: <Password that you typed in>"
Write-Output "Tenant Id: $tenantId"
Write-Output "***************************************************************************"

Create Release Definition

Now we will create a new Release Definition. Open the Release tab on VSTS and click the + icon to create a new release definition. Select Empty deployment template.

As a first step, we will link the build definition that we have already created to release definition.


Figure 6: Link build to the release definition

Now we will add tasks one by one. The first task is to link the Resource Group to this release. For that, the task template to be used is “Azure Resource Group Deployment”.

Select the Azure RM Subscription which is represented by the name of the Azure Service Endpoint that we have created earlier.

The action of this task is to Select Resource Group

From drop down, select the resource group.

Enter same name in the Output Resource Group name.

One more thing to ensure is that we have clicked the checkbox of “Enable Deployment Prerequisites”.


Figure 7: Release Task – Azure Deployment: Select Resource Group

Next task to add is “Azure File Copy”. See Figure 8.

For the source, select the output of the build that we have linked. We can drill down to the folder that we want to be copied, specifically the web application folder. Let’s explore the fields one by one.

Azure Connection Type – Select Azure Resource Manager

Azure RM Subscription – Select the name of the Azure Service Endpoint

Destination type – Azure VMs

Azure Storage Account – The storage account linked to the selected Resource Group

Resource Group – The selected Resource Group

Admin Login and Password – We can directly enter the credentials of administrator of VM or create variables, set them as secret by clicking on the lock and then use those variables here.


Figure 8: Release Task: Azure File Copy

Destination folder – Wherever you want the files to be copied. I have put it as C:\inetpub\wwwroot. (This path is for example only, you can provide your own path where you want the artifacts to be copied).

So far the tasks have achieved a connection to Resource Group, and then copied the web application to the target VM. Save the Release Definition with a name as appropriate.

We are now ready to create a release for one environment. The operations of build, release creation and deployment are set to be triggered manually. We have to set the triggers at various places so that there is an automated pipeline of tasks that gets executed from Check-in – Build – Publish – Release – Deploy – Update the Web Application on the VM.

I suggest that we execute the entire set of tasks manually once to remove any lurking bugs and then set the triggers for automation.

Set Triggers for CICD

Now we will set the triggers for Continuous Integration – Every check-in triggers a build, Continuous Deployment – Every successful build creates a release and triggers deployment of that.

First we will open the Build definition that we had created earlier. Select the Triggers tab. On that tab, check the checkbox for Continuous integration (CI) which ensures that a build of this type will be triggered for every check-in that happens in the scope of that project.continuous-integration-trigger

Figure 9: Continuous Integration Trigger

Next step is to set the trigger in such way that as soon as the build is over, a release is created and then the deployment happens. To set these triggers, open the release definition that we had created. Select the Triggers tab here too. First select the Release Trigger to be Continuous Deployment which creates a new release as soon as the build of the linked build definition is over. Other options available are Manual or Scheduled Triggers. For the dropdown of Artifacts Source, select the build definition that was linked.


Figure 10: Continuous Deployment Triggers - Release

Next set the Environment trigger. Select the trigger of Automated: after release creation. This ensures that as soon as the new release is created, the deployment actions will start. Options available are for Non-automated deployment or deployment after successful deployment on another environment.


Figure 11: Continuous Deployment Triggers - Deployment

In this way, we have created triggers for Continuous Integration and Continuous Deployment. As soon as a developer checks-in the code for updating the web application, the build will be triggered. As soon as the build is successful, the release will be created and then the deployment will take place automatically.


In this article we have walked through a basic scenario for continuous integration, continuous deployment which is part of the DevOps. In the next articles of this series we will check some more complex scenarios like multiple environment, multiple computers in environments and complex tasks.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+


Subodh is a Trainer and consultant on Azure DevOps and Scrum. He has an experience of over 33 years in team management, training, consulting, sales, production, software development and deployment. He is an engineer from Pune University and has done his post-graduation from IIT, Madras. He is a Microsoft Most Valuable Professional (MVP) - Developer Technologies (Azure DevOps), Microsoft Certified Trainer (MCT), Microsoft Certified Azure DevOps Engineer Expert, Professional Scrum Developer and Professional Scrum Master (II). He has conducted more than 300 corporate trainings on Microsoft technologies in India, USA, Malaysia, Australia, New Zealand, Singapore, UAE, Philippines and Sri Lanka. He has also completed over 50 consulting assignments - some of which included entire Azure DevOps implementation for the organizations.

He has authored more than 85 tutorials on Azure DevOps, Scrum, TFS and VS ALM which are published on is a regular speaker at Microsoft events including Partner Leadership Conclave.You can connect with him on LinkedIn .

Page copy protected against web site content infringement 	by Copyscape

Feedback - Leave us some adulation, criticism and everything in between!