All skills
microsoft avatar

/deploy

@b8a1c66
by microsoftmicrosoft/skills3.1k stars
351

Skills, MCP servers, Custom Agents, Agents.md for SDKs to ground Coding Agents

  • 16 files
  • 84.7 KB
  • Updated last week
  • GitHub

Use this Skill: https://skilld.dev/gh/microsoft/skills/deploy

This session only. Nothing lands on disk.

referencescode-deployment-container-apps.md

≈2.2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Code Deployment — Container Apps

After IaC deployment creates the Container App with a placeholder image (mcr.microsoft.com/azuredocs/containerapps-helloworld:latest), deploy the actual application code. This is Phase 2 of the two-phase Container Apps deployment pattern.

⛔ --subscription {subscriptionId} on EVERY az command (from context.json.azure.subscriptionId). Without it, the CLI uses whatever subscription is currently active — which may have changed since the prepare phase. This applies to ALL commands below.

⛔ Phase 2 is NOT optional. If IaC deployed a Container App with a placeholder image, you MUST execute Phase 2 before health checks. Do NOT leave a placeholder image and tell the user to deploy code manually.

Determine the code deploy path:

Condition Path Steps
ACR exists in IaC (services[] has Container Registry) ACR build + image update Steps 1–4 below
No ACR in IaC, simple app (single Dockerfile or source) Add ACR to IaC + redeploy, then ACR build Step 0 + Steps 1–4
No ACR in IaC, no Dockerfile, Oryx-compatible (Node/Python/Go/.NET) az containerapp update --source . Step 5 (Oryx shortcut)

Step 0 — Add ACR to IaC (if not already present)

Add container-registry.bicep module (ACR Basic, adminUserEnabled: false) + AcrPull role assignment for CA's managed identity (role GUID: 7f951dda-4ed3-4680-a7ca-43fe172d538d). Redeploy IaC, wait ~60s for AcrPull role propagation. Log as healing attempt.

⛔ Update prepare-plan.json (add ACR to services[]), scaffold-manifest.json.files[], and costEstimate.

Steps 1–4 — ACR Build + Image Update (IaC-compliant)

Step Command Notes
1. Build image az acr build --subscription {subscriptionId} -r {acrName} -t {appName}:latest . --no-logs Builds from workspace root. If buildRequirements.hasBuildKitSyntax, use -f Dockerfile.azure (see BuildKit handling below). ⛔ Build-time env vars: If Dockerfile has ARG NEXT_PUBLIC_* or ARG VITE_*, pass --build-arg NEXT_PUBLIC_API_URL=https://{api-fqdn} to inject the deployed API URL. These vars are baked into the JS bundle at build time — runtime env vars have no effect on client-side code. Get the API FQDN from Phase 1 output: az containerapp show -g {rg} -n {apiApp} --query properties.configuration.ingress.fqdn -o tsv.
2. Update Bicep image Edit infra/modules/{containerapp}.bicep: replace placeholder with image: '{acrLoginServer}/{appName}:latest'. Add ACR registry config: registries: [{ server: acrLoginServer, identity: 'system' }] IaC-only — no imperative az containerapp update
3. Redeploy az deployment sub create --subscription {subscriptionId} --location {location} --template-file infra/main.bicep --parameters @infra/main.parameters.json --parameters administratorLoginPassword=$dbPassword --name app-onboard-code-deploy-{timestamp} --query properties.provisioningState -o tsv Emit new portal link. ⛔ $dbPassword = existing KV secret, never new/placeholder — see Parameter Pass-Through.
4. Verify revision az containerapp show --subscription {subscriptionId} -g {rg} -n {ca} --query "{revision:properties.latestReadyRevisionName, image:properties.template.containers[0].image}" -o json Confirm image is not the placeholder

⛔ az acr build failures count toward the deploy-result.json.healingAttempts[] counter. After 3 failed builds (even with different root causes), pause and present a diagnosis to the user: "Web image build failed 3 times: [root causes]. Continue healing? (Yes / Cancel)." Each build fix attempt = 1 healing entry. Cross-reference deploy SKILL.md healing loop rule.

⛔ Windows: az acr build may fail with UnicodeEncodeError. Azure CLI log streaming crashes on non-ASCII characters (✓, ✗) using Windows charmap codec. Append --no-logs to the build command. Build success/failure is still reported via exit code.

Step 5 — Oryx Shortcut (no ACR needed, no Dockerfile)

az containerapp update --subscription {subscriptionId} -g {rg} -n {ca} --source . --set-env-vars NODE_ENV=production

⛔ az containerapp update --source is allowed for code deploy ONLY. This is different from az containerapp up --source (which is ⛔ BLOCKED because it creates resources imperatively). update --source updates an EXISTING Container App — no state drift.

Seed KV Secrets (between Phase 1 and Phase 2)

After Phase 1, seed real secret values into KV before Phase 2 activates secretRef:

az keyvault secret set --subscription {subscriptionId} --vault-name {kvName} --name {secret-name} --value $generatedValue

⛔ Use the SAME generated password passed to az deployment sub create. Shell variables don't persist between tool calls — reload from deploy-secrets.env (see deploy-safety.md § Deploy Checklist) or pass to BOTH commands in the same block.

After Code Deploy (all paths)

  • Wait 30–60s for the new revision to become ready
  • Proceed to Step 7 (Health-Check Endpoints)
  • If health check returns placeholder content → image update didn't take effect. Check az containerapp revision list

⛔ az containerapp revision restart does NOT re-resolve KV secrets. Container Apps caches KV-backed secretRef values at revision creation time. To pick up updated KV secrets, create a NEW revision by redeploying Bicep (preferred) or az containerapp update --revision-suffix rev{timestamp}. Do NOT use revision restart for KV secret rotation — it only restarts the container with the same cached values.

⛔ KV secretRef AND ACR registries require managed identity + roles to exist first. Phase 1 of the two-phase deploy creates the Container App with a placeholder image, registries: [], and secrets: []. Both KV secretRef and ACR registries with identity: 'system' fail in Phase 1 because the CA's managed identity doesn't exist yet (no principalId → AcrPull/KV role assignment fails → "Operation expired"). After Phase 1 completes and RBAC propagates (~60s), Phase 2 redeploys with ACR registries + KV secretRef + real image + correct targetPort.

Config-File Apps (Go/Viper, Spring Boot, etc.)

Creating Azure-specific config (e.g., config-azure.yml) is fine for non-secret values.

⛔ NEVER bake secrets into config files COPY'd into Docker images.

Secret injection: Config uses placeholders → az containerapp secret set → az containerapp update --set-env-vars KEY=secretref:name → framework env var override.

Go/Viper: AutomaticEnv() maps POSTGRES_PASSWORD → postgres_password (underscores), NOT postgres.password. Without SetEnvKeyReplacer(strings.NewReplacer(".", "_")), env vars can't override nested keys.

BuildKit Dockerfile Handling

ACR's az acr build uses the classic Docker builder — it does NOT support BuildKit. When buildRequirements.hasBuildKitSyntax == true: build using the ACR-compatible copy instead: az acr build -f Dockerfile.azure .. The user's original Dockerfile stays untouched. If Dockerfile.azure doesn't exist yet, create it by stripping BuildKit syntax from the original Dockerfile per dockerfile-generation.md § ACR Build Compatibility.

Parameter Pass-Through (Bicep Redeploy Safety)

⛔ On every redeploy, pass the SAME values you originally used — a full desired-state apply, not a patch, so an omitted param reverts to its default and a regenerated secret overwrites the live value. Two params bite:

  • containerImage — omitting it reverts the Container App to the placeholder image.
  • administratorLoginPassword (DB modules) — passing a new or placeholder value silently RESETS the database admin password, desyncing it from the Key Vault secret the app reads → runtime auth failures (Access denied for user).
$dbPassword = az keyvault secret show --subscription {subscriptionId} --vault-name {kvName} --name {db-secret} --query value -o tsv
az deployment sub create ... `
  --parameters containerImage='{acrLoginServer}/{appName}:latest' `
  --parameters administratorLoginPassword=$dbPassword `
  --query properties.provisioningState -o tsv

Database Post-Deploy Verification

⛔ You MUST read database-post-deploy.md for migration discovery, execution via Container Apps exec, error handling, and PostgreSQL-specific checks.

Source: SKILL.md on GitHub

No third-party reports yet.

Signed by skilld at b8a1c66. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 20 hours ago.

Activeupdated last week

README badge

README badge for microsoft/skills/deploy