Deploying Azure Infrastructure Resources with Azure Devops – Part 2

In part one we setup a project in Azure Devops, create an Azure repo, added an ARM template to the repo and created a build pipeline.  In this post we’ll create a release pipeline to actually deploy our resources in Azure.

Within Azure Devops open our project and select ‘Releases’ and select ‘New Pipeline’


On the next page choose under select template choose ‘Start with an empty job’


By default the stage is called Stage 1 as per the above screenshot, I’ve renamed mine to Deployment


The point of stages are the different releases to environments you might have such as dev, stage, production.  You can add these stages in and release to each individually.  Understanding this was key to me in understanding why tools such as Azure Devops are so very useful.  In this example I’m going to stick with the one stage though.

I now select Save and accept the default save location when prompted.  I then select ‘Add an artifact’


I select my Source, this is the build pipeline we created in part one. I leave everything else at default and select Add and then hit save.

In the deployment stage I click on 1 job, 0 task



I click + in Agent job and search for and select ‘Azure Resource Group Deployment’

In the Resource Group Deployment Task I set information such as the subscription to deploy to and the resource group.  In part 1 we said we’d deploy to a resource group called RG_Network which was created by the build pipeline for us.


Leave Template Location as Linked Artifact and click the three dots by Template Location to browse to the artifact which was created for us by the build pipeline


Hit Save

In the top right of the page select the down arrow by ‘Release’ and select Create A Release



Leave everything except for ‘Select the version for the artifact sources for this release’  Hit the drop down arrow and select your source artifact.  Click create and our release is created

A message appears saying the release has been created


In my case it was called Release-1 and I can click on that to see the release details.  In my case the deployment happened very quickly as the ARM template is very basic and just deploys a vnet but we can see it said the deployment was successful.


To see if it really was successful I can look in my RG_Network resource group to see if the vnet was created



And it was.  Using Azure Devops I’ve deployed an ARM template which created a vnet in Azure.

Earlier in this post I made a comment about stages and how getting started with Azure Devops has helped me understand why tools like this are so useful.  The deployment stage I deployed to could easily have been called Dev or Test and then I can have another stage called Production.  The key bit here is it’s the same ARM template being deployed in each stage so consistency of what is deployed is guaranteed across the stages.

Obviously there may be necessary changes between environments like test and production, such as IP addressing.  This can be handled with variables in the various stages to override the parameters of the ARM template.  I’ll cover those and some other features in future blog post.  Obviously what has been done here is fairly simple, just a single ARM template deploying one vnet.  As I learn more about using Azure Devops I’ll write it up 🙂


Deploying Azure Infrastructure Resources with Azure Devops – Part 1

I’ve recently had the opportunity to start playing with Azure Devops and as I’m historically and primarily an infrastructure guy I wondered how Azure Devops can help me with such things as Infrastructure as Code.

What I’ll show in this post is how to deploy ARM infrastructure resources such as VMs and vnets using ARM templates and Azure Devops.  I’m not going to go into how you can purchase Azure Devops, there are many ways to gain access to it

so I’m going to dive straight into how I deploy ARM templates with Azure Devops.

First an overview of what I’m going to be using:

Azure Devops (obviously)

Azure Repos (Azure repos are a git repo)

Build Pipeline

Release Pipeline

And my aim here is to deploy an Azure virtual network using Azure Devops

Your Devops URL is

Step 1 – Create a Project

When first going to Azure Devops this is the page I’m greeted with:


I create a project called ‘Azure Infrastructrure’ and leave the visibility set as Private.  When the projected is created I’m shown a ‘Welcome to the project’ screen


Down the left hand side you can see items such as Boards, Repos, Pipeleines, test Plans and Artifacts.  I’ll only be dealing with Repos, and Pipelines.

Firstly I choose Repos and I choose ‘or initialze with a Readme’ to create a new repo and click intiialize.  Note you also have options to clone the repo to your computer or push an existing repo.  For simplicity I’ll just be initializing a new repo.


An empty repo is created:


I’m going to create a new folder called ARM-Vnet by selecting New – Folder.  Note that you cannot create an empty directory so you have to create a placeholder file when you create the directory:


I’m also going to create a folder called ARM-VMs


I upload some existing ARM templates that I have for creating a vnet and virtual machines into the relevant folders.


Build Pipeline

The next step is to create a build pipeline.  You can read more about pipelines here

Select Pipelines – Build – New Pipeline

In the new pipeline window select ‘Use the visual designer to create a pipeline without Yaml’  It doesn’t look like a selectable item but ‘Use the visual designer’ section is.


Select your source repository.  As mentioned earlier I’m using Azure Repos


Select Continue

On the select template page choose ‘Start with an empty job’ and the build pipeline is created and immediately opens up for you to start customising the pipeline.  Note that by default it names the pipeline after your project and appends -CI to it.


Click on the + sign in Agent job 1.

Search for azure

Select Azure Resource Group Deployment and click Add to add Azure Resource Group Deployment to the agent job


Fillout the following details in the task:

Change the name of the deployment if you wish

Select the Azure subscription.  A note on selecting the Azure subscription, in my example my account is in the same Azure AD Tenant as where I’m going to target the deployment of my resources, so I can select authorize.  If this is not the case you need to create service connection between Azure Devops and the Azure AD Tenant to enable the deployment of resources from Azure Devops.  More on this at


Action – Create or Update Resource Group

Select an existing resource group or set a name for a new resource group

Set the location

Browse and select the to ARM template located in our repo

Browse and select the ARM template parameters if required

Deployment Mode – set to Validation Only



Click + on the agent job again and add a ‘Copy Files’ task.  Give the task a name and set the options as follows:

Set the source folder to the folder holding the relevant ARM template.  In my case this is my ARM-Vnet folder, under which is the ARM template for my virtual network.


Click + on Agent job 1 to add a new task and choose ‘Publish Build Artifact’

All the options can be left at their defaults for this task


Save the pipeline by clicking the arrow next to ‘Save and Queue’ and select Save.  We have now finished our build pipeline.  What does this do exactly?  It runs a validation against our ARM template, which is equivalent to Test-AzureRMResourceGroupDeployment cmdlet or the Azure CLI az group deployment validate command.  It checks that our template is syntactically correct and then copies it to the agent build directory (a directory on a VM essentially that is used to run the pipeline is my understanding) and then publishes that template as an artifact.

When defining the Azure Resource Group Deployment I specified a resource group called RG_Network, if we look at my current resource groups in my subscription we’ll see that no such resource group exists yet:


In the build pipeline if I now select ‘Queue’



Leave all the options and click Queue.  A message near the top of the page reports that the request has been queued and shows you the build number.  You can click that message to see the Build


Once the build has completed successfully the resource group RG_Network has been created in my Azure subscription but there are not resources in the resource group.


The resources will be deployed via our release pipeline in part 2.




VM Deployment with ARM Template

This ARM template will deploy x number of virtual machines (takes the number you need as a parameter), a storage account in the target resource group for boot diagnostics, deploys the VMs in an availability group and deploys x number of data disks per VM.  Both the number of data disks (per VM) and size are parameters.  It attaches the VMs to an existing vnet/subnet, both of which are parameters.  it also sets the Locale to UK on Windows servers using a custom script extension as per

Template over on my Github page

This template will be updated over time to include additional functionality.

OMS Deployment with ARM Template

An ARM template to deploy a basic OMS workspace in Azure.  It deploys a workspace and two OMS solutions: Anti-Malware assessment and Updates.

Another template for OMS deployment, which is identical to the above, but links the workspace to an existing automation account.  Note it does not create the automation account, the automation account must already exist.

These templates are over on my Github page