E

Expert Bicep Implement

All-in-one agent covering azure, bicep, infrastructure, code. Includes structured workflows, validation checks, and reusable patterns for devops infrastructure.

AgentClipticsdevops infrastructurev1.0.0MIT
0 views0 copies

Expert Bicep Implement

An Azure Bicep Infrastructure as Code specialist that writes production-grade Bicep templates following Azure best practices, covering module design, parameter validation, conditional deployments, and CI/CD integration.

When to Use This Agent

Choose Expert Bicep Implement when:

  • Writing new Bicep templates for Azure resource deployments
  • Refactoring ARM JSON templates into clean Bicep code
  • Creating reusable Bicep modules for team-wide use
  • Implementing conditional and looped resource deployments
  • Setting up Bicep CI/CD pipelines with validation and what-if

Consider alternatives when:

  • Using Azure Verified Modules (use Azure Verified Modules Guru)
  • Exporting existing resources to IaC (use Azure IaC Exporter)
  • Writing Terraform instead of Bicep (use a Terraform specialist)

Quick Start

# .claude/agents/expert-bicep-implement.yml name: Expert Bicep Implement description: Write production-grade Azure Bicep templates model: claude-sonnet tools: - Read - Write - Edit - Bash - Glob - Grep

Example invocation:

claude "Create a Bicep module for deploying an Azure App Service with staging slots, managed identity, custom domain, and diagnostic settings"

Core Concepts

Bicep Template Structure

FilePurposeExample
main.bicepOrchestration, module compositionDeploys all modules
modules/*.bicepReusable resource modulesappService.bicep
parameters/*.jsonEnvironment-specific valuesdev.parameters.json
bicepconfig.jsonLinter and registry configModule aliases

Bicep Module Pattern

// modules/appService.bicep @description('Name of the App Service') param appName string @description('Azure region') param location string = resourceGroup().location @description('App Service Plan SKU') @allowed(['B1', 'S1', 'P1v3', 'P2v3']) param skuName string = 'S1' @description('Enable staging deployment slot') param enableStagingSlot bool = true @description('Log Analytics workspace ID for diagnostics') param logAnalyticsWorkspaceId string @description('Tags to apply to all resources') param tags object = {} // App Service Plan resource appServicePlan 'Microsoft.Web/serverfarms@2023-01-01' = { name: '${appName}-plan' location: location tags: tags sku: { name: skuName } properties: { reserved: true } } // Web App resource webApp 'Microsoft.Web/sites@2023-01-01' = { name: appName location: location tags: tags identity: { type: 'SystemAssigned' } properties: { serverFarmId: appServicePlan.id httpsOnly: true siteConfig: { linuxFxVersion: 'NODE|20-lts' alwaysOn: true ftpsState: 'Disabled' minTlsVersion: '1.2' http20Enabled: true } } } // Staging slot (conditional) resource stagingSlot 'Microsoft.Web/sites/slots@2023-01-01' = if (enableStagingSlot) { parent: webApp name: 'staging' location: location tags: tags identity: { type: 'SystemAssigned' } properties: { serverFarmId: appServicePlan.id siteConfig: webApp.properties.siteConfig } } // Diagnostic settings resource diagnostics 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = { scope: webApp name: '${appName}-diag' properties: { workspaceId: logAnalyticsWorkspaceId logs: [ { category: 'AppServiceHTTPLogs', enabled: true } { category: 'AppServiceConsoleLogs', enabled: true } { category: 'AppServiceAppLogs', enabled: true } ] metrics: [ { category: 'AllMetrics', enabled: true } ] } } // Outputs output appServiceId string = webApp.id output defaultHostname string = webApp.properties.defaultHostName output principalId string = webApp.identity.principalId

CI/CD Pipeline

# .github/workflows/deploy-infra.yml name: Deploy Infrastructure on: push: paths: ['infra/**'] branches: [main] pull_request: paths: ['infra/**'] jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: azure/login@v2 with: client-id: ${{ secrets.AZURE_CLIENT_ID }} tenant-id: ${{ secrets.AZURE_TENANT_ID }} subscription-id: ${{ secrets.AZURE_SUBSCRIPTION_ID }} - run: az bicep build --file infra/main.bicep - run: | az deployment group validate \ --resource-group myapp-rg \ --template-file infra/main.bicep \ --parameters infra/parameters/prod.json what-if: needs: validate if: github.event_name == 'pull_request' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: azure/login@v2 with: { client-id: '${{ secrets.AZURE_CLIENT_ID }}', tenant-id: '${{ secrets.AZURE_TENANT_ID }}', subscription-id: '${{ secrets.AZURE_SUBSCRIPTION_ID }}' } - run: | az deployment group what-if \ --resource-group myapp-rg \ --template-file infra/main.bicep \ --parameters infra/parameters/prod.json deploy: needs: validate if: github.ref == 'refs/heads/main' runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 - uses: azure/login@v2 with: { client-id: '${{ secrets.AZURE_CLIENT_ID }}', tenant-id: '${{ secrets.AZURE_TENANT_ID }}', subscription-id: '${{ secrets.AZURE_SUBSCRIPTION_ID }}' } - run: | az deployment group create \ --resource-group myapp-rg \ --template-file infra/main.bicep \ --parameters infra/parameters/prod.json

Configuration

ParameterDescriptionDefault
bicep_versionBicep CLI versionlatest
target_scopeDeployment scope (resourceGroup, subscription)resourceGroup
module_registryBicep module registry (public, private ACR)br/public
linter_rulesBicep linter configurationDefault rules
naming_conventionResource naming patternAzure CAF
parameter_formatParameter file format (json, bicepparam)json

Best Practices

  1. Use parameter decorators for validation instead of runtime checks. Bicep's @allowed, @minLength, @maxLength, @minValue, and @maxValue decorators catch invalid parameters at deployment time, before any resources are created. Add @description to every parameter for self-documenting templates. Validation at the template level prevents failed deployments that partially create resources.

  2. Create modules for every reusable resource pattern. If an App Service with diagnostic settings and managed identity is deployed in 3 environments, create one module and call it 3 times with different parameters. Modules enforce consistency — every App Service gets the same security baseline, logging configuration, and identity setup. Changes to the module propagate to all deployments automatically.

  3. Use existing keyword to reference resources without redeploying them. When a module needs to reference a Key Vault, VNet, or Log Analytics workspace that is managed by another template, use resource kv 'Microsoft.KeyVault/vaults@2023-07-01' existing = { name: kvName }. This reads the resource's properties without attempting to modify it, avoiding permission conflicts and unintended changes.

  4. Run what-if on every pull request before merging infrastructure changes. The az deployment group what-if command shows exactly what resources will be created, modified, or deleted without actually making changes. Include the what-if output as a PR comment so reviewers can see the infrastructure impact. This is the Bicep equivalent of a terraform plan, and it prevents surprise changes.

  5. Separate concerns between main.bicep and modules. Main.bicep should only orchestrate module calls and pass parameters. All resource definitions belong in modules. This keeps main.bicep short and readable (under 100 lines), makes modules independently testable, and allows different teams to own different modules while sharing the same deployment orchestration.

Common Issues

Deployment fails with "resource already exists" when renaming resources. Azure does not rename resources — changing a name creates a new resource and orphans the old one, which may conflict. To rename, deploy the new resource alongside the old one, migrate data/configuration, then remove the old resource in a subsequent deployment. Never rename resources that contain stateful data (databases, storage accounts) without a migration plan.

Circular dependency between two resources that reference each other. Resource A's property references Resource B, and Resource B's property references Resource A, creating a deployment deadlock. Break the cycle by deploying one resource without the cross-reference, then updating it in a second deployment step. Alternatively, use dependsOn to establish ordering and set one reference using a resource block with the existing keyword after both resources exist.

Parameters file grows unwieldy with dozens of parameters. As templates add more resources and configuration options, the parameters file becomes difficult to manage. Group related parameters into objects: networking: { vnetPrefix, subnetPrefix, nsgRules } instead of vnetPrefix, subnetPrefix, nsgRules as separate top-level parameters. Use parameter files per environment and per module, not one monolithic file.

Community

Reviews

Write a review

No reviews yet. Be the first to review this template!

Similar Templates