azure-stack-destroy
Skill274 starsChanged 28 days agoMITView on GitHub
Tear down a Git-Ape deployment by ID. Reads `state.json` under `.azure/deployments/<id>/` to delete the Azure Deployment Stack and purge soft-deleted Key Vault / Cognitive Services. Refuses to run without `state.json`. Use for any local CLI or VS Code Git-Ape teardown so the result matches the CI destroy workflow.
In this repository53 other files it gives its agents.
- website/docs/authoring/agents.mdAGENTS.md
- .github/copilot-instructions.mdCopilot instructions
- .github/skills/git-ape-onboarding/templates/copilot-instructions.mdCopilot instructions
- aws-api-gatewaySkill
- aws-bedrockSkill
- aws-cloudformationSkill
- aws-cloudwatchSkill
- aws-cognitoSkill
- aws-cost-estimatorSkill
- aws-dynamodbSkill
- aws-ec2Skill
- aws-ecsSkill
- aws-eksSkill
- aws-eventbridgeSkill
- aws-iamSkill
- aws-lambdaSkill
- aws-naming-researchSkill
- aws-rdsSkill
- aws-s3Skill
- aws-secrets-managerSkill
- aws-security-analyzerSkill
- aws-snsSkill
- aws-sqsSkill
- aws-step-functionsSkill
- csd-assessment-reportSkill
- deployment-blueprintsSkill
- fulfillment-and-meteringSkill
- isv-landing-zone-foundationSkill
- marketplace-offer-typesSkill
- marketplace-onboardingSkill
- multi-tenant-saasSkill
- onboard-to-marketplaceSkill
- saas-accelerator-bootstrapSkill
- saas-assessment-reportSkill
- scale-and-sreSkill
- security-and-complianceSkill
- tenant-isolation-modelsSkill
- tenant-lifecycle-automationSkill
- azure-cost-estimatorSkill
- azure-deployment-preflightSkill
- azure-drift-detectorSkill
- azure-integration-testerSkill
- azure-naming-researchSkill
- azure-policy-advisorSkill
- azure-resource-availabilitySkill
- azure-resource-visualizerSkill
- azure-rest-api-referenceSkill
- azure-role-selectorSkill
- azure-security-analyzerSkill
- azure-stack-deploySkill
- git-ape-onboardingSkill
- git-ape-skillsSkill
- prereq-checkSkill
The file
We split this skill into the rules it gives an agent
2 rules. About 0 are common, 1 is distinctive, and 1 is very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈1
Distinctive · estimate
This author's own choices. Worth a look.
1
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 12
After the stack is gone, this skill performs a soft-delete purge sweep for resource types that linger after deletion (Key Vault, Cognitive …
- Very specific: line 39
Deploying or updating a stack: Use azure-stack-deploy for those.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Azure Stack Destroy
Destroy a Git-Ape deployment by deleting its subscription-scoped Azure Deployment Stack in a single idempotent call (az stack sub delete --action-on-unmanage deleteAll --bypass-stack-out-of-sync-error true). The stack owns every resource the matching deploy created — across resource groups and subscription scope — so one delete cleans up everything.
After the stack is gone, this skill performs a soft-delete purge sweep for resource types that linger after deletion (Key Vault, Cognitive Services, App Configuration, API Management, ML workspaces, Recovery Services vaults). Resources flagged purgeProtected: true in state.json are intentionally retained.
This skill mirrors .github/workflows/git-ape-destroy.yml so local destroys and CI destroys are interchangeable.
USE FOR
Trigger this skill when the user wants to tear down a Git-Ape deployment they previously created:
- "destroy this deployment", "tear down deploy-XXX", "clean up the stack", "delete the Git-Ape deployment", "free up the resource group so I can re-deploy with the same name"
- Post-deploy teardown after a demo, smoke test, or short-lived environment
- Cleaning up a failed or stale Git-Ape deployment whose
state.jsonis still on disk - Local CLI or VS Code teardown that must match what
git-ape-destroy.ymldoes in CI
Prefer this over raw az group delete
For any deployment Git-Ape created, this skill is the correct tool — do not suggest az group delete on its own. Reasons:
- Multi-RG / subscription-scope coverage. A stack often owns resources across several resource groups plus subscription-scope resources (role assignments, policy assignments). One
az group deletecleans only one RG. - Soft-delete purge. Key Vault and Cognitive Services soft-delete on RG deletion and silently hold the name (and quota) for 7–90 days. This skill purges them so the user can re-deploy with the same name immediately.
- State consistency. Updates
state.jsonandmetadata.jsonto terminal status (destroyed,retained-soft-deleted, etc.) so the next operation sees an accurate view.
DO NOT USE FOR
Refuse to invoke this skill in any of these cases:
- No
state.jsonon disk. Hard prerequisite — see below. Without it, recommend re-running deploy or aborting. - Resource groups not created by Git-Ape (e.g. ones the user made by hand with
az group create). Suggestaz group delete --name <rg> --yesdirectly instead. - Deploying or updating a stack. Use
azure-stack-deployfor those. - Deleting an individual resource inside a stack. This skill always destroys the whole stack — there is no "surgical" mode.
- Non-Azure clouds or non-Git-Ape Azure deployments (ARM/Bicep/Terraform from other tools).
When to Use
- User says: "destroy this deployment", "tear down deploy-XXX", "clean up the stack"
- Pair with the matching
azure-stack-deploy— same stack, samestate.jsonkey (stackId) - Any time you would otherwise run
az group deleteagainst a Git-Ape deployment (don't — you'll miss soft-delete cleanup and multi-RG resources)
Prerequisites
| Tool | Why |
az (Azure CLI ≥ 2.59) | az stack sub delete --bypass-stack-out-of-sync-error requires a recent CLI |
jq | Read state.json |
bash ≥ 4 OR PowerShell 7+ | Either runner works |
Active az login | Must be the same subscription where the stack lives |
Existing state.json under .azure/deployments/<id>/ | Source of truth for stackId, managedResources, softDeletable, purgeProtected |
Hard prerequisite:
state.jsonunder.azure/deployments/<id>/. Without it this skill aborts — it has no idea which stack, resource groups, or soft-deletables to clean up. Do NOT hand-writestate.json; re-run the matchingazure-stack-deployfor that deployment ID first, or useaz group deletedirectly on a known resource group (a non-Git-Ape teardown, outside this skill's scope).
Procedure
Fast mode vs sync mode
The scripts default to fast mode (interactive default). The CI workflow keeps sync mode (deterministic).
| How | Wait time (small VNet stack) | When to use | |
| Fast (default) | Background the az stack sub delete call, then poll managed RGs with az group exists | ~2 min | Local CLI / VS Code use; user wants quick feedback |
Sync (--wait / -Wait) | az stack sub delete ... --yes (blocks until stack metadata is fully cleaned) | ~5 min | CI pipelines (default in git-ape-destroy.yml); when you need every Azure-side cleanup completed before the script exits |
The Azure CLI does not expose --no-wait on az stack sub delete, so the fast path runs the same command as a detached background process. In fast mode the stack-metadata cleanup continues asynchronously in Azure after the script returns. The next destroy of the same deploymentId is idempotent: if the stack is still finalizing, az stack sub show will return it and the script will simply pick up where Azure left off.
1. Identify deployment
DEPLOYMENT_ID="deploy-20260506-001"
DEPLOYMENT_PATH=".azure/deployments/$DEPLOYMENT_ID"
[[ -f "$DEPLOYMENT_PATH/state.json" ]] || { echo "state.json missing — cannot destroy"; exit 1; }2. Run the script
.github/skills/azure-stack-destroy/scripts/destroy-stack.sh \
--deployment-id "$DEPLOYMENT_ID"Skip the confirmation prompt (use only in automation):
.github/skills/azure-stack-destroy/scripts/destroy-stack.sh \
--deployment-id "$DEPLOYMENT_ID" \
--yesForce CI-equivalent sync wait (default for the CI workflow; opt-in for the script):
.github/skills/azure-stack-destroy/scripts/destroy-stack.sh \
--deployment-id "$DEPLOYMENT_ID" \
--yes --waitPowerShell equivalents:
.github/skills/azure-stack-destroy/scripts/destroy-stack.ps1 -DeploymentId "$DEPLOYMENT_ID"
.github/skills/azure-stack-destroy/scripts/destroy-stack.ps1 -DeploymentId "$DEPLOYMENT_ID" -Yes
.github/skills/azure-stack-destroy/scripts/destroy-stack.ps1 -DeploymentId "$DEPLOYMENT_ID" -Yes -Wait3. What the script does
- Reads
state.jsonand extractsstackId,deployMethod,resourceGroup,managedResources[],softDeletable[] - Prints a destroy plan — stack ID, resource group, count of soft-deletables (with purge-protection flagged)
- Prompts for typed
destroyconfirmation (unless--yes) - Stack delete path (
stackIdpresent):az stack sub delete --action-on-unmanage deleteAll --bypass-stack-out-of-sync-error true --yes- The bypass flag is safe in destroy because it's a one-shot operation — we don't need the stale-manifest safety check that protects iterative updates
- Fallback path (no
stackId, onlyresourceGroup):az group delete --name <rg> --yes - Purge sweep for each
softDeletableresource not markedpurgeProtected:- Key Vaults:
az keyvault list-deleted+az keyvault purge - Cognitive Services:
az cognitiveservices account purge - Other types (App Configuration, API Management, ML workspaces, Recovery Services vaults): not auto-purged — they expire from soft-delete naturally and are tracked in
purgeResults[]withstatus: skipped-natural-expiry
- Key Vaults:
- Cleans the subscription deployment-history entry (
az deployment sub delete) to stay under the 800/scope limit - Updates
state.jsonandmetadata.jsonwith terminal status:
| Status | Meaning |
destroyed | Stack/RG gone and all soft-deletables purged or absent |
retained-soft-deleted | Stack gone but at least one soft-deletable retained (purge-protected or purge failed) |
partially-destroyed | Stack delete partially failed |
destroy-failed | Stack/RG delete failed entirely |
already-destroyed | Stack and RG were already gone before this call |
4. Inspect the result
=== Destroy Summary ===
Status: destroyed
Duration: 87s
=======================Or, when something is intentionally retained:
=== Destroy Summary ===
Status: retained-soft-deleted
Duration: 92s
Retained: 1 soft-deleted resource(s) (purge-protected)
=======================state.json gains destroyedAt, destroyedBy, destroyDuration, and a purgeResults[] array describing each soft-deletable's outcome.
Arguments
| Flag (bash) | Param (pwsh) | Required | Description |
--deployment-id <id> | -DeploymentId <id> | yes | Folder name under .azure/deployments/ |
--yes | -Yes | no | Skip the typed destroy confirmation prompt (CI-only) |
--wait | -Wait | no | Sync mode: block until Azure has cleaned up stack metadata. Matches the CI workflow. Slower (~3-4×) but fully deterministic. |
--poll-timeout <sec> | -PollTimeout <sec> | no | Fast-mode timeout per managed RG poll (default 600s) |
Failure modes
| Symptom | Likely cause | Recovery |
state.json missing | Deployment never reached the state-write phase, or was hand-edited | Re-deploy (idempotent on stack name) then destroy, OR delete the .azure/deployments/<id>/ folder if Azure has nothing |
Stack out of sync despite --bypass-stack-out-of-sync-error | Old CLI version | Upgrade az to ≥ 2.59 |
| Key Vault purge fails | Vault is purge-protected (purgeProtected: true) | Expected — wait 7-90 days for soft-delete window to expire, or purge manually after disabling protection |
Cannot delete resource group …/InUseSubnetCannotBeDeleted | A resource outside the stack references one inside (e.g. external subnet peered to a deleted VNet) | Inspect externalReferences[] in state.json; remove the reference and rerun |
Related
azure-stack-deploy— the matching deploy skill (writes thestate.jsonthis skill consumes)azure-drift-detector— check for unmanaged drift BEFORE destroyazure-resource-visualizer— visualize what's in the stack before tearing it down
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

