Declutter Your Azure by automating Post-PR Resource Cleanup
Maintaining a clutter-free Azure environment after Pull Request (PR) merges is crucial for developers and infrastructure personnel using Azure. This step-by-step guide introduces automated resource cleanup using the NuGet tool azure-resources-cleaner to optimize costs and enhance system efficiency efficiently. Automated post-PR has benefits extending beyond tidiness to cost optimization and improved operational efficiency.
Why does this tool exist?
When working with Azure Pipelines, you will occasionally use the reviewApp in your deployment jobs. For Kubernetes environments, this creates a resource backed by a new namespace with the given name. This was introduced in 2019. Unfortunately, Azure does not clean up these resources, and they can delay your pipelines from starting if you have many resources in your environment. I saw a delay of more than 5 minutes with just 40 PRs (1 or 2 per day for a month). These need to be cleaned up manually.
While this works for Kubernetes clusters, other resources such as Azure Static WebApps do not have this feature. See Azure/static-web-apps#497.
Sometimes, you have a whole resource group you need just for a PR and you wish to delete it once the PR is merged or closed/abandoned.
With GitHub, you can automate Azure Static WebApps environments using the official action, but other resource types require manual effort.
The azure-resources-cleaner exists to automate the process.
How does this tool work?
There is extensive documentation here. For this post, I will only pick what is necessary.
You need access to your Azure Subscription. The tool uses managed identity and will work on your machine when you have signed in using the Azure CLI, Visual Studio Code, Visual Studio, etc.
For it to find the resources to clean, they must be named using a specific pattern. Just the resources for the Pull Request. The supported naming formats are listed here.
Say you have a Pull Request #48, Azure Static WebApp environments named review-app-48, ra-48, or ra48 will be deleted. Azure Container Apps with names ending in review-app-48, ra-48, or ra48 will be removed. More on the supported resource types here.
Installation and setup
To kickstart your automated resource cleanup journey, you first need to install the azure-resources-cleaner tool from NuGet. Follow the installation instructions provided.
Once it is installed, you can access the tool using azrc. For example azrc -h or azrc βversion.
Execution
For the PR above, the tool will search through the subscriptions that it has access to when you run it.
A sample output would be:
It is good practice to limit the subscription within which it should operate if you have access to more than one.
Automating with GitHub Workflows
I found this to be the simplest way to get this done because of the awesome GitHub triggers.
With this workflow, the Azure CLI task provides the credentials that will then be used by the azure-resources-cleaner task. The workflow_dispatch trigger allows you to manually trigger the cleanup should there be an issue such as expired credentials.
Automating for Azure DevOps
This one gets a bit tricky, to be honest, because there is no way to trigger pipelines when a Pull Request status changes. Instead, for years I have had a ServiceHook that listens to git.pullrequest.updated events then handles it. Thankfully, this is not too hard to set up, and we can use an Azure ContainerApp so that we only pay for what we use.
The setup for the listener app is documented here and that for service hooks and subscriptions is here.
How to deploy a review app, you asked?
For Azure Static WebApps in Azure Repos, here's an example:
That one was trivial let us try one with Bicep which is where I get to do lots more. We need a parameter (reviewAppNameSuffix) that we assign for pull requests only.
Your pipeline:
Unfortunately, since we moved from managing Kubernetes clusters to using Azure ContainerApps, I forgot how to use reviewApp and create dynamic namespaces. If you need help you can reach out to me and I can help you out.
Now the bicep file, we deploy two apps
The same bicep can be used but this time with GitHub Workflows:
Conclusion
With this setup, I have ensured that for all my clients, I can validate pull requests before they are merged. I have an additional PR comment step that allows me to get a preview URL that I can share with my team or client for feedback. Fewer bugs make it to production or result in the "works on my machine" kind of scenario once deployed to production.
I do hope this helps you create and maintain preview environments like Vercel and other providers while saving on costs.
If you like my work, share, and feel free to sponsor me.