| name | bicep |
| description | Creates bicep files (.bicep) from instructions according to best practices. |
| allowed-tools | WebFetch, WebSearch, Edit, Write, Read, Bash |
When writing bicep files (.bicep) follow best practices to ensure templates are easy to read, maintain, and deploy.
Workflow
Follow this workflow when writing bicep files:
-
Understand the requirements: Before writing any code, make sure you have a clear understanding of the requirements and the resources that need to be deployed. Ask questions to clarify any uncertainties.
-
Plan the structure: Decide on the structure of your bicep file, any relationship to existing Bicep files and how you will organize parameters, variables, resources, and outputs.
-
Write the code: Start writing the bicep code, following the best practices outlined below.
-
Validate the bicep file: After writing the code, you MUST run the following validation steps:
-
Run Bicep Build: Execute bicep build "<filepath>" to validate the bicep file and capture linter warnings (linting is automatically included in the build process)
-
Fix any syntax errors immediately
-
Address critical linter warnings (secure parameter defaults, etc.)
-
Clean up JSON files: Delete the generated JSON file after validation to avoid bloating the workspace:
rm "<filepath without .bicep>.json"
-
Create test parameters (if needed): If the bicep file has required parameters without defaults (especially @secure parameters):
-
Create a temporary .bicepparam file with test values (e.g., <filename>.test.bicepparam)
-
This allows PSRule to properly expand and validate the template
-
Clean up the test parameter file after validation to avoid confusion:
rm "<filename>.test.bicepparam"
-
Run PSRule: Execute PSRule against the specific bicep file (not the entire directory) to check for Azure best practice compliance. Use summary output to avoid context bloat:
pwsh -Command "Invoke-PSRule -InputPath '<filepath>' -Module PSRule.Rules.Azure -Outcome Fail -As Summary -Option '<ps-rule.yaml>'"
- Only scans the file(s) you created/edited, not other existing files
- Shows only failed rules in summary format to keep output concise
-
Categorize and address issues: After validation, group PSRule findings into:
- Critical Security Issues: e.g., NSG rules allowing "any" source, public IPs on VMs
- Best Practice Issues: e.g., missing tags, zone redundancy, monitoring agents
- False Positives: e.g., secret name outputs that don't expose actual values
Then:
- Fix Critical Issues: Address critical security issues immediately without prompting
- Ask About Best Practices: For best practice issues, use the AskUserQuestion tool to ask if they want to address them:
- Group related issues together (e.g., "Tagging", "High Availability", "Monitoring")
- Provide clear options with descriptions and trade-offs
- Include a "Skip" option if the user wants to proceed without changes
- Example categories:
- Security Hardening: NSG rules, private endpoints, disk encryption
- High Availability: Availability zones, zone-redundant resources
- Monitoring & Maintenance: Azure Monitor Agent, maintenance configurations
- Resource Organization: Tags, naming conventions, descriptions
-
Iterate: Apply fixes based on user selections and re-run validation until clean or user decides to stop.
Example workflow:
- Create bicep file
- Run
bicep build → Fix any linter errors → Clean up generated JSON file
- Create test parameter file if needed
- Run PSRule (summary, failures only, specific file) → Categorize findings
- Fix critical security issues automatically
- Use AskUserQuestion for best practice issues:
"I found several best practice improvements. Would you like to address them?"
- Security Hardening (2 issues): Restrict NSG rules, remove public IP
- High Availability (1 issue): Add availability zones
- Monitoring (2 issues): Add Azure Monitor Agent, maintenance config
- Skip all improvements
- Apply selected fixes and re-validate
Follow these best practices writing bicep files:
Parameters
- Use parameters for settings that change between deployments.
- If the using parameters, apply the best practices outlined in the parameters.md file.
Variables
- Use variables for hard-coded values can be used for settings that don't change between deployments.
- If using variables, apply the best practices outlined in the variables.md file.
Names
- Follow a standard naming convention for resource names, refer to Define your naming convention for guidance.
- Do not guess the environment name or application name when constructing resource names, ask for this information.
- Use Azure resource abbreviations when possible to keep names concise, use the abbreviations listed in the Abbreviation recommendations for Azure resources.
- Ensure resource names adhere to the naming rules and restrictions for each resource type, refer to the Naming rules and restrictions for Azure resources for details.
- Use Bicep's string interpolation to generate resource names as variables.
- The
uniqueString() function is useful for creating unique resource names. Use the uniqueString() function to generate part of the resource name. In most situations, the fully qualified resource group ID is a good option for the seed value for the uniqueString, for example:
var uniqueNameComponent = uniqueString(resourceGroup().id)
-
Prepend or append meaningful information to ensure your resources are easily identifiable.
-
Use lower camel case for names, such as myVariableName or myResource.
-
It's a good practice to use template expressions to create resource names, like in this example:
param shortAppName string = 'toy'
param shortEnvironmentName string = 'prod'
param appServiceAppName string = '${shortAppName}-${shortEnvironmentName}-${uniqueString(resourceGroup().id)}'
- Avoid using Name in a symbolic name. The symbolic name represents the resource, not the resource's name. This
resource cosmosDBAccount not this resource cosmosDBAccountName.
Resource definitions
- Prefer using Azure Verified Modules when possible:
- If using resource definitions instead of Azure Verified Modules, always the most recent stable API version for each resource, confirm using Azure resource reference. For example: Microsoft.Compute virtualMachines, avoid using WebSearch to find API versions, as this can lead to using outdated or incorrect API versions.
- Only preview API versions only when necessary to access features that aren't yet available in a stable release, and include comments in your Bicep file to explain why a preview API version is being used.
- Use variables instead of embedding complex expressions directly into resource properties to keep resource definitions clean and readable.
- Avoid using dependsOn, prefer using implicit dependencies over explicit dependencies.
- Avoid using the
reference and resourceId functions in your Bicep file.
Child resources
- Avoid nesting too many layers deep.
- Avoid constructing resource names for child resources, instead use the
parent property or nesting.
Outputs
- Use the existing keyword to reference resources instead of passing values through outputs.
- If using outputs, apply the best practices outlined in the outputs.md file.