Exercise - Add a Bicep deployment task to the pipeline

Completed

You've created a basic pipeline, and you've configured your Azure and Azure Pipelines environments to connect. Now, you're ready to deploy your website's Bicep file to Azure from your pipeline.

In this exercise, you'll:

  • Add a Bicep file to your repository.
  • Add a pipeline step to deploy your Bicep file.
  • Run your pipeline again and verify that it successfully deployed your website.

Add your website's Bicep file to the Git repository

You've already prepared your website's Bicep file. You can use the Bicep file to deploy different configurations of the website resources, depending on the environment and configuration. Here, you add your Bicep file to your repository.

  1. Open the Visual Studio Code Explorer.

  2. In the deploy folder, create a new file named main.bicep. Make sure you create the file inside the deploy folder, and not at the root of the repository:

    Screenshot of the Visual Studio Code Explorer, with the main dot bicep file highlighted and located in the deploy folder.

  3. Copy the following code into the main.bicep file:

    @description('The Azure region into which the resources should be deployed.')
    param location string = resourceGroup().location
    
    @description('The type of environment. This must be nonprod or prod.')
    @allowed([
      'nonprod'
      'prod'
    ])
    param environmentType string
    
    @description('Indicates whether to deploy the storage account for toy manuals.')
    param deployToyManualsStorageAccount bool
    
    @description('A unique suffix to add to resource names that need to be globally unique.')
    @maxLength(13)
    param resourceNameSuffix string = uniqueString(resourceGroup().id)
    
    var appServiceAppName = 'toy-website-${resourceNameSuffix}'
    var appServicePlanName = 'toy-website-plan'
    var toyManualsStorageAccountName = 'toyweb${resourceNameSuffix}'
    
    // Define the SKUs for each component based on the environment type.
    var environmentConfigurationMap = {
      nonprod: {
        appServicePlan: {
          sku: {
            name: 'F1'
            capacity: 1
          }
        }
        toyManualsStorageAccount: {
          sku: {
            name: 'Standard_LRS'
          }
        }
      }
      prod: {
        appServicePlan: {
          sku: {
            name: 'S1'
            capacity: 2
          }
        }
        toyManualsStorageAccount: {
          sku: {
            name: 'Standard_ZRS'
          }
        }
      }
    }
    
    var toyManualsStorageAccountConnectionString = deployToyManualsStorageAccount ? 'DefaultEndpointsProtocol=https;AccountName=${toyManualsStorageAccount.name};EndpointSuffix=${environment().suffixes.storage};AccountKey=${toyManualsStorageAccount.listKeys().keys[0].value}' : ''
    
    resource appServicePlan 'Microsoft.Web/serverfarms@2022-03-01' = {
      name: appServicePlanName
      location: location
      sku: environmentConfigurationMap[environmentType].appServicePlan.sku
    }
    
    resource appServiceApp 'Microsoft.Web/sites@2022-03-01' = {
      name: appServiceAppName
      location: location
      properties: {
        serverFarmId: appServicePlan.id
        httpsOnly: true
        siteConfig: {
          appSettings: [
            {
              name: 'ToyManualsStorageAccountConnectionString'
              value: toyManualsStorageAccountConnectionString
            }
          ]
        }
      }
    }
    
    resource toyManualsStorageAccount 'Microsoft.Storage/storageAccounts@2022-09-01' = if (deployToyManualsStorageAccount) {
      name: toyManualsStorageAccountName
      location: location
      kind: 'StorageV2'
      sku: environmentConfigurationMap[environmentType].toyManualsStorageAccount.sku
    }
    
  4. Save your changes to the file.

  5. In the Visual Studio Code terminal, run this code to stage the changes, commit the changes, and push the changes to your repository:

    git add deploy/main.bicep
    git commit -m 'Add Bicep file'
    git push
    

Replace the pipeline steps

Next, update your pipeline definition to deploy your Bicep file to Azure by using the service connection.

  1. In Visual Studio Code, open the deploy/azure-pipelines.yml file.

  2. Before the jobs: line, add variables: to define a variable named deploymentDefaultLocation:

    trigger: none
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
    - name: deploymentDefaultLocation
      value: westus3
    
    jobs:
    
  3. To remove the script step from the pipeline definition, delete the bottom two lines of the file.

    Tip

    When you work in Visual Studio Code and have installed the Azure Pipelines extension, try using the Ctrl+Space key combination. It shows a context menu with suggested elements to add at your current cursor position.

  4. At the bottom of the file, add a task that uses the AzureResourceManagerTemplateDeployment task to deploy your Bicep file:

    jobs:
    - job:
      steps:
    
      - task: AzureResourceManagerTemplateDeployment@3
        inputs:
          connectedServiceName: $(ServiceConnectionName)
          deploymentName: $(Build.BuildNumber)
          location: $(deploymentDefaultLocation)
          resourceGroupName: $(ResourceGroupName)
          csmFile: deploy/main.bicep
          overrideParameters: >
            -environmentType $(EnvironmentType)
            -deployToyManualsStorageAccount $(DeployToyManualsStorageAccount)
    

    Note

    It's a good idea to type this code yourself instead of copying and pasting it from this module. Pay attention to the file's indentation. If your indentation isn't correct, your YAML file won't be valid. Visual Studio Code indicates errors by displaying squiggly lines.

    This step uses a system variable, $(Build.BuildNumber), to name the deployment. The variable can help you easily see which pipeline run a deployment corresponds to.

    The location task property is required by the AzureResourceManagerTemplateDeployment task. It specifies the Azure region into which a resource group should be created. In this exercise, you already created a resource group and so the location you specify here doesn't matter. But you need to provide the value anyway. Here, you set it to the value of the deploymentDefaultLocation variable that you set in a previous step.

  5. Save your changes to the file. Your file should look like this example:

    trigger: none
    
    pool:
      vmImage: ubuntu-latest
    
    variables:
    - name: deploymentDefaultLocation
      value: westus3
    
    jobs:
    - job:
      steps:
    
      - task: AzureResourceManagerTemplateDeployment@3
        inputs:
          connectedServiceName: $(ServiceConnectionName)
          deploymentName: $(Build.BuildNumber)
          location: $(deploymentDefaultLocation)
          resourceGroupName: $(ResourceGroupName)
          csmFile: deploy/main.bicep
          overrideParameters: >
            -environmentType $(EnvironmentType)
            -deployToyManualsStorageAccount $(DeployToyManualsStorageAccount)
    
  6. In the Visual Studio Code terminal, stage your changes, commit them to your repository, and push them to Azure Repos:

    git add deploy/azure-pipelines.yml
    git commit -m 'Add deployment task to pipeline'
    git push
    

Add pipeline variables

  1. In your browser, select Pipelines.

    Screenshot of Azure DevOps that shows the menu, with Pipelines highlighted.

  2. Select your pipeline.

    Screenshot of Azure DevOps that shows the pipelines list, with the toy-website pipeline highlighted.

  3. Select Edit.

    Screenshot of Azure DevOps that shows the pipeline, with Edit highlighted.

  4. Select Variables.

    Screenshot of Azure DevOps that shows the pipeline editor, with the Variables button highlighted.

  5. Select New variable.

    Screenshot of Azure DevOps that shows the pipeline variable editor, with the 'New variable' button highlighted.

  6. In Name, enter ServiceConnectionName. In Value, enter ToyWebsite.

    Leave the checkboxes cleared, and select OK.

    Screenshot of Azure DevOps that shows the pipeline variable editor, with the OK button highlighted.

  7. To create more variables, select +.

    Screenshot of Azure DevOps that shows the pipeline variable list, with the plus button highlighted.

    Create the following variables the same way you created the ServiceConnectionName variable:

    Variable name Value
    ResourceGroupName ToyWebsite
    EnvironmentType nonprod
  8. Complete the steps again to create a variable named DeployToyManualsStorageAccount, with a value of true. For this variable, select the Let users override this value when running this pipeline checkbox.

    Screenshot of Azure DevOps that shows the pipeline variable editor.

  9. When you've created all four variables, select Save.

    Screenshot of Azure DevOps that shows the pipeline variable editor, with the Save button highlighted.

Run your pipeline

Now, you're ready to run your pipeline!

Your template includes a storage account, which your website team uses to store instruction manuals for toys. Because you're still testing your environment, you don't need to deploy the storage account every time you deploy the website. So, you created a Bicep parameter to control whether the storage account is deployed. Here, you run the pipeline and override the deployment so that it doesn't deploy the storage account this time.

  1. Select Run.

    Screenshot of Azure DevOps that shows the pipeline, with the Run button highlighted.

    The Run pipeline pane appears. On this pane, you can configure settings for this specific run of the pipeline.

  2. Select Variables.

    Screenshot of Azure DevOps that shows the 'Run pipeline' page, with the Variables menu item highlighted.

  3. Select the DeployToyManualsStorageAccount variable and change its value to false. Then select Update.

    Screenshot of Azure DevOps that shows the 'Run pipeline' variable editor, with the Update button highlighted.

  4. Select the back arrow.

    Screenshot of Azure DevOps that shows the 'Run pipeline' page, with the back arrow highlighted.

  5. To start a new pipeline run, select Run. The pipeline might take a few minutes to start. After the pipeline starts, the deployment might take a few minutes to finish.

  6. To open the job, in the Jobs section select Job. You can monitor the job as it runs, or you can wait until the job completes to review its history.

    Wait for the job to finish.

  7. Select Job.

    Screenshot of Azure DevOps that shows the job page, with the Job menu item highlighted.

  8. Select 1 queue time variable used.

    Screenshot of Azure DevOps that shows the pipeline log, with the '1 queue time variable used' item highlighted.

    The overridden value for this pipeline run is shown. The DeployToyManualsStorageAccount variable's value is false because you overrode the original value.

  9. Inspect the rest of your pipeline output.

    The pipeline shows a successful deployment.

Verify the deployment

  1. Go to the Azure portal.

  2. In the left menu, select Resource groups.

  3. Select ToyWebsite.

  4. In Overview, view the deployment status. You can see that one deployment succeeded.

    Screenshot of the Azure portal that shows the resource group with one successful deployment.

  5. Select 1 Succeeded to see the details of the deployment.

    Screenshot of the Azure portal that shows the resource group deployment history, with the deployment highlighted.

    The deployment name is the same as the name of the pipeline run.

  6. To see what resources were deployed, select the deployment. To expand the deployment to see more details, select Deployment details. In this case, there's an Azure App Service plan and an app.

    Screenshot of the Azure portal that shows the resource group deployment details, with the App Service resources highlighted.