Spaces:
Running
Running
Download scripts/deploy.sh from IsabellePai/pai_pet: direct link, hf CLI and curl.
- Browser
- Download file 4.36 kB
-
https://huggingface.co/spaces/IsabellePai/pai_pet/resolve/main/scripts/deploy.sh
- Command line
-
hf download hf://spaces/IsabellePai/pai_pet/scripts/deploy.sh
-
curl -L -o deploy.sh https://huggingface.co/spaces/IsabellePai/pai_pet/resolve/main/scripts/deploy.sh
4.36 kB
| # Deploy Pai Pet in one go: push to the Hugging Face Space, update the app on | |
| # the robot, and (re)start it. | |
| # | |
| # Usage (from anywhere in the repo): | |
| # ./scripts/deploy.sh | |
| # | |
| # The robot is found automatically. To point it at a specific address: | |
| # ROBOT=192.168.1.209 ./scripts/deploy.sh | |
| set -euo pipefail | |
| APP=pai_pet | |
| SPACE=IsabellePai/pai_pet | |
| FALLBACK_IP=192.168.1.209 # last known address of the robot | |
| cd "$(git rev-parse --show-toplevel)" | |
| say() { printf '\n\033[1m==> %s\033[0m\n' "$*"; } | |
| fail() { printf '\n\033[31mERROR: %s\033[0m\n' "$*" >&2; exit 1; } | |
| json() { python3 -c "import sys,json; d=json.load(sys.stdin); print($1)"; } | |
| # --- 1. Uncommitted changes are not deployed: warn --------------------------- | |
| if [ -n "$(git status --porcelain)" ]; then | |
| say "You have changes that are not committed (they will NOT be deployed):" | |
| git status --short | |
| read -r -p "Continue anyway? [y/N] " answer | |
| [[ "$answer" =~ ^[yY]$ ]] || exit 1 | |
| fi | |
| # --- 2. Push to the Space ---------------------------------------------------- | |
| say "Pushing to Hugging Face ($SPACE)" | |
| git push origin main | |
| HEAD_SHA=$(git rev-parse HEAD) | |
| SPACE_SHA=$(curl -s -m 15 "https://huggingface.co/api/spaces/$SPACE" | json "d.get('sha','')" || true) | |
| [ "$SPACE_SHA" = "$HEAD_SHA" ] || fail "The Space is on ${SPACE_SHA:0:7}, but your code is on ${HEAD_SHA:0:7}. Did the push work?" | |
| echo "Space is on ${HEAD_SHA:0:7}" | |
| # --- 3. Find the robot --------------------------------------------------------- | |
| say "Looking for the robot" | |
| robot_ok() { curl -s -m 4 "http://$1:8000/api/daemon/status" >/dev/null; } | |
| HOST="${ROBOT:-}" | |
| if [ -z "$HOST" ]; then | |
| if robot_ok reachy-mini.local; then | |
| HOST=reachy-mini.local | |
| elif command -v powershell.exe >/dev/null; then | |
| # WSL can't resolve .local names, but Windows can. | |
| HOST=$(timeout 20 powershell.exe -NoProfile -Command \ | |
| "(Resolve-DnsName reachy-mini.local -Type A -ErrorAction SilentlyContinue | Select-Object -First 1).IPAddress" \ | |
| 2>/dev/null | tr -d '\r' || true) | |
| fi | |
| if [ -z "$HOST" ] || ! robot_ok "$HOST"; then HOST=$FALLBACK_IP; fi | |
| fi | |
| robot_ok "$HOST" || fail "Can't reach the robot at $HOST. Is it on, and on the same Wi-Fi? (Or set ROBOT=<ip>)" | |
| API="http://$HOST:8000/api/apps" | |
| echo "Robot found at $HOST" | |
| # --- 4. Stop the app if it is running ---------------------------------------- | |
| RUNNING=$(curl -s -m 8 "$API/current-app-status" | json "(d or {}).get('info',{}).get('name','')") | |
| if [ -n "$RUNNING" ]; then | |
| say "Stopping $RUNNING" | |
| curl -s -m 20 -X POST "$API/stop-current-app" >/dev/null | |
| fi | |
| # --- 5. Update (or install, the first time) ---------------------------------- | |
| INSTALLED=$(curl -s -m 8 "$API/list-available/installed" | json "'$APP' in [a['name'] for a in d]") | |
| if [ "$INSTALLED" = "True" ]; then | |
| say "Updating $APP on the robot" | |
| JOB=$(curl -s -m 30 -X POST "$API/update/$APP" | json "d['job_id']") | |
| else | |
| say "Installing $APP on the robot" | |
| JOB=$(curl -s -m 30 -X POST "$API/install" -H "Content-Type: application/json" \ | |
| -d "{\"name\": \"$APP\", \"source_kind\": \"hf_space\", \"url\": \"https://huggingface.co/spaces/$SPACE\"}" | json "d['job_id']") | |
| fi | |
| STATUS="" | |
| for _ in $(seq 1 60); do # up to ~3 minutes | |
| STATUS=$(curl -s -m 8 "$API/job-status/$JOB" | json "d['status']" || true) | |
| [ "$STATUS" = done ] || [ "$STATUS" = failed ] && break | |
| printf '.'; sleep 3 | |
| done | |
| echo | |
| if [ "$STATUS" != done ]; then | |
| curl -s -m 8 "$API/job-status/$JOB" | json "'\n'.join(d.get('logs',[])[-15:])" || true | |
| fail "Update did not finish (status: ${STATUS:-unknown})" | |
| fi | |
| ROBOT_SHA=$(curl -s -m 30 "$API/check-updates" | json \ | |
| "next((a['installed_sha'] for a in d['apps_with_updates'] if a['app_name']=='$APP'), '$HEAD_SHA')") | |
| [ "$ROBOT_SHA" = "$HEAD_SHA" ] || fail "The robot installed ${ROBOT_SHA:0:7}, expected ${HEAD_SHA:0:7}" | |
| echo "Robot has ${HEAD_SHA:0:7}" | |
| # --- 6. Start it ------------------------------------------------------------- | |
| say "Starting $APP (the robot will move)" | |
| curl -s -m 20 -X POST "$API/start-app/$APP" >/dev/null | |
| STATE="" | |
| for _ in $(seq 1 15); do | |
| STATE=$(curl -s -m 8 "$API/current-app-status" | json "(d or {}).get('state','')" || true) | |
| [ "$STATE" = running ] && break | |
| sleep 1 | |
| done | |
| [ "$STATE" = running ] || fail "$APP did not start (state: ${STATE:-not running})" | |
| say "Done: $APP ${HEAD_SHA:0:7} is running on the robot" | |