刪除 CF Pages 部署
一個處理部署過多的 Python 腳本
當你嘗試刪除一個擁有超過約 100 次部署的 Pages 專案時(每次構建都算作一次部署,例如你更新了網誌中的一篇文章),你可能會遇到以下錯誤:Your project has too many deployments to be deleted, follow this guide to delete them: https://cfl.re/3CXesln

於是我叫大肥魚(Deepseek)幫我寫一個 Python 腳本,自動刪除部署,這樣我之後就可以刪除該專案。cloudflare-bulk-delete 這個 repo 已經壞了,因為 Pages API 每頁查詢的記錄上限是 25 條,而該工具每次發送 100 條記錄的查詢,導致 HTTP 400 錯誤。
python
1#!/usr/bin/env python3
2"""Bulk delete all Cloudflare Pages deployments in a project."""
3
4import os
5import sys
6import requests
7
8# Config — set these via environment variables or edit inline
9ACCOUNT_ID = os.environ.get("CLOUDFLARE_ACCOUNT_ID", "your_account_id")
10TOKEN = os.environ.get("CLOUDFLARE_API_TOKEN", "cfut_kfcCRAZYthursday")
11PROJECT = os.environ.get("CLOUDFLARE_PROJECT", "hugo")
12
13BASE = f"https://api.cloudflare.com/client/v4/accounts/{ACCOUNT_ID}/pages/projects/{PROJECT}/deployments"
14HEADERS = {"Authorization": f"Bearer {TOKEN}"}
15
16
17def fetch_all_deployment_ids():
18 """Fetch all deployment IDs across all pages."""
19 ids = []
20 page = 1
21 while True:
22 resp = requests.get(f"{BASE}?page={page}", headers=HEADERS).json()
23 if not resp["success"]:
24 print(f"Error fetching page {page}: {resp['errors']}", file=sys.stderr)
25 sys.exit(1)
26
27 ids.extend(d["id"] for d in resp["result"])
28 total_pages = resp["result_info"]["total_pages"]
29 print(f" Page {page}/{total_pages} — collected {len(ids)} total")
30
31 if page >= total_pages:
32 break
33 page += 1
34
35 return ids
36
37
38def delete_deployment(dep_id):
39 """Delete a single deployment. Returns (ok, message)."""
40 r = requests.delete(f"{BASE}/{dep_id}", headers=HEADERS)
41 data = r.json()
42 if data.get("success"):
43 return True, "OK"
44 else:
45 err = data.get("errors", [{}])[0].get("message", "unknown error")
46 return False, err
47
48
49def main():
50 print(f"=== Fetching all deployments for project '{PROJECT}' ===")
51 ids = fetch_all_deployment_ids()
52 print(f"\n=== Deleting {len(ids)} deployments ===")
53
54 ok = 0
55 skip = 0
56 for i, dep_id in enumerate(ids, 1):
57 success, msg = delete_deployment(dep_id)
58 if success:
59 ok += 1
60 print(f" [{i}/{len(ids)}] OK {dep_id}")
61 else:
62 skip += 1
63 print(f" [{i}/{len(ids)}] SKIP ({msg}) {dep_id}")
64
65 print(f"\n=== Done! Deleted {ok}, skipped {skip}, total {len(ids)} ===")
66
67
68if __name__ == "__main__":
69 main()