Tools for the Atmosphere tools.slices.network
quickslice atproto html
at feat/lexicon-validator 218 lines 5.6 kB view raw
1#!/usr/bin/env bash 2set -euo pipefail 3 4# Bunny CDN Deploy Script for tools.slices.network 5# Syncs .html files to Bunny Storage with clean URLs (no .html extension) 6 7# Colors for output 8RED='\033[0;31m' 9GREEN='\033[0;32m' 10YELLOW='\033[1;33m' 11NC='\033[0m' # No Color 12 13# Counters 14UPLOADED=0 15DELETED=0 16 17# Parse arguments 18DRY_RUN=false 19VERBOSE=false 20 21while [[ $# -gt 0 ]]; do 22 case $1 in 23 --dry-run) 24 DRY_RUN=true 25 shift 26 ;; 27 --verbose|-v) 28 VERBOSE=true 29 shift 30 ;; 31 *) 32 echo -e "${RED}Unknown option: $1${NC}" 33 exit 1 34 ;; 35 esac 36done 37 38# Load .env file if it exists 39if [ -f .env ]; then 40 set -a 41 source .env 42 set +a 43fi 44 45# Required environment variables 46: "${BUNNY_API_KEY:?BUNNY_API_KEY environment variable is required}" 47: "${BUNNY_STORAGE_PASSWORD:?BUNNY_STORAGE_PASSWORD environment variable is required}" 48: "${BUNNY_STORAGE_ZONE:?BUNNY_STORAGE_ZONE environment variable is required}" 49: "${BUNNY_STORAGE_HOST:?BUNNY_STORAGE_HOST environment variable is required}" 50: "${BUNNY_PULLZONE_ID:?BUNNY_PULLZONE_ID environment variable is required}" 51 52# Configuration 53STORAGE_URL="https://${BUNNY_STORAGE_HOST}/${BUNNY_STORAGE_ZONE}" 54 55echo "Bunny CDN Deploy - tools.slices.network" 56echo "========================================" 57echo "Storage Zone: ${BUNNY_STORAGE_ZONE}" 58if [ "$DRY_RUN" = true ]; then 59 echo -e "${YELLOW}DRY RUN MODE - No changes will be made${NC}" 60fi 61echo "" 62 63# Upload a single file (strips .html extension for clean URLs) 64upload_file() { 65 local local_path="$1" 66 local filename 67 filename=$(basename "$local_path") 68 # Strip .html extension for clean URLs 69 local remote_name="${filename%.html}" 70 71 if [ "$VERBOSE" = true ]; then 72 echo " Uploading: ${filename} -> ${remote_name}" 73 fi 74 75 if [ "$DRY_RUN" = true ]; then 76 ((UPLOADED++)) 77 return 0 78 fi 79 80 local response 81 local http_code 82 83 response=$(curl -s -w "\n%{http_code}" -X PUT \ 84 "${STORAGE_URL}/${remote_name}" \ 85 -H "AccessKey: ${BUNNY_STORAGE_PASSWORD}" \ 86 -H "Content-Type: text/html" \ 87 --data-binary "@${local_path}") 88 89 http_code=$(echo "$response" | tail -n1) 90 91 if [[ "$http_code" =~ ^2 ]]; then 92 ((UPLOADED++)) 93 return 0 94 else 95 echo -e "${RED}Failed to upload ${filename}: HTTP ${http_code}${NC}" 96 echo "$response" | head -n -1 97 return 1 98 fi 99} 100 101# List all files in remote storage 102list_remote_files() { 103 local response 104 response=$(curl -s -X GET "${STORAGE_URL}/" \ 105 -H "AccessKey: ${BUNNY_STORAGE_PASSWORD}" \ 106 -H "Accept: application/json") 107 108 echo "$response" | jq -r '.[] | select(.IsDirectory == false) | .ObjectName' 2>/dev/null 109} 110 111# Delete a single file from remote 112delete_file() { 113 local remote_name="$1" 114 115 if [ "$VERBOSE" = true ]; then 116 echo " Deleting: ${remote_name}" 117 fi 118 119 if [ "$DRY_RUN" = true ]; then 120 ((DELETED++)) 121 return 0 122 fi 123 124 local http_code 125 http_code=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \ 126 "${STORAGE_URL}/${remote_name}" \ 127 -H "AccessKey: ${BUNNY_STORAGE_PASSWORD}") 128 129 if [[ "$http_code" =~ ^2 ]]; then 130 ((DELETED++)) 131 return 0 132 else 133 echo -e "${RED}Failed to delete ${remote_name}: HTTP ${http_code}${NC}" 134 return 1 135 fi 136} 137 138# Purge pull zone cache 139purge_cache() { 140 echo "Purging CDN cache..." 141 142 if [ "$DRY_RUN" = true ]; then 143 echo -e "${YELLOW} Would purge pull zone ${BUNNY_PULLZONE_ID}${NC}" 144 return 0 145 fi 146 147 local http_code 148 http_code=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ 149 "https://api.bunny.net/pullzone/${BUNNY_PULLZONE_ID}/purgeCache" \ 150 -H "AccessKey: ${BUNNY_API_KEY}" \ 151 -H "Content-Type: application/json") 152 153 if [[ "$http_code" =~ ^2 ]]; then 154 echo -e "${GREEN} Cache purged successfully${NC}" 155 return 0 156 else 157 echo -e "${RED} Failed to purge cache: HTTP ${http_code}${NC}" 158 return 1 159 fi 160} 161 162# ============================================ 163# MAIN EXECUTION 164# ============================================ 165 166# Find all .html files in root directory 167HTML_FILES=$(find . -maxdepth 1 -name "*.html" -type f 2>/dev/null) 168 169if [ -z "$HTML_FILES" ]; then 170 echo -e "${YELLOW}No .html files found in current directory${NC}" 171 exit 0 172fi 173 174# Build list of expected remote names (without .html extension) 175LOCAL_NAMES_LIST=$(mktemp) 176trap "rm -f $LOCAL_NAMES_LIST" EXIT 177 178# Step 1: Upload all local .html files 179echo "Uploading files..." 180echo "$HTML_FILES" | while read -r file; do 181 filename=$(basename "$file") 182 remote_name="${filename%.html}" 183 echo "$remote_name" >> "$LOCAL_NAMES_LIST" 184 upload_file "$file" 185done 186 187echo "" 188 189# Step 2: Delete orphaned remote files 190echo "Checking for orphaned files..." 191REMOTE_FILES=$(list_remote_files) 192 193if [ -n "$REMOTE_FILES" ]; then 194 while IFS= read -r remote_file; do 195 if [ -z "$remote_file" ]; then 196 continue 197 fi 198 if ! grep -qxF "$remote_file" "$LOCAL_NAMES_LIST"; then 199 delete_file "$remote_file" 200 fi 201 done <<< "$REMOTE_FILES" 202fi 203 204echo "" 205 206# Step 3: Purge CDN cache 207purge_cache 208 209# Summary 210echo "" 211echo "========================================" 212echo -e "${GREEN}Deploy complete!${NC}" 213echo " Uploaded: ${UPLOADED} files" 214echo " Deleted: ${DELETED} files" 215if [ "$DRY_RUN" = true ]; then 216 echo -e "${YELLOW} (DRY RUN - no actual changes made)${NC}" 217fi 218echo "========================================"