File size: 4,355 Bytes
362788c
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
#!/usr/bin/env bash
# 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"