Skip to main content

aigbb-azd-compliance

Validate and deploy Azure Developer CLI (azd) projects with compliance-first patterns. Covers azure.yaml configuration, Bicep parameter sync, Container Apps image preservation (IMAGE_NAME/RESOURCE_EXISTS), service-to-resource binding, azd tags, hook scripts, shared subscription safety, and pre-flight validation. Use when setting up azd projects, writing azure.yaml, validating Bicep infrastructure for Container Apps, troubleshooting azd up failures, running compliance checks, or preparing for deployment. Triggers on azd, azure.yaml, azd compliance, azd deploy, azd provision, azd up, Container Apps deployment, IMAGE_NAME, RESOURCE_EXISTS, remoteBuild, azd tags, parameter mismatch, pre-flight check, deployment validation.

Jump to install

Source facts

Repository
aiappsgbb/template
Last source activity
February 26, 2026 at 21:12
Detected SKILL.md language
English
Stars
0
Forks
0

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
6 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
aigbb-azd-compliance
description
Validate and deploy Azure Developer CLI (azd) projects with compliance-first patterns. Covers azure.yaml configuration, Bicep parameter sync, Container Apps image preservation (IMAGE_NAME/RESOURCE_EXISTS), service-to-resource binding, azd tags, hook scripts, shared subscription safety, and pre-flight validation. Use when setting up azd projects, writing azure.yaml, validating Bicep infrastructure for Container Apps, troubleshooting azd up failures, running compliance checks, or preparing for deployment. Triggers on azd, azure.yaml, azd compliance, azd deploy, azd provision, azd up, Container Apps deployment, IMAGE_NAME, RESOURCE_EXISTS, remoteBuild, azd tags, parameter mismatch, pre-flight check, deployment validation.
# Azure Developer CLI (azd) Compliance & Deployment Deploy containerized applications to Azure Container Apps with full compliance validation. This skill combines deployment patterns with the checks needed to prevent `azd provision` and `azd deploy` failures. **Philosophy**: Only flag issues that will cause failures or runtime problems. Skip style preferences. --- ## Quick Start ```bash azd auth login # Authenticate azd init # Creates azure.yaml and .azure/ folder azd env new <env-name> # Create environment (dev, staging, prod) azd up # Provision infra + build + deploy ``` --- ## 1. azure.yaml Configuration ### Minimal Configuration ```yaml name: my-app services: api: project: ./src/api language: python host: containerapp docker: path: ./Dockerfile remoteBuild: true ``` ### Full Configuration with Hooks ```yaml name: my-app metadata: template: my-project@1.0.0 infra: provider: bicep path: ./infra services: web: project: ./src/web language: ts host: containerapp docker: path: ./Dockerfile context: . remoteBuild: true api: project: ./src/api language: python host: containerapp docker: path: ./Dockerfile context: . remoteBuild: true hooks: preprovision: shell: sh run: python infra/scripts/preprovision.py postprovision: shell: sh run: python infra/scripts/postprovision.py predeploy: shell: sh run: python infra/scripts/predeploy.py postdeploy: shell: sh run: python infra/scripts/postdeploy.py ``` ### Critical azure.yaml Rules | Check | Why It Matters | |-------|----------------| | `name` field exists | azd refuses to run without it | | `infra.path` points to existing directory | `azd provision` fails immediately | | Service `project` paths exist | `azd deploy` can't find source code | | Service `host` matches infrastructure | Deploys to wrong/nonexistent resource | | `remoteBuild: true` on all containerapp services | Local builds fail on ARM Macs, in CI/CD, and require Docker Desktop | ### Service Hosts | azure.yaml `host` | Required Bicep Resource | |-------------------|------------------------| | `containerapp` | Container App with matching name pattern | | `function` | Function App | | `appservice` | App Service | | `staticwebapp` | Static Web App | ### Service Languages | Language | Value | Package Manager | |----------|-------|-----------------| | Python | `python` | requirements.txt or pyproject.toml | | TypeScript | `ts` | package.json | | JavaScript | `js` | package.json | | C# | `csharp` | .csproj | | Java | `java` | pom.xml or build.gradle | | Go | `go` | go.mod | --- ## 2. Parameter Sync (Most Common Failure) Every parameter in `main.bicep` that lacks a default **MUST** have a mapping in `main.parameters.json`. ### main.bicep Parameters ```bicep // These MUST be in main.parameters.json (no default) param environmentName string param location string // These are OPTIONAL in main.parameters.json (have defaults) param principalId string = '' param apiImageName string = '' param apiExists bool = false ``` ### main.parameters.json ```json { "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentParameters.json#", "contentVersion": "1.0.0.0", "parameters": { "environmentName": { "value": "${AZURE_ENV_NAME}" }, "location": { "value": "${AZURE_LOCATION}" }, "principalId": { "value": "${AZURE_PRINCIPAL_ID}" }, "apiImageName": { "value": "${SERVICE_API_IMAGE_NAME=}" }, "apiExists": { "value": "${SERVICE_API_RESOURCE_EXISTS=false}" } } } ``` ### Parameter Injection Syntax | Syntax | Meaning | |--------|---------| | `${AZURE_ENV_NAME}` | Required — azd auto-populates | | `${AZURE_LOCATION}` | Required — azd auto-populates | | `${MY_VAR}` | Must be set via `azd env set MY_VAR "value"` | | `${MY_VAR=default}` | Uses `default` if not set | | `${SERVICE_API_IMAGE_NAME=}` | Empty string default (for first deploy) | | `${SERVICE_API_RESOURCE_EXISTS=false}` | Boolean default (for first deploy) | ### Validation ```powershell # List parameters without defaults in main.bicep Select-String -Path infra/main.bicep -Pattern "^param\s+\w+\s+\w+$" | Where-Object { $_ -notmatch "=" } # List parameters in main.parameters.json (Get-Content infra/main.parameters.json | ConvertFrom-Json).parameters.PSObject.Properties.Name # Compare — every param without a default must appear in parameters.json ``` --- ## 3. Container Image Preservation (IMAGE_NAME / RESOURCE_EXISTS) For each service with `host: containerapp` in azure.yaml, azd manages two variables to prevent re-provision from overwriting the deployed container image. **Reference**: [Deploy to Azure Container Apps using azd](https://learn.microsoft.com/azure/developer/azure-developer-cli/container-apps-workflows) ### Required Variables Per Service For a service named `api` in azure.yaml: | Variable | Set By | Purpose | |----------|--------|---------| | `SERVICE_API_IMAGE_NAME` | `azd deploy` | Currently deployed image tag | | `SERVICE_API_RESOURCE_EXISTS` | `azd provision` | Whether Container App already exists | **Pattern**: `SERVICE_<UPPER_CASE_SERVICE_NAME>_IMAGE_NAME` and `SERVICE_<UPPER_CASE_SERVICE_NAME>_RESOURCE_EXISTS` ### Check 1: main.parameters.json Must Map Both ```json { "parameters": { "apiImageName": { "value": "${SERVICE_API_IMAGE_NAME=}" }, "apiExists": { "value": "${SERVICE_API_RESOURCE_EXISTS=false}" } } } ``` The `=` after the variable name provides a default (empty string or `false`) for first-time deployments. ### Check 2: Bicep Must Declare and Use Both ```bicep @description('Container image name for the api service') param apiImageName string = '' @description('Whether the api Container App already exists') param apiExists bool = false module api 'br/public:avm/res/app/container-app:0.18.1' = { name: 'api' params: { name: '${abbrs.appContainerApps}api-${resourceToken}' tags: union(tags, { 'azd-service-name': 'api' }) environmentResourceId: containerAppsEnvironment.outputs.resourceId containers: [ { name: 'main' image: !empty(apiImageName) ? apiImageName : 'mcr.microsoft.com/k8se/quickstart:latest' resources: { cpu: json('0.5'), memory: '1Gi' } } ] ingressExternal: true ingressTargetPort: 8000 } } ``` ### Check 3: Container App Module with Image Guard (Recommended) Use the AVM Container App module directly with the image guard pattern: ```bicep module api 'br/public:avm/res/app/container-app:0.18.1' = { params: { name: '${abbrs.appContainerApps}api-${resourceToken}' tags: union(tags, { 'azd-service-name': 'api' }) environmentResourceId: containerAppsEnvironment.outputs.resourceId containers: [ { name: 'main' image: !empty(apiImageName) ? apiImageName : 'mcr.microsoft.com/k8se/quickstart:latest' resources: { cpu: json('0.5'), memory: '1Gi' } env: [ { name: 'AZURE_CLIENT_ID', value: managedIdentity.outputs.clientId } ] } ] ingressExternal: true ingressTargetPort: 8000 registries: [ { server: '${containerRegistry.outputs.name}.azurecr.io' identity: managedIdentity.outputs.resourceId } ] } } ``` ### What Breaks Without This | Scenario | Without IMAGE_NAME / RESOURCE_EXISTS | With both variables | |----------|--------------------------------------|---------------------| | First `azd provision` | ✅ Works (uses default placeholder) | ✅ Works | | `azd deploy` | ✅ Pushes new image | ✅ Pushes new image | | Re-run `azd provision` | ❌ **Overwrites deployed image** with placeholder, app breaks | ✅ Preserves current image | | `azd up` (provision + deploy) | ⚠️ Temporary downtime between provision and deploy | ✅ Image preserved during provision phase | ### Validation Command ```powershell # Verify both variables exist for each containerapp service Select-String -Path infra/main.parameters.json -Pattern 'SERVICE_.*_IMAGE_NAME|SERVICE_.*_RESOURCE_EXISTS' ``` --- ## 4. Service-to-Resource Binding & Tags azd uses tags to discover deployed resources. Without them, `azd deploy` and `azd down` can't find your resources. ### Required: Resource Group Tag ```bicep var tags = { 'azd-env-name': environmentName // REQUIRED — azd uses this to find resources } ``` ### Required: Service Resource Tags For each service in azure.yaml, the corresponding Bicep resource **must** include `azd-service-name`: ```bicep tags: union(tags, { 'azd-service-name': 'api' // MUST match service key in azure.yaml }) ``` ### Tag-to-Service Mapping | azure.yaml | Bicep tag required | |------------|-------------------| | `services.api:` | `'azd-service-name': 'api'` | | `services.web:` | `'azd-service-name': 'web'` | | `services.frontend:` | `'azd-service-name': 'frontend'` | | `services.backend:` | `'azd-service-name': 'backend'` | **Why it matters**: Without these tags, azd can't find deployed resources for `azd deploy` or `azd down`. --- ## 5. Bicep Output Naming Convention azd needs outputs to know where services deployed and to auto-populate `.azure/<env>/.env`. ### Per-Service Outputs (Required) ```bicep // Pattern: SERVICE_<SERVICE_NAME>_<PROPERTY> output SERVICE_API_ENDPOINT_URL string = api.outputs.fqdn output SERVICE_API_NAME string = api.outputs.name output SERVICE_WEB_ENDPOINT_URL string = web.outputs.fqdn output SERVICE_WEB_NAME string = web.outputs.name ``` ### Infrastructure Outputs (Common) ```bicep output AZURE_LOCATION string = location output AZURE_RESOURCE_GROUP string = resourceGroup().name output AZURE_CLIENT_ID string = userAssignedIdentity.outputs.clientId output AZURE_KEY_VAULT_ENDPOINT string = keyVault.outputs.endpoint output AZURE_CONTAINER_REGISTRY_ENDPOINT string = containerRegistry.outputs.loginServer ``` All Bicep outputs automatically become azd environment variables in `.azure/<env>/.env`. --- ## 6. Hook Scripts ### Available Hook Points | Hook | Timing | Use Case | |------|--------|----------| | `prerestore` | Before package restore | Pre-install setup | | `postrestore` | After package restore | Post-install setup |
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub