-
Notifications
You must be signed in to change notification settings - Fork 2
166 lines (147 loc) · 6.92 KB
/
cleanup-preview-dns.yml
File metadata and controls
166 lines (147 loc) · 6.92 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
name: Cleanup preview DNS records
on:
# Run when branches are deleted
delete:
# Run when PRs are closed (merged or abandoned)
pull_request:
types: [closed]
# Weekly cleanup for any orphaned records
schedule:
- cron: '0 3 * * 0' # Sunday 3am UTC
workflow_dispatch:
jobs:
cleanup:
runs-on: ubuntu-latest
# Only run for branch deletions (not tag deletions)
if: github.event_name != 'delete' || github.event.ref_type == 'branch'
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Delete preview domain
if: github.event_name == 'pull_request' || github.event_name == 'delete'
env:
CF_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CF_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CF_ZONE_ID: ${{ secrets.CLOUDFLARE_ZONE_ID }}
run: |
if [ -z "$CF_ZONE_ID" ] || [ -z "$CF_API_TOKEN" ] || [ -z "$CF_ACCOUNT_ID" ]; then
echo "::warning::Cloudflare secrets not fully configured, skipping"
exit 0
fi
# Determine branch name based on event type
if [ "${{ github.event_name }}" = "pull_request" ]; then
BRANCH=$(echo "${{ github.head_ref }}" | tr '/' '-' | tr '[:upper:]' '[:lower:]' | cut -c1-28)
else
BRANCH=$(echo "${{ github.event.ref }}" | tr '/' '-' | tr '[:upper:]' '[:lower:]' | cut -c1-28)
fi
FQDN="${BRANCH}-demo.osc.earth"
PROJECT="osa-demo"
# Skip protected branches
if [ "$BRANCH" = "main" ] || [ "$BRANCH" = "develop" ]; then
echo "Skipping protected branch: ${BRANCH}"
exit 0
fi
# Remove Pages custom domain first (404 is expected if already removed)
echo "Removing Pages custom domain: ${FQDN}"
HTTP_CODE=$(curl -s -o /tmp/pages_resp.json -w "%{http_code}" -X DELETE \
"https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/pages/projects/${PROJECT}/domains/${FQDN}" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json")
if [ "$HTTP_CODE" = "200" ]; then
echo "Pages custom domain removed."
elif [ "$HTTP_CODE" = "404" ]; then
echo "Pages domain not found (already removed)."
else
echo "::warning::Failed to remove Pages domain ${FQDN} (HTTP ${HTTP_CODE})"
fi
# Then remove DNS record
echo "Looking for DNS record: ${FQDN}"
RECORDS=$(curl -sf -X GET \
"https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records?name=${FQDN}&type=CNAME" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json") || {
echo "::warning::Failed to query DNS records for ${FQDN}"
exit 0
}
RECORD_ID=$(echo "$RECORDS" | jq -r '.result[0].id // empty')
if [ -n "$RECORD_ID" ]; then
echo "Deleting DNS record: ${FQDN} (${RECORD_ID})"
if curl -sf -X DELETE \
"https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records/${RECORD_ID}" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json"; then
echo "Deleted."
else
echo "::warning::Failed to delete DNS record ${RECORD_ID} for ${FQDN}"
fi
else
echo "No DNS record found for ${FQDN}"
fi
- name: Periodic cleanup of orphaned records
if: github.event_name == 'schedule' || github.event_name == 'workflow_dispatch'
env:
CF_API_TOKEN: ${{ secrets.CLOUDFLARE_API_TOKEN }}
CF_ACCOUNT_ID: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
CF_ZONE_ID: ${{ secrets.CLOUDFLARE_ZONE_ID }}
GH_TOKEN: ${{ github.token }}
run: |
if [ -z "$CF_ZONE_ID" ] || [ -z "$CF_API_TOKEN" ] || [ -z "$CF_ACCOUNT_ID" ]; then
echo "::warning::Cloudflare secrets not fully configured, skipping"
exit 0
fi
PROJECT="osa-demo"
echo "Fetching all *-demo.osc.earth CNAME records..."
RECORDS=$(curl -sf -X GET \
"https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records?type=CNAME&per_page=100" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json") || {
echo "::error::Failed to fetch DNS records from Cloudflare"
exit 1
}
# Pre-fetch all branch names to avoid per-record API calls
# If this fails, abort to avoid accidentally deleting active records
BRANCHES=$(gh api "repos/${{ github.repository }}/branches" --paginate -q '.[].name') || {
echo "::error::Failed to list branches from GitHub API. Aborting to avoid accidental deletions."
exit 1
}
# Filter to *-demo.osc.earth records (excluding demo.osc.earth itself)
echo "$RECORDS" | jq -r '.result[] | select(.name | endswith("-demo.osc.earth")) | "\(.id) \(.name)"' | while read -r RECORD_ID FQDN; do
# Extract branch name: remove -demo.osc.earth suffix
BRANCH=$(echo "$FQDN" | sed 's/-demo\.osc\.earth$//')
# Skip protected branches
if [ "$BRANCH" = "develop" ]; then
echo "Keeping: ${FQDN} (protected branch)"
continue
fi
# Check if any branch sanitizes to this name
FOUND=false
while IFS= read -r REMOTE_BRANCH; do
SANITIZED=$(echo "$REMOTE_BRANCH" | tr '/' '-' | tr '[:upper:]' '[:lower:]' | cut -c1-28)
if [ "$SANITIZED" = "$BRANCH" ]; then
FOUND=true
break
fi
done <<< "$BRANCHES"
if [ "$FOUND" = "true" ]; then
echo "Keeping: ${FQDN} (branch exists)"
else
echo "Deleting orphaned: ${FQDN} (no matching branch)"
# Remove Pages custom domain (may not exist, log but continue)
if ! curl -sf -X DELETE \
"https://api.cloudflare.com/client/v4/accounts/${CF_ACCOUNT_ID}/pages/projects/${PROJECT}/domains/${FQDN}" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json"; then
echo "::warning::Failed to remove Pages domain ${FQDN} (may not exist)"
fi
# Remove DNS record
if curl -sf -X DELETE \
"https://api.cloudflare.com/client/v4/zones/${CF_ZONE_ID}/dns_records/${RECORD_ID}" \
-H "Authorization: Bearer ${CF_API_TOKEN}" \
-H "Content-Type: application/json"; then
echo "Deleted: ${FQDN}"
else
echo "::warning::Failed to delete DNS record ${RECORD_ID} for ${FQDN}"
fi
fi
done
echo "Cleanup complete."