Skip to content

Cleanup Container Images #206

Cleanup Container Images

Cleanup Container Images #206

name: Cleanup Container Images
# Run daily at 2 AM UTC to clean up old container images
on:
schedule:
- cron: '0 2 * * *' # Daily at 2 AM UTC
workflow_dispatch: # Allow manual triggering
inputs:
dry_run:
description: 'Dry run mode (show what would be deleted without actually deleting)'
required: false
default: 'false'
type: boolean
# Set up permissions for Azure authentication
permissions:
id-token: write
contents: read
packages: write
jobs:
cleanup-images:
runs-on: ubuntu-latest
env:
AZURE_CLIENT_ID: ${{ vars.AZURE_CLIENT_ID }}
AZURE_TENANT_ID: ${{ vars.AZURE_TENANT_ID }}
AZURE_SUBSCRIPTION_ID: ${{ vars.AZURE_SUBSCRIPTION_ID }}
AZURE_ENV_NAME: ${{ vars.AZURE_ENV_NAME }}
AZURE_LOCATION: ${{ vars.AZURE_LOCATION }}
steps:
- name: Install Azure CLI
run: |
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
- name: Log in with Azure (Federated Credentials)
uses: azure/login@v2
with:
client-id: ${{ env.AZURE_CLIENT_ID }}
tenant-id: ${{ env.AZURE_TENANT_ID }}
subscription-id: ${{ env.AZURE_SUBSCRIPTION_ID }}
- name: Get Azure Container Registry Name
id: get-acr
run: |
# Get the resource group name
rg_name="rg-${{ env.AZURE_ENV_NAME }}"
echo "Resource group: $rg_name"
# Verify the resource group exists
if ! az group show --name "$rg_name" >/dev/null 2>&1; then
echo "Resource group '$rg_name' not found. Skipping cleanup."
echo "acr_name=" >> $GITHUB_OUTPUT
exit 0
fi
# Get the ACR name from the resource group
acr_name=$(az acr list --resource-group "$rg_name" --query "[0].name" --output tsv 2>/dev/null)
if [ -z "$acr_name" ] || [ "$acr_name" = "null" ]; then
echo "No Azure Container Registry found in resource group '$rg_name'."
echo "acr_name=" >> $GITHUB_OUTPUT
else
echo "Found ACR: $acr_name"
echo "acr_name=$acr_name" >> $GITHUB_OUTPUT
fi
- name: Cleanup Old Container Images
id: cleanup
run: |
acr_name="${{ steps.get-acr.outputs.acr_name }}"
dry_run="${{ github.event.inputs.dry_run || 'false' }}"
if [ -z "$acr_name" ]; then
echo "No Azure Container Registry found. Skipping cleanup."
echo "purged_count=0" >> $GITHUB_OUTPUT
exit 0
fi
echo "Starting container image cleanup for ACR: $acr_name"
echo "Retention policy: Keep 5 most recent images per repository"
# Get all repositories in the ACR
repositories=$(az acr repository list --name "$acr_name" --output tsv 2>/dev/null)
if [ -z "$repositories" ]; then
echo "No repositories found in ACR. Nothing to clean up."
echo "purged_count=0" >> $GITHUB_OUTPUT
exit 0
fi
echo "Found repositories: $(echo "$repositories" | wc -l)"
# Build the purge command with filters for each repository
PURGE_FILTERS=""
for repo in $repositories; do
PURGE_FILTERS="$PURGE_FILTERS --filter '$repo:.*'"
done
# Construct the purge command and capture the output
PURGE_CMD="acr purge $PURGE_FILTERS --ago 0d --keep 5 --untagged"
if [ "$dry_run" = "true" ]; then
PURGE_CMD="$PURGE_CMD --dry-run"
echo "🔍 DRY RUN MODE: Will show what would be deleted without actually deleting"
fi
echo "Running purge command..."
# Run the purge command and capture output
purge_output=$(az acr run \
--cmd "$PURGE_CMD" \
--registry "$acr_name" \
--timeout 3600 \
/dev/null)
exit_code=$?
# Count purged images by looking for lines with "Deleted manifest" in the output
purged_count=$(echo "$purge_output" | grep -c "Deleted manifest" || true)
echo "purged_count=$purged_count" >> $GITHUB_OUTPUT
if [ $exit_code -eq 0 ]; then
echo "✅ Cleanup process completed successfully!"
echo "🧹 Images purged: $purged_count"
else
echo "❌ Cleanup process failed with exit code $exit_code"
exit $exit_code
fi
- name: Create Summary
run: |
purged_count="${{ steps.cleanup.outputs.purged_count }}"
dry_run="${{ github.event.inputs.dry_run || 'false' }}"
echo "## Container Registry Cleanup Summary" >> $GITHUB_STEP_SUMMARY
echo "- Registry: \`${{ steps.get-acr.outputs.acr_name }}\`" >> $GITHUB_STEP_SUMMARY
echo "- Date: $(date -u '+%Y-%m-%d %H:%M:%S UTC')" >> $GITHUB_STEP_SUMMARY
if [ "$dry_run" = "true" ]; then
echo "- Mode: 🔍 **DRY RUN** (no images were actually deleted)" >> $GITHUB_STEP_SUMMARY
echo "- Images that would be purged: **$purged_count**" >> $GITHUB_STEP_SUMMARY
else
echo "- Mode: ✅ **Production Run**" >> $GITHUB_STEP_SUMMARY
echo "- Images purged: **$purged_count**" >> $GITHUB_STEP_SUMMARY
fi
echo "- Retention Policy: Keep 5 most recent images per repository" >> $GITHUB_STEP_SUMMARY