|
#!/bin/bash |
|
# Delete Cloudflare Pages/Workers deployments via API |
|
# Usage: ./delete-cf-deployments.sh --project=xxx --account=xxx --token=xxx [--limit=N] [--keep=N] |
|
|
|
PROJECT="" |
|
ACCOUNT_ID="" |
|
TOKEN="" |
|
LIMIT="" |
|
KEEP="" |
|
|
|
for arg in "$@"; do |
|
case $arg in |
|
--project=*) PROJECT="${arg#*=}" ;; |
|
--account=*) ACCOUNT_ID="${arg#*=}" ;; |
|
--token=*) TOKEN="${arg#*=}" ;; |
|
--limit=*) LIMIT="${arg#*=}" ;; |
|
--keep=*) KEEP="${arg#*=}" ;; |
|
esac |
|
done |
|
|
|
if [ -z "$PROJECT" ] || [ -z "$ACCOUNT_ID" ] || [ -z "$TOKEN" ]; then |
|
echo "Usage: $0 --project=<name> --account=<id> --token=<api-token> [options]" |
|
echo "" |
|
echo "Required:" |
|
echo " --project=NAME Cloudflare Pages project name" |
|
echo " --account=ID Your Cloudflare account ID" |
|
echo " --token=TOKEN Cloudflare API token" |
|
echo "" |
|
echo "Options:" |
|
echo " --limit=N Delete only N deployments (for testing)" |
|
echo " --keep=N Keep the last N deployments (cleanup mode)" |
|
echo "" |
|
echo "Examples:" |
|
echo " $0 --project=my-site --account=abc123 --token=xyz789 --limit=3" |
|
echo " $0 --project=my-site --account=abc123 --token=xyz789 --keep=10" |
|
echo " $0 --project=my-site --account=abc123 --token=xyz789" |
|
echo "" |
|
echo "Get API token: Cloudflare Dashboard → My Profile → API Tokens" |
|
echo " → Create Token → Edit Cloudflare Pages" |
|
echo "" |
|
echo "Get Account ID: Cloudflare Dashboard → any site → Overview" |
|
echo " → right sidebar under 'API'" |
|
exit 1 |
|
fi |
|
|
|
API="https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/pages/projects/$PROJECT" |
|
|
|
echo "Deleting deployments for: $PROJECT" |
|
[ -n "$LIMIT" ] && echo "Limit: $LIMIT" |
|
[ -n "$KEEP" ] && echo "Keeping last: $KEEP deployments" |
|
echo "" |
|
|
|
COUNT=0 |
|
PAGE=1 |
|
|
|
# For --keep mode, we need to skip the first N deployments |
|
# API returns deployments sorted by date (newest first) |
|
# So we paginate past the ones we want to keep |
|
|
|
if [ -n "$KEEP" ]; then |
|
# Calculate which page to start from |
|
PER_PAGE=25 |
|
SKIP_PAGES=$((KEEP / PER_PAGE)) |
|
SKIP_IN_PAGE=$((KEEP % PER_PAGE)) |
|
PAGE=$((SKIP_PAGES + 1)) |
|
echo "Skipping first $KEEP deployments (starting from page $PAGE)..." |
|
echo "" |
|
fi |
|
|
|
while true; do |
|
# Fetch deployments with pagination |
|
RESPONSE=$(curl -s "$API/deployments?per_page=25&page=$PAGE" \ |
|
-H "Authorization: Bearer $TOKEN") |
|
|
|
IDS=$(echo "$RESPONSE" | jq -r '.result[].id // empty' 2>/dev/null) |
|
|
|
if [ -z "$IDS" ]; then |
|
echo "No more deployments." |
|
break |
|
fi |
|
|
|
# Convert to array |
|
IDS_ARRAY=($IDS) |
|
START_INDEX=0 |
|
|
|
# On the first page in --keep mode, skip partial entries |
|
if [ -n "$KEEP" ] && [ "$PAGE" -eq "$((SKIP_PAGES + 1))" ] && [ "$SKIP_IN_PAGE" -gt 0 ]; then |
|
START_INDEX=$SKIP_IN_PAGE |
|
echo "Skipping first $SKIP_IN_PAGE on this page..." |
|
fi |
|
|
|
for ((i=START_INDEX; i<${#IDS_ARRAY[@]}; i++)); do |
|
ID="${IDS_ARRAY[$i]}" |
|
|
|
echo "Deleting $ID..." |
|
curl -s -X DELETE "$API/deployments/$ID?force=true" \ |
|
-H "Authorization: Bearer $TOKEN" > /dev/null |
|
|
|
COUNT=$((COUNT + 1)) |
|
|
|
if [ -n "$LIMIT" ] && [ "$COUNT" -ge "$LIMIT" ]; then |
|
echo "" |
|
echo "Reached limit of $LIMIT. Deleted $COUNT deployments." |
|
exit 0 |
|
fi |
|
|
|
sleep 0.3 |
|
done |
|
|
|
# In normal mode (no --keep), always fetch page 1 since we're deleting |
|
# In --keep mode, move to next page |
|
if [ -z "$KEEP" ]; then |
|
PAGE=1 |
|
else |
|
PAGE=$((PAGE + 1)) |
|
fi |
|
done |
|
|
|
echo "" |
|
echo "Done! Deleted $COUNT deployments." |
|
echo "" |
|
echo "To delete the project entirely, run:" |
|
echo " npx wrangler pages project delete $PROJECT" |
|
echo "" |
|
echo "Or delete it via Cloudflare Dashboard:" |
|
echo " Workers & Pages → $PROJECT → Settings → Delete project" |