Tools for the Atmosphere tools.slices.network
quickslice atproto html
at main 233 lines 6.0 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, keeps others as-is) 64upload_file() { 65 local local_path="$1" 66 local filename 67 filename=$(basename "$local_path") 68 # Strip .html extension for clean URLs, keep other extensions 69 local remote_name 70 if [[ "$filename" == *.html ]]; then 71 remote_name="${filename%.html}" 72 else 73 remote_name="$filename" 74 fi 75 76 if [ "$VERBOSE" = true ]; then 77 echo " Uploading: ${filename} -> ${remote_name}" 78 fi 79 80 if [ "$DRY_RUN" = true ]; then 81 ((UPLOADED++)) 82 return 0 83 fi 84 85 local response 86 local http_code 87 88 # Determine content type 89 local content_type="text/html" 90 if [[ "$filename" == *.js ]]; then 91 content_type="application/javascript" 92 fi 93 94 response=$(curl -s -w "\n%{http_code}" -X PUT \ 95 "${STORAGE_URL}/${remote_name}" \ 96 -H "AccessKey: ${BUNNY_STORAGE_PASSWORD}" \ 97 -H "Content-Type: ${content_type}" \ 98 --data-binary "@${local_path}") 99 100 http_code=$(echo "$response" | tail -n1) 101 102 if [[ "$http_code" =~ ^2 ]]; then 103 ((UPLOADED++)) 104 return 0 105 else 106 echo -e "${RED}Failed to upload ${filename}: HTTP ${http_code}${NC}" 107 echo "$response" | head -n -1 108 return 1 109 fi 110} 111 112# List all files in remote storage 113list_remote_files() { 114 local response 115 response=$(curl -s -X GET "${STORAGE_URL}/" \ 116 -H "AccessKey: ${BUNNY_STORAGE_PASSWORD}" \ 117 -H "Accept: application/json") 118 119 echo "$response" | jq -r '.[] | select(.IsDirectory == false) | .ObjectName' 2>/dev/null 120} 121 122# Delete a single file from remote 123delete_file() { 124 local remote_name="$1" 125 126 if [ "$VERBOSE" = true ]; then 127 echo " Deleting: ${remote_name}" 128 fi 129 130 if [ "$DRY_RUN" = true ]; then 131 ((DELETED++)) 132 return 0 133 fi 134 135 local http_code 136 http_code=$(curl -s -o /dev/null -w "%{http_code}" -X DELETE \ 137 "${STORAGE_URL}/${remote_name}" \ 138 -H "AccessKey: ${BUNNY_STORAGE_PASSWORD}") 139 140 if [[ "$http_code" =~ ^2 ]]; then 141 ((DELETED++)) 142 return 0 143 else 144 echo -e "${RED}Failed to delete ${remote_name}: HTTP ${http_code}${NC}" 145 return 1 146 fi 147} 148 149# Purge pull zone cache 150purge_cache() { 151 echo "Purging CDN cache..." 152 153 if [ "$DRY_RUN" = true ]; then 154 echo -e "${YELLOW} Would purge pull zone ${BUNNY_PULLZONE_ID}${NC}" 155 return 0 156 fi 157 158 local http_code 159 http_code=$(curl -s -o /dev/null -w "%{http_code}" -X POST \ 160 "https://api.bunny.net/pullzone/${BUNNY_PULLZONE_ID}/purgeCache" \ 161 -H "AccessKey: ${BUNNY_API_KEY}" \ 162 -H "Content-Type: application/json") 163 164 if [[ "$http_code" =~ ^2 ]]; then 165 echo -e "${GREEN} Cache purged successfully${NC}" 166 return 0 167 else 168 echo -e "${RED} Failed to purge cache: HTTP ${http_code}${NC}" 169 return 1 170 fi 171} 172 173# ============================================ 174# MAIN EXECUTION 175# ============================================ 176 177# Find all .html and .js files in root directory 178DEPLOY_FILES=$(find . -maxdepth 1 \( -name "*.html" -o -name "*.js" \) -type f 2>/dev/null) 179 180if [ -z "$DEPLOY_FILES" ]; then 181 echo -e "${YELLOW}No .html or .js files found in current directory${NC}" 182 exit 0 183fi 184 185# Build list of expected remote names (without .html extension) 186LOCAL_NAMES_LIST=$(mktemp) 187trap "rm -f $LOCAL_NAMES_LIST" EXIT 188 189# Step 1: Upload all local files 190echo "Uploading files..." 191echo "$DEPLOY_FILES" | while read -r file; do 192 filename=$(basename "$file") 193 if [[ "$filename" == *.html ]]; then 194 remote_name="${filename%.html}" 195 else 196 remote_name="$filename" 197 fi 198 echo "$remote_name" >> "$LOCAL_NAMES_LIST" 199 upload_file "$file" 200done 201 202echo "" 203 204# Step 2: Delete orphaned remote files 205echo "Checking for orphaned files..." 206REMOTE_FILES=$(list_remote_files) 207 208if [ -n "$REMOTE_FILES" ]; then 209 while IFS= read -r remote_file; do 210 if [ -z "$remote_file" ]; then 211 continue 212 fi 213 if ! grep -qxF "$remote_file" "$LOCAL_NAMES_LIST"; then 214 delete_file "$remote_file" 215 fi 216 done <<< "$REMOTE_FILES" 217fi 218 219echo "" 220 221# Step 3: Purge CDN cache 222purge_cache 223 224# Summary 225echo "" 226echo "========================================" 227echo -e "${GREEN}Deploy complete!${NC}" 228echo " Uploaded: ${UPLOADED} files" 229echo " Deleted: ${DELETED} files" 230if [ "$DRY_RUN" = true ]; then 231 echo -e "${YELLOW} (DRY RUN - no actual changes made)${NC}" 232fi 233echo "========================================"