Integrate Resource Manager templates with Azure Pipelines

Visual Studio provides the Azure Resource Group project for creating templates and deploying them to your Azure subscription. You can integrate this project with Azure Pipelines for continuous integration and continuous deployment (CI/CD).

There are two ways to deploy templates with Azure Pipelines:

  • Add task that runs an Azure PowerShell script. This option has the advantage of providing consistency throughout the development life cycle because you use the same script that is included in the Visual Studio project (Deploy-AzureResourceGroup.ps1). The script stages artifacts from your project to a storage account that Resource Manager can access. Artifacts are items in your project such as linked templates, scripts, and application binaries. Then, the script deploys the template.

  • Add tasks to copy and deploy tasks. This option offers a convenient alternative to the project script. You configure two tasks in the pipeline. One task stages the artifacts and the other task deploys the template.

This article shows both approaches.

Prepare your project

This article assumes your Visual Studio project and Azure DevOps organization are ready for creating the pipeline. The following steps show how to make sure you're ready:

Create pipeline

  1. If you haven't added a pipeline previously, you need to create a new pipeline. From your Azure DevOps organization, select Pipelines and New pipeline.

    Add new pipeline

  2. Specify where your code is stored. The following image shows selecting Azure Repos Git.

    Select code source

  3. From that source, select the repository that has the code for your project.

    Select repository

  4. Select the type of pipeline to create. You can select Starter pipeline.

    Select pipeline

You're ready to either add an Azure PowerShell task or the copy file and deploy tasks.

Azure PowerShell task

This section shows how to configure continuous deployment by using a single task that runs the PowerShell script in your project. The following YAML file creates an Azure PowerShell task:

pool:
  name: Hosted Windows 2019 with VS2019
  demands: azureps

steps:
- task: AzurePowerShell@3
  inputs:
    azureSubscription: 'demo-deploy-sp'
    ScriptPath: 'AzureResourceGroupDemo/Deploy-AzureResourceGroup.ps1'
    ScriptArguments: -ResourceGroupName 'demogroup' -ResourceGroupLocation 'centralus' 
    azurePowerShellVersion: LatestVersion

When you set the task to AzurePowerShell@3, the pipeline uses commands from the AzureRM module to authenticate the connection. By default, the PowerShell script in the Visual Studio project uses the AzureRM module. If you've updated your script to use the Az module, set the task to AzurePowerShell@4.

steps:
- task: AzurePowerShell@4

For azureSubscription, provide the name of the service connection you created.

inputs:
    azureSubscription: '<your-connection-name>'

For scriptPath, provide the relative path from the pipeline file to your script. You can look in your repository to see the path.

ScriptPath: '<your-relative-path>/<script-file-name>.ps1'

If you don't need to stage artifacts, just pass the name and location of a resource group to use for deployment. The Visual Studio script creates the resource group if it doesn't already exist.

ScriptArguments: -ResourceGroupName '<resource-group-name>' -ResourceGroupLocation '<location>'

If you need to stage artifacts to an existing storage account, use:

ScriptArguments: -ResourceGroupName '<resource-group-name>' -ResourceGroupLocation '<location>' -UploadArtifacts -ArtifactStagingDirectory '$(Build.StagingDirectory)' -StorageAccountName '<your-storage-account>'

Now, that you understand how to create the task, let's go through the steps to edit the pipeline.

  1. Open your pipeline, and replace the contents with your YAML:

    pool:
      name: Hosted Windows 2019 with VS2019
      demands: azureps
    
    steps:
    - task: AzurePowerShell@3
      inputs:
        azureSubscription: 'demo-deploy-sp'
        ScriptPath: 'AzureResourceGroupDemo/Deploy-AzureResourceGroup.ps1'
        ScriptArguments: -ResourceGroupName 'demogroup' -ResourceGroupLocation 'centralus' -UploadArtifacts -ArtifactStagingDirectory '$(Build.StagingDirectory)' -StorageAccountName 'stage3a4176e058d34bb88cc'
        azurePowerShellVersion: LatestVersion
    
  2. Select Save.

    Save pipeline

  3. Provide a message for the commit, and commit directly to master.

  4. When you select Save, the build pipeline is automatically run. Go back to the summary for your build pipeline, and watch the status.

    View results

You can select the currently running pipeline to see details about the tasks. When it finishes, you see the results for each step.

Copy and deploy tasks

This section shows how to configure continuous deployment by using a two tasks to stage the artifacts and deploy the template.

The following YAML shows the Azure file copy task:

- task: AzureFileCopy@3
  displayName: 'Stage files'
  inputs:
    SourcePath: 'AzureResourceGroup1'
    azureSubscription: 'demo-deploy-sp'
    Destination: 'AzureBlob'
    storage: 'stage3a4176e058d34bb88cc'
    ContainerName: 'democontainer'
    outputStorageUri: 'artifactsLocation'
    outputStorageContainerSasToken: 'artifactsLocationSasToken'
    sasTokenTimeOutInMinutes: '240'

There are several parts of this task to revise for your environment. The SourcePath indicates the location of the artifacts relative to the pipeline file. In this example, the files exist in a folder named AzureResourceGroup1 which was the name of the project.

SourcePath: '<path-to-artifacts>'

For azureSubscription, provide the name of the service connection you created.

azureSubscription: '<your-connection-name>'

For storage and container name, provide the names of the storage account and container you want to use for storing the artifacts. The storage account must exist.

storage: '<your-storage-account-name>'
ContainerName: '<container-name>'

The following YAML shows the Azure resource group deployment task:

- task: AzureResourceGroupDeployment@2
  displayName: 'Deploy template'
  inputs:
    azureSubscription: 'demo-deploy-sp'
    resourceGroupName: 'demogroup'
    location: 'centralus'
    templateLocation: 'URL of the file'
    csmFileLink: '$(artifactsLocation)WebSite.json$(artifactsLocationSasToken)'
    csmParametersFileLink: '$(artifactsLocation)WebSite.parameters.json$(artifactsLocationSasToken)'
    overrideParameters: '-_artifactsLocation $(artifactsLocation) -_artifactsLocationSasToken "$(artifactsLocationSasToken)"'

There are several parts of this task to revise for your environment. For azureSubscription, provide the name of the service connection you created.

azureSubscription: '<your-connection-name>'

For resourceGroupName and location, provide the name and location of the resource group you want to deploy to. The task creates the resource group if it doesn't exist.

resourceGroupName: '<resource-group-name>'
location: '<location>'

The deployment task links to a template named WebSite.json and a parameters file named WebSite.parameters.json. Use the names of your template and parameter files.

Now, that you understand how to create the tasks, let's go through the steps to edit the pipeline.

  1. Open your pipeline, and replace the contents with your YAML:

    pool:
      name: Hosted Windows 2019 with VS2019
    
    steps:
    - task: AzureFileCopy@3
      displayName: 'Stage files'
      inputs:
        SourcePath: 'AzureResourceGroup1'
        azureSubscription: 'demo-deploy-sp'
        Destination: 'AzureBlob'
        storage: 'stage3a4176e058d34bb88cc'
        ContainerName: 'democontainer'
        outputStorageUri: 'artifactsLocation'
        outputStorageContainerSasToken: 'artifactsLocationSasToken'
        sasTokenTimeOutInMinutes: '240'
    - task: AzureResourceGroupDeployment@2
      displayName: 'Deploy template'
      inputs:
        azureSubscription: 'demo-deploy-sp'
        resourceGroupName: demogroup
        location: 'centralus'
        templateLocation: 'URL of the file'
        csmFileLink: '$(artifactsLocation)WebSite.json$(artifactsLocationSasToken)'
        csmParametersFileLink: '$(artifactsLocation)WebSite.parameters.json$(artifactsLocationSasToken)'
        overrideParameters: '-_artifactsLocation $(artifactsLocation) -_artifactsLocationSasToken "$(artifactsLocationSasToken)"'
    
  2. Select Save.

  3. Provide a message for the commit, and commit directly to master.

  4. When you select Save, the build pipeline is automatically run. Go back to the summary for your build pipeline, and watch the status.

    View results

You can select the currently running pipeline to see details about the tasks. When it finishes, you see the results for each step.

Next steps

For step-by-step process on using Azure Pipelines with Resource Manager templates, see Tutorial: Continuous integration of Azure Resource Manager templates with Azure Pipelines.