diff --git a/plugin/skills/azure-deploy/SKILL.md b/plugin/skills/azure-deploy/SKILL.md index 015cd3836..d757a636c 100644 --- a/plugin/skills/azure-deploy/SKILL.md +++ b/plugin/skills/azure-deploy/SKILL.md @@ -1,10 +1,10 @@ --- name: azure-deploy -description: "Execute Azure deployments for ALREADY-PREPARED applications that have existing .azure/plan.md and infrastructure files. DO NOT use this skill when the user asks to CREATE a new application — use azure-prepare instead. This skill runs azd up, azd deploy, terraform apply, and az deployment commands with built-in error recovery. Requires .azure/plan.md from azure-prepare and validated status from azure-validate. WHEN: \"run azd up\", \"run azd deploy\", \"execute deployment\", \"push to production\", \"push to cloud\", \"go live\", \"ship it\", \"bicep deploy\", \"terraform apply\", \"publish to Azure\", \"launch on Azure\". DO NOT USE WHEN: \"create and deploy\", \"build and deploy\", \"create a new app\", \"set up infrastructure\", \"create and deploy to Azure using Terraform\" — use azure-prepare for these." +description: "Execute Azure deployments for ALREADY-PREPARED applications that have existing .azure/plan.md and infrastructure files. DO NOT use this skill when the user asks to CREATE a new application — use azure-prepare instead. This skill runs azd up, azd deploy, terraform apply, and az deployment commands with built-in error recovery. Requires .azure/plan.md from azure-prepare and validated status from azure-validate. WHEN: \"run azd up\", \"run azd deploy\", \"execute deployment\", \"push to production\", \"push to cloud\", \"go live\", \"ship it\", \"bicep deploy\", \"terraform apply\", \"publish to Azure\", \"launch on Azure\", \"deploy existing app\", \"deploy prepared app\", \"apply Terraform\", \"az deployment group create\", \"redeploy\", \"roll out\". DO NOT USE WHEN: \"create and deploy\", \"build and deploy\", \"create a new app\", \"set up infrastructure\", \"create and deploy to Azure using Terraform\" — use azure-prepare for these." license: MIT metadata: author: Microsoft - version: "1.0.2" + version: "1.0.3" --- # Azure Deploy diff --git a/plugin/skills/azure-prepare/SKILL.md b/plugin/skills/azure-prepare/SKILL.md index 55885842a..369b5f82f 100644 --- a/plugin/skills/azure-prepare/SKILL.md +++ b/plugin/skills/azure-prepare/SKILL.md @@ -1,10 +1,10 @@ --- name: azure-prepare -description: "Prepare Azure apps for deployment (infra Bicep/Terraform, azure.yaml, Dockerfiles). Use for create/modernize or create+deploy; not cross-cloud migration (use azure-cloud-migrate). WHEN: \"create app\", \"build web app\", \"create API\", \"create serverless HTTP API\", \"create frontend\", \"create back end\", \"build a service\", \"modernize application\", \"update application\", \"add authentication\", \"add caching\", \"host on Azure\", \"create and deploy\", \"deploy to Azure\", \"deploy to Azure using Terraform\", \"deploy to Azure App Service\", \"deploy to Azure App Service using Terraform\", \"deploy to Azure Container Apps\", \"deploy to Azure Container Apps using Terraform\", \"generate Terraform\", \"generate Bicep\", \"function app\", \"timer trigger\", \"service bus trigger\", \"event-driven function\", \"containerized Node.js app\", \"social media app\", \"static portfolio website\", \"todo list with frontend and API\", \"prepare my Azure application to use Key Vault\", \"managed identity\"." +description: "Prepare Azure apps for deployment (infra Bicep/Terraform, azure.yaml, Dockerfiles). Use for create/modernize or create+deploy; not cross-cloud migration (use azure-cloud-migrate). WHEN: \"create app\", \"build web app\", \"create API\", \"create serverless HTTP API\", \"create frontend\", \"create back end\", \"build a service\", \"modernize application\", \"update application\", \"add authentication\", \"add caching\", \"host on Azure\", \"create and deploy\", \"deploy to Azure\", \"generate Terraform\", \"generate Bicep\", \"function app\", \"timer trigger\", \"service bus trigger\", \"event-driven function\", \"containerized Node.js app\", \"social media app\", \"static portfolio website\", \"todo list with frontend and API\", \"prepare my Azure application to use Key Vault\", \"managed identity\", \"set up Azure infrastructure\", \"provision Azure resources\", \"scaffold Azure project\", \"azure.yaml\", \"infra/main.bicep\", \"Terraform infrastructure\", \"Bicep template\"." license: MIT metadata: author: Microsoft - version: "1.0.1" + version: "1.0.4" --- # Azure Prepare @@ -36,6 +36,8 @@ Activate this skill when user wants to: 6. **Confirm Azure context** — Use `ask_user` for subscription and location per [Azure Context](references/azure-context.md) 7. ❌ **Destructive actions require `ask_user`** — [Global Rules](references/global-rules.md) 8. **Scope: preparation only** — This skill generates infrastructure code and configuration files. Deployment execution (`azd up`, `azd deploy`, `terraform apply`) is handled by the **azure-deploy** skill, which provides built-in error recovery and deployment verification. +9. **Handoff is mandatory** — After plan approval and preparation, you MUST invoke **azure-validate** via skill call. If the user asked to deploy in the same request and validation succeeds, immediately hand off to **azure-deploy**. Do not just mention the next step—invoke it. +10. **Do not deploy in azure-prepare** — Never run deployment or provisioning commands here (e.g., `azd up`, `azd deploy`, `azd provision`, `terraform apply`, `az deployment group create`). Those are exclusively handled by **azure-deploy** after **azure-validate** succeeds. --- @@ -103,7 +105,7 @@ Execute the approved plan. Update `.azure/plan.md` status after each step. | 3 | **Generate Artifacts** — Create infrastructure and configuration files | [generate.md](references/generate.md) | | 4 | **Harden Security** — Apply security best practices | [security.md](references/security.md) | | 5 | **Update Plan** — Mark steps complete, set status to `Ready for Validation` | `.azure/plan.md` | -| 6 | **⚠️ Hand Off** — Invoke **azure-validate** skill. Your preparation work is done. Deployment execution is handled by azure-deploy. | — | +| 6 | **⚠️ Hand Off** — Invoke **azure-validate** skill now (skill call). If validation succeeds and the user requested deployment, immediately invoke **azure-deploy**. Do not run azd/terraform deployment commands here. | — | --- @@ -136,4 +138,8 @@ Execute the approved plan. Update `.azure/plan.md` status after each step. > > Skipping validation leads to deployment failures. Be patient and follow the complete workflow for the highest success outcome. +> **⚠️ REQUIRED ACTION** +> +> Invoke **azure-validate** now. If it succeeds and the user asked to deploy, immediately invoke **azure-deploy**. + **→ Invoke azure-validate now** diff --git a/tests/azure-deploy/__snapshots__/triggers.test.ts.snap b/tests/azure-deploy/__snapshots__/triggers.test.ts.snap index a55b16632..048de5ba6 100644 --- a/tests/azure-deploy/__snapshots__/triggers.test.ts.snap +++ b/tests/azure-deploy/__snapshots__/triggers.test.ts.snap @@ -2,7 +2,7 @@ exports[`azure-deploy - Trigger Tests Trigger Keywords Snapshot skill description triggers match snapshot 1`] = ` { - "description": "Execute Azure deployments for ALREADY-PREPARED applications that have existing .azure/plan.md and infrastructure files. DO NOT use this skill when the user asks to CREATE a new application — use azure-prepare instead. This skill runs azd up, azd deploy, terraform apply, and az deployment commands with built-in error recovery. Requires .azure/plan.md from azure-prepare and validated status from azure-validate. WHEN: "run azd up", "run azd deploy", "execute deployment", "push to production", "push to cloud", "go live", "ship it", "bicep deploy", "terraform apply", "publish to Azure", "launch on Azure". DO NOT USE WHEN: "create and deploy", "build and deploy", "create a new app", "set up infrastructure", "create and deploy to Azure using Terraform" — use azure-prepare for these.", + "description": "Execute Azure deployments for ALREADY-PREPARED applications that have existing .azure/plan.md and infrastructure files. DO NOT use this skill when the user asks to CREATE a new application — use azure-prepare instead. This skill runs azd up, azd deploy, terraform apply, and az deployment commands with built-in error recovery. Requires .azure/plan.md from azure-prepare and validated status from azure-validate. WHEN: "run azd up", "run azd deploy", "execute deployment", "push to production", "push to cloud", "go live", "ship it", "bicep deploy", "terraform apply", "publish to Azure", "launch on Azure", "deploy existing app", "deploy prepared app", "apply Terraform", "az deployment group create", "redeploy", "roll out". DO NOT USE WHEN: "create and deploy", "build and deploy", "create a new app", "set up infrastructure", "create and deploy to Azure using Terraform" — use azure-prepare for these.", "extractedKeywords": [ "already-prepared", "application", @@ -27,6 +27,7 @@ exports[`azure-deploy - Trigger Tests Trigger Keywords Snapshot skill descriptio "existing", "files", "from", + "group", "have", "identity", "infrastructure", @@ -35,11 +36,14 @@ exports[`azure-deploy - Trigger Tests Trigger Keywords Snapshot skill descriptio "live", "mcp", "plan", + "prepared", "production", "publish", "push", "recovery", + "redeploy", "requires", + "roll", "runs", "ship", "skill", @@ -85,6 +89,7 @@ exports[`azure-deploy - Trigger Tests Trigger Keywords Snapshot skill keywords m "existing", "files", "from", + "group", "have", "identity", "infrastructure", @@ -93,11 +98,14 @@ exports[`azure-deploy - Trigger Tests Trigger Keywords Snapshot skill keywords m "live", "mcp", "plan", + "prepared", "production", "publish", "push", "recovery", + "redeploy", "requires", + "roll", "runs", "ship", "skill", diff --git a/tests/azure-prepare/__snapshots__/triggers.test.ts.snap b/tests/azure-prepare/__snapshots__/triggers.test.ts.snap index 206b80b43..34e15bd84 100644 --- a/tests/azure-prepare/__snapshots__/triggers.test.ts.snap +++ b/tests/azure-prepare/__snapshots__/triggers.test.ts.snap @@ -2,7 +2,7 @@ exports[`azure-prepare - Trigger Tests Trigger Keywords Snapshot skill description triggers match snapshot 1`] = ` { - "description": "Prepare Azure apps for deployment (infra Bicep/Terraform, azure.yaml, Dockerfiles). Use for create/modernize or create+deploy; not cross-cloud migration (use azure-cloud-migrate). WHEN: \"create app\", \"build web app\", \"create API\", \"create serverless HTTP API\", \"create frontend\", \"create back end\", \"build a service\", \"modernize application\", \"update application\", \"add authentication\", \"add caching\", \"host on Azure\", \"create and deploy\", \"deploy to Azure\", \"deploy to Azure using Terraform\", \"deploy to Azure App Service\", \"deploy to Azure App Service using Terraform\", \"deploy to Azure Container Apps\", \"deploy to Azure Container Apps using Terraform\", \"generate Terraform\", \"generate Bicep\", \"function app\", \"timer trigger\", \"service bus trigger\", \"event-driven function\", \"containerized Node.js app\", \"social media app\", \"static portfolio website\", \"todo list with frontend and API\", \"prepare my Azure application to use Key Vault\", \"managed identity\".", + "description": "Prepare Azure apps for deployment (infra Bicep/Terraform, azure.yaml, Dockerfiles). Use for create/modernize or create+deploy; not cross-cloud migration (use azure-cloud-migrate). WHEN: \"create app\", \"build web app\", \"create API\", \"create serverless HTTP API\", \"create frontend\", \"create back end\", \"build a service\", \"modernize application\", \"update application\", \"add authentication\", \"add caching\", \"host on Azure\", \"create and deploy\", \"deploy to Azure\", \"generate Terraform\", \"generate Bicep\", \"function app\", \"timer trigger\", \"service bus trigger\", \"event-driven function\", \"containerized Node.js app\", \"social media app\", \"static portfolio website\", \"todo list with frontend and API\", \"prepare my Azure application to use Key Vault\", \"managed identity\", \"set up Azure infrastructure\", \"provision Azure resources\", \"scaffold Azure project\", \"azure.yaml\", \"infra/main.bicep\", \"Terraform infrastructure\", \"Bicep template\".", "extractedKeywords": [ "application", "apps", @@ -14,7 +14,6 @@ exports[`azure-prepare - Trigger Tests Trigger Keywords Snapshot skill descripti "build", "caching", "cli", - "container", "containerized", "create", "cross-cloud", @@ -29,7 +28,9 @@ exports[`azure-prepare - Trigger Tests Trigger Keywords Snapshot skill descripti "http", "identity", "infra", + "infrastructure", "list", + "main", "managed", "media", "migration", @@ -37,17 +38,21 @@ exports[`azure-prepare - Trigger Tests Trigger Keywords Snapshot skill descripti "node", "portfolio", "prepare", + "project", + "provision", + "resources", + "scaffold", "security", "serverless", "service", "social", "static", + "template", "terraform", "timer", "todo", "trigger", "update", - "using", "validation", "vault", "website", @@ -71,7 +76,6 @@ exports[`azure-prepare - Trigger Tests Trigger Keywords Snapshot skill keywords "build", "caching", "cli", - "container", "containerized", "create", "cross-cloud", @@ -86,7 +90,9 @@ exports[`azure-prepare - Trigger Tests Trigger Keywords Snapshot skill keywords "http", "identity", "infra", + "infrastructure", "list", + "main", "managed", "media", "migration", @@ -94,17 +100,21 @@ exports[`azure-prepare - Trigger Tests Trigger Keywords Snapshot skill keywords "node", "portfolio", "prepare", + "project", + "provision", + "resources", + "scaffold", "security", "serverless", "service", "social", "static", + "template", "terraform", "timer", "todo", "trigger", "update", - "using", "validation", "vault", "website", diff --git a/tests/utils/agent-runner.ts b/tests/utils/agent-runner.ts index 71732fa73..2666c9a86 100644 --- a/tests/utils/agent-runner.ts +++ b/tests/utils/agent-runner.ts @@ -394,6 +394,11 @@ export function useAgentRunner() { const skillDirectory = path.resolve(__dirname, "../../plugin/skills"); + const systemPrompt = config.systemPrompt ?? { + mode: "append", + content: "When a relevant skill is available, prefer using it instead of doing the task manually. This is an automated integration test: if you create a plan, continue execution without asking for user approval." + }; + const session = await client.createSession({ model: modelOverride || "claude-sonnet-4.5", onPermissionRequest: approveAll, @@ -406,10 +411,7 @@ export function useAgentRunner() { tools: ["*"] } }, - systemMessage: config.systemPrompt ?? { - mode: "append", - content: "When a relevant skill is available, prefer using it instead of doing the task manually." - } + systemMessage: systemPrompt }); entry.session = session; @@ -730,7 +732,7 @@ export async function runConversation(config: ConversationConfig): Promise