Spaces:
Running
Running
File size: 5,147 Bytes
07aa9a2 | 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 | #!/bin/bash
# ============================================================
# HF-VPS β Clean Deployment Script
#
# Enforces the mandatory workflow:
# local changes β GitHub (source of truth) β HF Space
#
# Usage:
# bash scripts/deploy.sh # standard clean deploy
# bash scripts/deploy.sh --factory # factory reset (full Docker rebuild, no cache)
#
# Requirements:
# - .env.local must exist with HF_TOKEN set
# - Both git remotes must be configured:
# origin β https://github.com/luizcireno-crypto/HF-SaaS.git
# hf β https://huggingface.co/spaces/lulavc/HF-SaaS.git
#
# What this does:
# 1. Validates environment and git state
# 2. Pushes to GitHub (origin/main)
# 3. Force-pushes to HF Space (ensures no stale git refs or old files)
# 4. Optionally triggers a factory restart (full clean Docker rebuild)
# 5. Monitors build status until RUNNING or ERROR
# ============================================================
set -e
# ---- Load credentials from .env.local ----
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$(dirname "$SCRIPT_DIR")"
ENV_FILE="$ROOT_DIR/.env.local"
if [ ! -f "$ENV_FILE" ]; then
echo "[deploy] ERROR: .env.local not found at $ROOT_DIR/.env.local"
echo "[deploy] Create it with: HF_TOKEN=hf_..."
exit 1
fi
source "$ENV_FILE"
if [ -z "$HF_TOKEN" ]; then
echo "[deploy] ERROR: HF_TOKEN is not set in .env.local"
exit 1
fi
HF_USERNAME="${HF_USERNAME:-lulavc}"
HF_SPACE="${HF_SPACE:-HF-SaaS}"
FACTORY_RESET=false
# ---- Parse flags ----
for arg in "$@"; do
case $arg in
--factory) FACTORY_RESET=true ;;
esac
done
echo ""
echo "============================================"
echo " HF-VPS Clean Deployment"
echo " Space: $HF_USERNAME/$HF_SPACE"
if [ "$FACTORY_RESET" = true ]; then
echo " Mode: Factory Reset (full Docker rebuild)"
else
echo " Mode: Standard (incremental Docker rebuild)"
fi
echo "============================================"
echo ""
# ---- Step 1: Validate git state ----
cd "$ROOT_DIR"
BRANCH=$(git rev-parse --abbrev-ref HEAD)
if [ "$BRANCH" != "main" ]; then
echo "[deploy] ERROR: Not on main branch (currently on: $BRANCH)"
echo "[deploy] Switch to main before deploying."
exit 1
fi
if ! git diff-index --quiet HEAD --; then
echo "[deploy] ERROR: Uncommitted changes detected."
echo "[deploy] Commit all changes before deploying."
git status --short
exit 1
fi
echo "[deploy] Git state OK β branch: main, working tree clean"
# ---- Step 2: Push to GitHub (source of truth) ----
echo "[deploy] Pushing to GitHub (origin/main)..."
git push origin main
echo "[deploy] GitHub updated β"
# ---- Step 3: Force-push to HF Space (clean git state) ----
echo "[deploy] Force-pushing to HF Space (no stale refs or old files)..."
git push hf main --force
echo "[deploy] HF Space git updated β"
# ---- Step 4: Factory reset (optional β busts Docker cache) ----
if [ "$FACTORY_RESET" = true ]; then
echo "[deploy] Triggering factory restart (clean Docker rebuild, no cache)..."
RESTART_RESP=$(curl -s -X POST \
"https://huggingface.co/api/spaces/$HF_USERNAME/$HF_SPACE/restart?factory=true" \
-H "Authorization: Bearer $HF_TOKEN")
echo "[deploy] Factory restart triggered: $RESTART_RESP"
fi
# ---- Step 5: Monitor build status ----
echo ""
echo "[deploy] Monitoring build status..."
echo "[deploy] Logs: https://huggingface.co/spaces/$HF_USERNAME/$HF_SPACE?logs=container"
echo ""
MAX_WAIT=300 # 5 minutes max
INTERVAL=10
ELAPSED=0
while [ $ELAPSED -lt $MAX_WAIT ]; do
STAGE=$(curl -s \
"https://huggingface.co/api/spaces/$HF_USERNAME/$HF_SPACE" \
-H "Authorization: Bearer $HF_TOKEN" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('runtime',{}).get('stage','unknown'))" 2>/dev/null)
ERROR=$(curl -s \
"https://huggingface.co/api/spaces/$HF_USERNAME/$HF_SPACE" \
-H "Authorization: Bearer $HF_TOKEN" \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d.get('runtime',{}).get('errorMessage',''))" 2>/dev/null)
printf "[deploy] [%3ds] Stage: %s\n" "$ELAPSED" "$STAGE"
if [ "$STAGE" = "RUNNING" ]; then
echo ""
echo "============================================"
echo " Deployment successful!"
echo " Space: https://huggingface.co/spaces/$HF_USERNAME/$HF_SPACE"
echo " App: https://$HF_USERNAME-$(echo $HF_SPACE | tr '[:upper:]' '[:lower:]').hf.space"
echo "============================================"
exit 0
fi
if [ "$STAGE" = "ERROR" ] || [ "$STAGE" = "BUILD_ERROR" ]; then
echo ""
echo "[deploy] ERROR: Build failed!"
echo "[deploy] Error: $ERROR"
echo "[deploy] Check logs: https://huggingface.co/spaces/$HF_USERNAME/$HF_SPACE?logs=container"
exit 1
fi
sleep $INTERVAL
ELAPSED=$((ELAPSED + INTERVAL))
done
echo "[deploy] Timed out after ${MAX_WAIT}s β check logs manually:"
echo "[deploy] https://huggingface.co/spaces/$HF_USERNAME/$HF_SPACE?logs=container"
exit 1
|