After the series of blog posts about Terraform and Azure DevOps, lets dive into Bicep and build a pipeline.
In this blog I shall highlight information about Bicep deployment modes, (Bicep) Linter, what-if operations with preflight validation and good practices.
Also I will refer to mainly Microsoft documentation. I find that the Microsoft documentation and learn sites are great and contain the information needed to learn. So, going into too much detail explaining what is already documented would be a waste of time 😉
In a previous post regarding IaC tool selection, Bicep is also mentioned:IaC Tool selection, where to start? – Cloudfive
New to Bicep? Watch this video:
Table of Contents
Bicep deployment modes
This is the default mode used by Azure Resource Manager. In this mode Resource Manager won’t delete anything. Bicep builds based on a template. With existing resources not specified in the template, these existing resources are left alone. Resources specified in the template are added if they don’t exist. Existing resources are updated based on the configuration in the template.
To run in complete mode, you must explicitly ask the deployment to run in this mode. Using this mode, Azure Resource Manager deletes resources that exist in the Resource Group but are not specified in the Bicep template.
Azure CLI example for setting deployment mode parameter:
az deployment group create \ --mode Complete \ --name ExampleDeployment \ --resource-group ExampleResourceGroup \ --template-file storage.json
Complete mode is only available when deploying to a resource group. So, it is not available when deploying to a subscription, management group, or a tenant.
Example what-if output with “Complete” deployment mode:
What is a Linter?
A linter is a tool to help you improve your code. Linters can provide information to speed up debugging.
‘The Bicep linter checks Bicep files for syntax errors and best practice violations. The linter helps enforce coding standards by providing guidance during development. You can customize the best practices to use for checking the file.’
What is preflight validation?
A check for succesful deployment to Azure environment. Additional checks include:
- Valid naming context for your Bicep resources valid;
- Names already taken for Bicep resources;
- Region checks for resource deployments.
Preview the changes when deploying a Bicep file.
Overall Good practices
Working with environments
Using the environments feature in Azure Pipelines makes it possible to link deployments to an environment. An environment owner can define checks and approvals which are inherited by deployments. It is important to establish good practices to review your pipeline definitions. Your repository can be configured to require pull request reviews on any changes to your main branch by using branch protection policies (like explained in: Terraform and Azure DevOps | Part 3 – Cloudfive).
More about working with the environments feature with Azure pipelines: Create target environment – Azure Pipelines | Microsoft Docs
Additional check and approvals
Adding additional checks and approvals to service connections, ensures that approval is needed before deployment.
Separate service connection
In certain stages you could use an additional separate service connection (service principal), for example the what-if stage. It is possible to have a custom Azure role defined based on least privileges (minimum permissions needed for execution).
Demo code can be downloaded at: Git CloudFive the repository consists of three files:
- bicepconfig.json > Linter configuration
- main.bicep > Bicep template
If you don’t have your own test project available or you are to lazy 😉 It is also possible to run a template and set up your Azure DevOps project. View steps @ Exercise – Set up your environment – Training | Microsoft Docs
In this example an Azure pipeline is built which consists of three stages:
- Lint > linting of Bicep file
- Validate > Is the Bicep template likely to deploy? Are names for resources already taken? Are resources valid?
- Deploy > Deploy resources
stages: - stage: Lint jobs: - job: LintCode displayName: Lint code steps: - script: | az bicep build --file deploy/main.bicep name: LintBicepCode displayName: Run Bicep linter - stage: Validate jobs: - job: ValidateBicepCode displayName: Validate Bicep code steps: - task: AzureResourceManagerTemplateDeployment@3 name: RunPreflightValidation displayName: Run preflight validation inputs: connectedServiceName: $(ServiceConnectionName) location: $(deploymentDefaultLocation) deploymentMode: Validation resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType) - stage: Deploy jobs: - job: Deploy steps: - task: AzureResourceManagerTemplateDeployment@3 name: Deploy displayName: Deploy to Azure inputs: connectedServiceName: $(ServiceConnectionName) deploymentName: $(Build.BuildNumber) location: $(DeploymentDefaultLocation) resourceGroupName: $(ResourceGroupName) csmFile: deploy/main.bicep overrideParameters: > -environmentType $(EnvironmentType)