Thank you for helping improve azure-resource-sweeper!
This guide walks you from a fresh clone to an open pull request.
- Development environment
- Project structure
- Code style
- Running tests
- Pull-request checklist
- Adding a new resource type
- Reporting an issue
This extension is developed with azdev — the official Azure CLI extension
development tool — and follows the azext_ package convention required by the
Azure CLI extension loader.
# 1. Clone your fork
git clone https://github.com/<your-username>/azure-resource-sweeper.git
cd azure-resource-sweeper
# 2. Create and activate a virtual environment
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
# 3. Install azdev
pip install azdev
# 4. Set up the CLI dev environment (links this repo to your local Azure CLI)
azdev setup --repo .
# 5. Register the extension with azdev
azdev extension add resource-sweeper
# 6. Verify the command group is recognised
az sweeper --helpIf azdev setup fails (e.g., no Azure CLI installed), you can install in
editable mode directly:
pip install -e ".[dev]"
python -m build
az extension add --source dist/azure_resource_sweeper-*.whlWhy
azext_prefix? The Azure CLI extension loader discovers packages via theazure.cli.extensionsentry-point group defined insetup.py. The package directory must start withazext_so the loader can findCOMMAND_LOADER_CLSin__init__.py.
azext_resource_sweeper/
├── __init__.py # COMMAND_LOADER_CLS — CLI entry point
├── commands.py # load_command_table — registers az sweeper scan / clean
├── custom.py # scan_resources() / clean_resources() — core logic
├── _params.py # load_arguments — CLI parameter definitions
└── _help.py # Help text and usage examples
- flake8 must pass:
flake8 azext_resource_sweeper/ - Type hints are required on every public function.
- Every public function must have a docstring (Google style).
- Lines must be within 90 characters.
Run before pushing:
flake8 azext_resource_sweeper/
pytest tests/unit/ -v# Unit tests only (no Azure subscription needed — all SDK calls are mocked)
pytest tests/unit/ -v
# With coverage report
pytest tests/unit/ -v --cov=azext_resource_sweeper --cov-report=term-missing
# Integration tests (requires AZURE_SUBSCRIPTION_ID env var)
export AZURE_SUBSCRIPTION_ID=<your-subscription-id>
pytest tests/integration/ -v-
flake8 azext_resource_sweeper/passes with no warnings. -
pytest tests/unit/passes and coverage did not drop. - New behavior is covered by a unit test (Azure SDKs mocked).
- Public functions have type hints and docstrings.
-
CHANGELOG.mdhas an entry under[Unreleased]. - PR description explains the why, not just the what.
Example: adding detection for unused Load Balancers.
_KQL_QUERIES["loadbalancer"] = """
Resources
| where type =~ 'microsoft.network/loadbalancers'
| where array_length(properties.backendAddressPools) == 0
| project id, name, resourceGroup, location, subscriptionId,
sku = tostring(sku.name)
"""_COST_TABLE["loadbalancer"] = 18.25 # Basic SKU flat per month_VALID_TYPES = (
"disk", "nic", "publicip", "appserviceplan", "loadbalancer", "all"
)elif rtype == "loadbalancer":
client = NetworkManagementClient(credential, sub)
client.load_balancers.begin_delete(rg, name).result()RESOURCE_TYPES = [
"disk", "nic", "publicip", "appserviceplan", "loadbalancer", "all"
]Add an example under helps["sweeper scan"] and helps["sweeper clean"].
Mock the Resource Graph query to return a fake Load Balancer row and assert
that scan_resources() returns it and clean_resources() calls the right
deletion API.
Add a row to the Supported resource types table in README.md and a
CHANGELOG.md entry under [Unreleased].
Use the GitHub issue templates:
- Bug report — unexpected error or wrong detection result
- Feature request — new resource type or capability
Open issues at: https://github.com/danakim1004au-prog/azure-resource-sweeper/issues