Skip to content

Improve widget footer: AI disclaimer and compact layout #70

Improve widget footer: AI disclaimer and compact layout

Improve widget footer: AI disclaimer and compact layout #70

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."