# Bicep Generation Generate Bicep IaC files from the approved infrastructure plan. > Important: All Bicep files must be created under `/infra/`. Never place `.bicep` files in the project root or in `.azure/`. ## File Structure Generate files under `/infra/`: ``` infra/ ├── main.bicep # Orchestrator — deploys all modules ├── main.bicepparam # Parameter values └── modules/ ├── storage.bicep # One module per resource or logical group ├── compute.bicep ├── networking.bicep └── monitoring.bicep ``` ## Generation Steps 1. Create `infra/` directory — create `/infra/` and `/infra/modules/` directories. All files in subsequent steps go here. 2. Read plan — load `/.azure/infrastructure-plan.json`, verify `meta.status === "approved"` 3. Fetch Bicep schemas — for each resource in the plan, use a sub-agent to call `bicepschema_get` with `resource-type` set to the ARM type from the relevant [resources/](resources/README.md) category file (e.g., `Microsoft.ContainerService/managedClusters`). Instruct the sub-agent: "Return the full property structure for {ARM type}: required properties, allowed values, child resources. ≤500 tokens." Use this output — not training data — to generate correct resource definitions. > The schema tool returns only the schema for the exact type requested. Sub-resource types (e.g., `Microsoft.Network/virtualNetworks/subnets`) return a smaller, focused schema but miss parent-level properties (e.g., VNet `encryption` lives on the parent, not the subnet sub-resource). Strategy: > - Start with sub-resource types when validating child resources — smaller responses (~25KB vs ~95KB), easier to summarize > - Fetch the parent type separately when you need parent-level properties (encryption, tags, SKU) — delegate to a sub-agent with specific property extraction instructions to manage the large response 4. Generate modules — group resources by category; one `.bicep` file per group under `infra/modules/`. Use the schema from step 3 for property names, allowed values, and required fields. 5. Generate main.bicep — write `infra/main.bicep` that imports all modules and passes parameters 6. Generate parameters — create `infra/main.bicepparam` with environment-specific values ## Bicep Conventions - Use `@description()` decorators on all parameters - Use `@secure()` for secrets and connection strings - Choose `targetScope` in `main.bicep` based on the deployment plan: - For single resource group deployments, set `targetScope = 'resourceGroup'` and deploy with `az deployment group create`. - For subscription-scope deployments (for example, resources across multiple resource groups or subscription-level resources), set `targetScope = 'subscription'` and deploy with `az deployment sub create`. - Use `existing` keyword for referencing pre-existing resources - Output resource IDs and endpoints needed by other resources - Use `dependsOn` only when implicit dependencies are insufficient ## Parameter File Format ```bicep using './main.bicep' param location = 'eastus' param environmentName = 'prod' param workloadName = 'datapipeline' ``` ## Multi-Environment For multi-environment plans, generate one parameter file per environment: ```txt infra/ ├── main.bicep ├── main.dev.bicepparam ├── main.staging.bicepparam └── main.prod.bicepparam ``` ## Validation Before Deployment Run `az bicep build --file infra/main.bicep` to validate syntax before deploying.