Azure Deploy
MicrosoftOfficialCreated by Microsoft
- Skill
- Workflow
- Cloud and DevOps
- MIT
- Medium risk
- Has scripts
AutoGineer summary
Written by AutoGineer from the skill’s own files, not by the author
The azure-deploy skill manages the execution of cloud deployments for applications that have already been prepared and validated. It acts as the final stage in the deployment pipeline, ensuring that infrastructure and code are pushed to Azure using standardized recipes. The skill enforces strict prerequisites, requiring a validated deployment plan and a completed pre-deployment checklist to ensure success and minimize errors. It handles various deployment methods, including Azure Developer CLI (azd), Terraform, and Azure CLI, while providing built-in error recovery and post-deployment configuration steps.
What it does
- Executes deployment commands like azd up, azd deploy, and terraform apply.
- Verifies that the deployment plan is marked as Validated before proceeding.
- Performs pre-deployment health checks, including RBAC verification for managed identities.
- Configures post-deployment settings such as SQL managed identities and EF migrations.
- Provides verified, fully-qualified HTTPS endpoint URLs for the deployed application.
- Implements error recovery and verification steps based on specific deployment recipes.
When to use it
- When you need to push updates to an existing, already-prepared Azure deployment.
- When you have a project with an existing .azure/deployment-plan.md file.
- When you are ready to ship code to production after passing the azure-validate check.
- When you need to run standard deployment commands like azd up or az deployment.
Advantages
- Ensures deployment consistency by requiring a validated plan and pre-deploy checklist.
- Reduces deployment failures through automated RBAC health checks and error recovery.
- Standardizes post-deployment tasks like database migrations and identity configuration.
- Provides clear, actionable feedback with fully-qualified URLs for deployed services.
Usage examples
- “run azd up”
- The agent verifies the deployment plan status, completes the pre-deploy checklist, executes the deployment, and returns the HTTPS endpoint URLs.
- “push to production”
- The agent checks for a validated deployment plan, runs the appropriate deployment recipe, and confirms the application is live.
Install
Download the skill as a ZIP:
https://autogineer.com/agent-skills/microsoft/azure-deploy/downloadUnzip it into the cross-client skills folder of your project:
mkdir -p .agents/skills && unzip azure-deploy.zip -d .agents/skills
Documentation by Microsoft
Azure Deploy
AUTHORITATIVE GUIDANCE — MANDATORY COMPLIANCE
PREREQUISITE: The azure-validate skill MUST be invoked and completed with status
ValidatedBEFORE executing this skill.
⛔ STOP — PREREQUISITE CHECK REQUIRED Before proceeding, verify BOTH prerequisites are met:
azure-prepare was invoked and completed →
.azure/deployment-plan.mdexistsazure-validate was invoked and passed → plan status =
ValidatedIf EITHER is missing, STOP IMMEDIATELY:
No plan? → Invoke azure-prepare skill first
Status not
Validated? → Invoke azure-validate skill first⛔ DO NOT MANUALLY UPDATE THE PLAN STATUS
You are FORBIDDEN from changing the plan status to
Validatedyourself. Only the azure-validate skill is authorized to set this status after running actual validation checks. If you update the status without running validation, deployments will fail.DO NOT ASSUME the app is ready. DO NOT SKIP validation to save time. Skipping steps causes deployment failures. The complete workflow ensures success:
azure-prepare→azure-validate→azure-deploy
Triggers
Activate this skill when user wants to:
Execute deployment of an already-prepared application (azure.yaml and infra/ exist)
Push updates to an existing Azure deployment
Run
azd up,azd deploy, oraz deploymenton a prepared projectShip already-built code to production
Deploy an application that already includes API Management (APIM) gateway infrastructure
Scope: This skill executes deployments. It does not create applications, generate infrastructure code, or scaffold projects. For those tasks, use azure-prepare.
APIM / AI Gateway: Use this skill to deploy applications whose APIM/AI gateway infrastructure was already created during azure-prepare. For creating or changing APIM resources, see APIM deployment guide. For AI governance policies, invoke azure-aigateway skill.
Rules
Run after azure-prepare and azure-validate
.azure/deployment-plan.mdmust exist with statusValidatedPre-deploy checklist required — Pre-Deploy Checklist
⛔ Destructive actions require
ask_user— global-rulesScope: deployment execution only — This skill owns execution of
azd up,azd deploy,terraform apply, andaz deploymentcommands. These commands are run through this skill's error recovery and verification pipeline.
Steps
| # | Action | Reference |
|---|---|---|
| 1 | Check Plan — Read .azure/deployment-plan.md, verify status = Validated AND Validation Proof section is populated | .azure/deployment-plan.md |
| 2 | Pre-Deploy Checklist — MUST complete ALL steps | Pre-Deploy Checklist |
| 3 | Load Recipe — Based on recipe.type in .azure/deployment-plan.md | recipes/README.md |
| 4 | RBAC Health Check — For Container Apps + ACR with managed identity: run azd provision --no-prompt, then verify AcrPull role has propagated before proceeding (see checklist) | Pre-Deploy Checklist — Container Apps RBAC |
| 5 | Execute Deploy — Follow recipe steps | Recipe README |
| 6 | Post-Deploy — Configure SQL managed identity and apply EF migrations if applicable | Post-Deployment |
| 7 | Handle Errors — See recipe's errors.md | — |
| 8 | Verify Success — Confirm deployment completed and endpoints are accessible | Verification |
| 9 | Live Role Verification — Query Azure to confirm provisioned RBAC roles are correct and sufficient | live-role-verification.md |
| 10 | Report Results — Present deployed endpoint URLs to the user as fully-qualified https:// links | Verification |
⛔ URL FORMAT RULE
When presenting endpoint URLs to the user, you MUST always use fully-qualified URLs with the
https://scheme (e.g.https://myapp.azurewebsites.net, notmyapp.azurewebsites.net). Many Azure CLI commands return bare hostnames without a scheme — always prependhttps://before presenting them.
⛔ VALIDATION PROOF CHECK
When checking the plan, verify the Validation Proof section (Section 7) contains actual validation results with commands run and timestamps. If this section is empty, validation was bypassed — invoke azure-validate skill first.
SDK Quick References
Azure Developer CLI: azd
Azure Identity: Python | .NET | TypeScript | Java
MCP Tools
| Tool | Purpose |
|---|---|
mcp_azure_mcp_subscription_list | List available subscriptions |
mcp_azure_mcp_group_list | List resource groups in subscription |
mcp_azure_mcp_azd | Execute AZD commands |
azure__role | List role assignments for live RBAC verification (step 9) |
References
Troubleshooting - Common issues and solutions
Post-Deployment Steps - SQL + EF Core setup
Files
- ATTRIBUTION.mdAdded by AutoGineer968 B
- LICENSELicence file added by AutoGineer1.1 KiB
- SKILL.md6.5 KiB
- references/auth-best-practices.md6.1 KiB
- references/global-rules.md1.2 KiB
- references/live-role-verification.md3.9 KiB
- references/pre-deploy-checklist.md18.4 KiB
- references/recipes/README.md431 B
- references/recipes/azcli/README.md1.7 KiB
- references/recipes/azcli/errors.md492 B
- references/recipes/azcli/verify.md2.0 KiB
- references/recipes/azd/README.md3.7 KiB
- references/recipes/azd/ef-migrations.md5.0 KiB
- references/recipes/azd/errors.md15.4 KiB
- references/recipes/azd/functions-deploy.md3.5 KiB
- references/recipes/azd/post-deployment.md4.2 KiB
- references/recipes/azd/scripts/apply-migrations.ps1Script1.8 KiB
- references/recipes/azd/scripts/apply-migrations.shScript1.8 KiB
- references/recipes/azd/scripts/grant-and-migrate.ps1Script4.2 KiB
- references/recipes/azd/scripts/grant-and-migrate.shScript4.3 KiB
- references/recipes/azd/sql-entra-auth.md2.5 KiB
- references/recipes/azd/sql-managed-identity.md7.4 KiB
- references/recipes/azd/verify.md4.9 KiB
- references/recipes/bicep/README.md2.4 KiB
- references/recipes/bicep/errors.md511 B
- references/recipes/bicep/verify.md763 B
- references/recipes/cicd/README.md1.2 KiB
- references/recipes/cicd/errors.md542 B
- references/recipes/cicd/examples/azdo-azd.yml487 B
- references/recipes/cicd/examples/azdo-multistage.yml831 B
- references/recipes/cicd/examples/github-azd.yml782 B
- references/recipes/cicd/examples/github-bicep.yml660 B
- references/recipes/cicd/verify.md754 B
- references/recipes/terraform/README.md3.2 KiB
- references/recipes/terraform/errors.md858 B
- references/recipes/terraform/verify.md752 B
- references/region-availability.md3.0 KiB
- references/sdk/azd-deployment.md792 B
- references/sdk/azure-identity-dotnet.md941 B
- references/sdk/azure-identity-java.md1.2 KiB
- references/sdk/azure-identity-py.md1.1 KiB
- references/sdk/azure-identity-ts.md1.1 KiB
- references/troubleshooting.md8.0 KiB
references/recipes/azd/errors.md
AZD Errors
Deployment Runtime Errors
These errors occur during azd up execution:
| Error | Cause | Resolution |
|---|---|---|
unknown flag: --location | azd up doesn't accept --location | Use azd env set AZURE_LOCATION <region> before azd up |
| Provision failed | Bicep template errors | Check detailed error in output |
| Deploy failed | Build or Docker errors | Check build logs |
| Package failed | Missing Dockerfile or deps | Verify Dockerfile exists and dependencies |
| Quota exceeded | Subscription limits | Request increase or change region |
PrincipalId '...' has type 'ServicePrincipal', which is different from specified PrincipalType 'User' | Base template RBAC assigns roles with principalType: 'User' but deploying identity is a service principal (CI/CD) | Set allowUserIdentityPrincipal: false in the storageEndpointConfig variable in infra/main.bicep. Do NOT try clearing AZURE_PRINCIPAL_ID — azd repopulates it. See Principal Type Mismatch. |
ImagePullBackOff or azd up hangs during provision for Container Apps | Container App references an image that doesn't exist in ACR yet | See Container Apps Bootstrap Problem |
unauthorized: authentication required on docker push to ACR | ACR auth token expired or scoped incorrectly | See ACR Authentication Failures |
could not determine container registry endpoint | Missing AZURE_CONTAINER_REGISTRY_ENDPOINT | See Missing Container Registry Variables |
map has no entry for key "AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID" | Missing managed identity env vars | See Missing Container Registry Variables |
map has no entry for key "MANAGED_IDENTITY_CLIENT_ID" | Missing managed identity client ID | See Missing Container Registry Variables |
Operation expired / revision creation timeout (900s) | RBAC propagation delay — Container App's managed identity doesn't have AcrPull on ACR yet | See Container App Revision Timeout |
found '2' resources tagged with 'azd-service-name: <name>' | Previous deployment left duplicate-tagged resources in same RG | Preferred: Create fresh env with azd env new <new-name> --no-prompt, set subscription/location, redeploy. Alternative: Delete conflicting resources (requires ask_user). |
Literal {{ .Env.* }} in Terraform errors | azd does not interpolate template variables in .tfvars.json | See Unresolved Terraform Template Variables |
ℹ️ Pre-flight validation: Run
azure-validatebefore deployment to catch configuration errors early. See Pre-Deploy Checklist.
Container App Revision Timeout
Symptom: azd up provisions infrastructure successfully but the Container App revision creation times out after ~900 seconds. The Container App enters a Failed provisioning state with no active revision. The azd output shows Operation expired or The operation did not complete within the permitted time.
Cause: Azure RBAC propagation delay. When azd up runs both azd provision and azd deploy in a single step:
Bicep creates the Container App with a system-assigned managed identity and a public placeholder image
Bicep creates an
AcrPullrole assignment for that identity on ACR in a separate module using the two-phase deployment patternazd deployimmediately pushes the real image and creates a new Container App revisionThe revision tries to pull the image from ACR, but the
AcrPullrole assignment hasn't propagated yet (can take 1–5 minutes)The image pull fails repeatedly until the 900-second timeout is reached
Solution:
Verify the Container App state:
az containerapp show --name <app-name> --resource-group <resource-group> \
--query "{provisioningState:properties.provisioningState, latestRevision:properties.latestRevisionName}" -o jsonConfirm the AcrPull role exists (it may have propagated by now):
PRINCIPAL_ID=$(az containerapp identity show --name <app-name> --resource-group <resource-group> --query principalId -o tsv)
az role assignment list --scope $(az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv) \
--assignee-object-id "$PRINCIPAL_ID" --query "[].roleDefinitionName" -o tsvPowerShell:
$PrincipalId = az containerapp identity show --name <app-name> --resource-group <resource-group> --query principalId -o tsv
$AcrScope = az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv
az role assignment list --scope $AcrScope --assignee-object-id $PrincipalId --query "[].roleDefinitionName" -o tsvIf AcrPull is missing, assign it:
az role assignment create \
--assignee-object-id "$PRINCIPAL_ID" \
--assignee-principal-type ServicePrincipal \
--role AcrPull \
--scope $(az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv)PowerShell:
$AcrScope = az acr show --name <acr-name> --resource-group <resource-group> --query id -o tsv
az role assignment create `
--assignee-object-id $PrincipalId `
--assignee-principal-type ServicePrincipal `
--role AcrPull `
--scope $AcrScopeWait for propagation, then redeploy:
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT $(az acr show --name <acr-name> --resource-group <resource-group> --query loginServer -o tsv)
for attempt in 1 2 3 4 5; do
echo "Waiting for RBAC propagation (attempt $attempt/5)..."
sleep 60
if azd deploy --no-prompt; then
echo "Deployment succeeded after RBAC propagation."
break
fi
if [ "$attempt" -eq 5 ]; then
echo "Deployment still failing after 5 minutes. Re-check AcrPull assignment and Container App revision status."
exit 1
fi
donePowerShell:
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT (az acr show --name <acr-name> --resource-group <resource-group> --query loginServer -o tsv)
for ($attempt = 1; $attempt -le 5; $attempt++) {
Write-Output "Waiting for RBAC propagation (attempt $attempt/5)..."
Start-Sleep -Seconds 60
azd deploy --no-prompt
if ($LASTEXITCODE -eq 0) {
Write-Output "Deployment succeeded after RBAC propagation."
break
}
if ($attempt -eq 5) {
Write-Output "Deployment still failing after 5 minutes. Re-check AcrPull assignment and Container App revision status."
exit 1
}
}💡 Prevention: To avoid this in future deployments, ensure the Bicep template includes the
AcrPullrole assignment withprincipalType: 'ServicePrincipal', and consider usingazd provision+azd deployas separate steps instead ofazd upto allow RBAC propagation time between infrastructure creation and app deployment.
Container Apps Bootstrap Problem
Symptom: azd up hangs or fails during provisioning with ImagePullBackOff, or the Container App cannot start because the referenced image doesn't exist in ACR yet.
Cause: The Bicep template creates the Container App referencing an ACR image, but that image doesn't exist until azd deploy builds and pushes it. This chicken-and-egg problem blocks provisioning.
Solution — use two-phase deployment:
# Phase 1: Provision infrastructure (Container App uses placeholder image)
azd provision --no-prompt
# Phase 2: Build, push, and update Container App with real image
azd deploy --no-prompt⚠️ This requires the Bicep template to use a placeholder image parameter (e.g.,
mcr.microsoft.com/azuredocs/containerapps-helloworld:latest) so provisioning succeeds without the app image. If the Bicep hardcodes the ACR image reference, update it to accept acontainerImageNameparameter with a placeholder default before provisioning.
⚠️ Do NOT repeatedly poll a hanging
azd up— if there is no provisioning progress or you continue to seeImagePullBackOffevents for several minutes during a Container Apps deployment, stop it and switch to the two-phase approach above.
ACR Authentication Failures
Symptom: docker push fails with unauthorized: authentication required even after az acr login succeeds.
Solution — try these methods in order:
# Method 1: AAD-based login (preferred)
az acr login --name <acr-name>
docker push <acr-name>.azurecr.io/<image>:<tag>
# Method 2: Admin credentials (fallback)
ACR_USER=$(az acr credential show --name <acr-name> --query username -o tsv)
ACR_PASS=$(az acr credential show --name <acr-name> --query "passwords[0].value" -o tsv)
docker login <acr-name>.azurecr.io -u "$ACR_USER" -p "$ACR_PASS"
docker push <acr-name>.azurecr.io/<image>:<tag>PowerShell (Method 2):
$AcrUser = az acr credential show --name <acr-name> --query username -o tsv
$AcrPass = az acr credential show --name <acr-name> --query "passwords[0].value" -o tsv
docker login <acr-name>.azurecr.io -u $AcrUser -p $AcrPass
docker push <acr-name>.azurecr.io/<image>:<tag>💡 Tip: Prefer
azd deployover manualdocker push— azd handles ACR authentication automatically.
Missing Container Registry Variables
Symptom: Errors during azd deploy about missing container registry or managed identity environment variables:
ERROR: could not determine container registry endpoint, ensure 'registry' has been set in the docker options or 'AZURE_CONTAINER_REGISTRY_ENDPOINT' environment variable has been setOr:
ERROR: failed executing template file: template: manifest template:6:14: executing "manifest template" at <.Env.AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID>: map has no entry for key "AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID"Or:
ERROR: failed executing template file: template: manifest template:39:26: executing "manifest template" at <.Env.MANAGED_IDENTITY_CLIENT_ID>: map has no entry for key "MANAGED_IDENTITY_CLIENT_ID"Cause: This typically occurs with .NET Aspire projects using azd "limited mode" (in-memory infrastructure generation without explicit infra/ folder). The azd provision command creates the Azure Container Registry and Managed Identity resources but doesn't automatically populate the environment variables that azd deploy needs to reference them.
⚠️ Prevention is Better: For .NET Aspire projects, this issue should be addressed PROACTIVELY before deployment by setting up environment variables after
azd initbut beforeazd up. This avoids deployment failures entirely.
Solution:
After azd provision succeeds, manually set the missing environment variables by querying the provisioned resources:
# Get the resource group name (typically rg-{environment-name})
azd env get-values
# Set container registry endpoint
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT $(az acr list --resource-group <resource-group-name> --query "[0].loginServer" -o tsv)
# Set managed identity resource ID
azd env set AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID $(az identity list --resource-group <resource-group-name> --query "[0].id" -o tsv)
# Set managed identity client ID
azd env set MANAGED_IDENTITY_CLIENT_ID $(az identity list --resource-group <resource-group-name> --query "[0].clientId" -o tsv)PowerShell:
# Set container registry endpoint
azd env set AZURE_CONTAINER_REGISTRY_ENDPOINT (az acr list --resource-group <resource-group-name> --query "[0].loginServer" -o tsv)
# Set managed identity resource ID
azd env set AZURE_CONTAINER_REGISTRY_MANAGED_IDENTITY_ID (az identity list --resource-group <resource-group-name> --query "[0].id" -o tsv)
# Set managed identity client ID
azd env set MANAGED_IDENTITY_CLIENT_ID (az identity list --resource-group <resource-group-name> --query "[0].clientId" -o tsv)After setting these variables, retry the deployment:
azd deploy --no-prompt💡 Tip: This issue is specific to Aspire limited mode. Manually setting these environment variables after
azd provisionis the recommended workaround.
Unresolved Terraform Template Variables
Symptom: Terraform receives literal Go-style template strings instead of resolved values during azd provision:
Error: Invalid value for variable "environment_name"
The value "{{ .Env.AZURE_ENV_NAME }}" is not valid.Or Terraform silently uses the literal string, causing resource naming failures, state conflicts, and cascading errors that lead to deployment timeouts.
Cause: azd reads infra/main.tfvars.json, substitutes ${VAR} references using its built-in envsubst, and passes the resolved file to Terraform via -var-file=. Go-style {{ .Env.* }} variables are only processed in azure.yaml and service manifests — they are NOT interpolated in .tfvars.json or any Terraform variable files. If azure-prepare generated a main.tfvars.json with Go-style template expressions, those literal strings are passed to Terraform.
Solution:
Fix the syntax in
infra/main.tfvars.json— replace Go-style{{ .Env.* }}with${VAR}:{ "environment_name": "${AZURE_ENV_NAME}", "location": "${AZURE_LOCATION}", "subscription_id": "${AZURE_SUBSCRIPTION_ID}" }Or use
TF_VAR_*environment variables if you don't havemain.tfvars.json:azd env set TF_VAR_environment_name "$(azd env get-value AZURE_ENV_NAME)" azd env set TF_VAR_location "$(azd env get-value AZURE_LOCATION)" azd env set TF_VAR_subscription_id "$(azd env get-value AZURE_SUBSCRIPTION_ID)"Ensure
variables.tfdeclares all required variables:variable "environment_name" { type = string } variable "location" { type = string }Re-run deployment:
azd up --no-prompt
⚠️ Prevention: This issue should be caught by
azure-validateStep 10 (Template Variable Resolution Check) before deployment. If you encounter it, re-run validation after fixing.
Retry
After fixing the issue:
azd up --no-promptPrincipal Type Mismatch
Symptom: azd up fails during provisioning with:
PrincipalId '...' has type 'ServicePrincipal', which is different from specified PrincipalType 'User'Cause: Many AZD templates (e.g., functions-quickstart-python-http-azd) include RBAC role assignments for the deploying user with hardcoded principalType: 'User'. This is controlled by an allowUserIdentityPrincipal flag in main.bicep's storageEndpointConfig variable. When deploying from CI/CD with a service principal, azd sets AZURE_PRINCIPAL_ID to that service principal's object ID, but the Bicep still tries to create a role assignment with principalType: 'User', causing ARM to reject it.
Solution:
In infra/main.bicep, find the storageEndpointConfig variable and set allowUserIdentityPrincipal to false:
var storageEndpointConfig = {
enableBlob: true
enableQueue: false
enableTable: false
enableFiles: false
allowUserIdentityPrincipal: false // Set to false for service principal deployments
}⚠️ Do NOT try to fix this by running
azd env set AZURE_PRINCIPAL_ID "". TheazdCLI repopulates this value from the current auth context, so clearing it has no effect.
Cleanup (DESTRUCTIVE)
azd down --force --purge⚠️ Permanently deletes ALL resources including databases and Key Vaults.
Requirements and compatibility
Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta
“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.
Security
What our scanner noticed· Medium risk
- Instructions that use the network
- Downloads piped into a shell
- Scripts that your agent may run
This skill includes scripts that your agent may run. Read them before you use it.
A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.
Attribution and licence
- Created by
- Microsoft
- Publisher
- Microsoft (Official)
- Source
- microsoft/skills · .github/plugins/azure-skills/skills/azure-deploy · commit 0696600
- Licence
- MIT License (redistribution allowed)
- LICENSE (added by AutoGineer from .github/plugins/azure-skills/LICENSE)
- ATTRIBUTION.md (written by AutoGineer)
- Synced
- Also distributed in
- microsoft/azure-skills
AutoGineer is not affiliated with or endorsed by Microsoft or Microsoft.
Download ZIP
The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download azure-deploy.zip