Skip to content

Docker Hub prune

Docker Hub prune #28

---
name: Docker Hub prune
'on':
workflow_dispatch:
schedule:
- cron: 0 0 * * 0 # weekly on Sundays
jobs:
prune:
if: github.repository == 'netbrain/zwift'
runs-on: ubuntu-latest
env:
REPO: netbrain/zwift
MAX_AGE_DAYS: 365
steps:
- name: Prune old Docker Hub tags
run: |
# Authenticate and get JWT token
token="$(curl -sf -X POST "https://hub.docker.com/v2/users/login" \
-H "Content-Type: application/json" \
-d "{\"username\":\"${{ secrets.DOCKERHUB_USERNAME }}\",\"password\":\"${{ secrets.DOCKERHUB_TOKEN }}\"}" \
| jq -r '.token')"
if [[ -z ${token} ]] || [[ ${token} == "null" ]]; then
echo "::error::Failed to authenticate with Docker Hub"
exit 1
fi
cutoff="$(date -u -d "-${MAX_AGE_DAYS} days" +%s)"
deleted=0
page_size=100
page=1
echo "Pruning tags older than ${MAX_AGE_DAYS} days (before $(date -u -d "-${MAX_AGE_DAYS} days" +%Y-%m-%d))"
while true; do
response="$(curl -sf "https://hub.docker.com/v2/repositories/${REPO}/tags/?page_size=${page_size}&page=${page}")"
tags="$(echo "${response}" | jq -r '.results // []')"
count="$(echo "${tags}" | jq 'length')"
if [[ ${count} -eq 0 ]]; then
break
fi
for i in $(seq 0 $((count - 1))); do
tag="$(echo "${tags}" | jq -r ".[${i}].name")"
last_updated="$(echo "${tags}" | jq -r ".[${i}].last_updated")"
tag_ts="$(date -u -d "${last_updated}" +%s)"
# Never delete the latest tag
if [[ ${tag} == "latest" ]]; then
echo "Skipping: ${tag} (protected)"
continue
fi
if [[ ${tag_ts} -lt ${cutoff} ]]; then
echo "Deleting: ${tag} (last updated: ${last_updated})"
http_code="$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \
"https://hub.docker.com/v2/repositories/${REPO}/tags/${tag}/" \
-H "Authorization: Bearer ${token}")"
if [[ ${http_code} -eq 204 ]]; then
((deleted++)) || true
else
echo "::warning::Failed to delete tag ${tag} (HTTP ${http_code})"
fi
else
echo "Keeping: ${tag} (last updated: ${last_updated})"
fi
done
next="$(echo "${response}" | jq -r '.next // empty')"
if [[ -z ${next} ]]; then
break
fi
((page++)) || true
done
echo "Pruned ${deleted} tag(s)"