Developing with Azure Bicep
Azure Bicep ships with a growing set of features to help you develop your Infrastructure as Code. While the defaults are designed to help you get started quickly, you can customize your development experience to suit the needs of your organization.
While it is possible to work with multiple configuration files, we recommend keeping a top-level bicepconfig.json
file at the root of each repo, and using inline linter overrides in individual Bicep files where necessary.
See here for an overview of the Bicep configuration file.
All linter rules come with a default level, but this can be overridden in the Bicep configuration file. You may want to think carefully about which rules you want to enforce (by upgrading the level to “error”), or disable (by downgrading the level to “off”) at the repository level.
Here is an example Bicep configuration file with linter rule customizations:
|
|
It is possible to disable linting violations inline in your Bicep file using the #disable-next-line
directive. See Silencing false positives for more information.
If you don’t feel that the linter rule applies to your code generally, use the bicepconfig.json
in your repo to disable it globally rather than using inline overrides.
If you are consuming modules from one or more private Module Registries, it is worth configuring your bicepconfig.json
with common module aliases to simplify usage.
For example, the following configuration:
{
"moduleAliases": {
"br": {
"storage": {
"registry": "myprivateregistry.azurecr.io",
"modulePath": "bicep/modules/storage"
}
}
}
}
Would allow you to simplify usage to:
module foo 'br/storage:account:v1' = {
...
}
Registry tags should be considered immutable when publishing modules. You should always pin to a specific tag (e.g. v0.2.1
) instead of a tag that may be changed (latest
), to ensure that your deployment is reproducible in the future should you need to redeploy.
Prefer using @description()
decorators over code comments for explaining functionality, because they can be understood programatically with tooling:
- The Bicep VSCode extension will show hovers containing descriptions on parameters, outputs, and other declarations. This makes them easier for other developers to quickly understand.
- There are tooling options to automatically generate Markdown documentation for Wikis or documentation sites based on
@description()
annotations.
If you’re defining files within your Bicep files to use in your deployment, consider instead using the loadTextContent
function for non-binary content, the loadFileAsBase64
function for binary content, and the loadJsonContent
/ loadYamlContent
for loading JSON / YAML respectively.
This is preferred:
var myScript = loadTextContent('bash.sh')
Over:
var myScript = '''
#!/bin/bash
...
'''
It’s generally better to be able to represent these as separate files in your repo, as it allows for editors to understand the syntax, and makes it simpler to test them when authoring. loadJsonContent
& loadYamlContent
also understand your files structurally, and will allow for completions and type validation when using them - making for a better editor experience.
Instead of defining the following:
@description('The name of the storage account')
param storageAccountName string
@description('The storage account SKU')
param storageAccountSku string
Consider instead using User-defined types to group related fields together:
@description('Storage account properties')
param storageAccount {
@description('The resource name')
name: string
@description('The SKU')
sku: string
}
Defining your parameters with Bicep parameters files gives you the following advantages over JSON-based parameters:
- Instant editor feedback about mismatches or type validation issues.
- Support for expressions (including loading data from external files).
- Easy-to-interpret diagnostics at deploy time if there are any failures compiling.
It’s useful to have control over the version of Bicep you install in your CI pipeline. This ensures that your builds are reproducible, yielding the following benefits:
- You are in control of upgrading Bicep: New validations or linters are added periodically, and may impact whether your Bicep files build successfully. Rather than having this happen automatically whenever a new version is published, we recommend being in control of your Bicep version by explicitly referencing it in your pipeline.
- You have the guarantee that your CI & CD pipeline are running with the exact same version of Bicep: You’ll have a higher level of confidence that a pass in CI will translate to a pass in CD.
- You can redeploy an old copy of your code having to fix things: Because the version of Bicep is declared in your codebase, you’ll have a guarantee that if your Bicep file built successfully 1 year ago, it’ll still build successfully today.
For Azure CLI, you can achieve this with the following. Replace v0.21.1
with the version you wish to pin to.
az bicep install --version v0.21.1