mirror of
https://github.com/gesellix/Bose-SoundTouch.git
synced 2026-08-19 00:56:16 +00:00
make screenshots was producing artifacts: a ghost Spotify pill on
ui-devices, empty Plan-card URL inputs on ui-migration with cascading
"localhost" warnings, and "Checking configuration…" placeholder text
instead of "❌ Not configured" on ui-settings. Two root causes, fixed
together so the run is deterministic again.
1. Fakespeaker too thin for the post-wizard inspect pipeline. The new
migration wizard probes /supportedURLs and reads /networkInfo and
/sources alongside the existing /info, /presets, /recents. Those
routes now exist with sanitized fixtures (deviceID DEADBEEFCAFE,
loopback IPs, no real MACs or account IDs). The full group endpoint
set is also wired: /getGroup and /removeGroup return the empty
<group/> shape a real un-paired device emits; /addGroup and
/updateGroup echo the posted body with <status>GROUP_OK</status>
inserted before </group>, matching the success path documented in
issue #252. /supportedURLs lists everything the fake now serves so
any caller that probes capabilities first (e.g. marge_pairing.go)
sees a coherent picture. Tests cover the GET routes' XML roots, the
POST echo + GROUP_OK insertion contract, and /removeGroup's
GET-only contract (405 with Allow: GET on other methods).
2. run.sh seed hit a DNS cliff. The :443 preflight shipped in 3727ae6
resolves server_url on every /setup/settings call, and the
populatePlannedNetworkConfig step does it again. With the previous
seed of http://aftertouch.local:8000 each lookup burned ~5s on DNS
timeout, which compounded across the wizard calls and pushed
ui-migration past chromedp's 30s per-shot budget. Switched the seed
to http://aftertouch.localhost:8000 — RFC 6761 means *.localhost
resolves to loopback via the system resolver in milliseconds
(verified ~8ms on macOS / glibc / systemd-resolved) — so the brand-
friendly hostname survives in the captured PNGs without the
timeout. Manifest settle times bumped (ui-settings 300→2000ms,
ui-devices 500→2500ms, ui-sync 300→1000ms) to give fetchSettings +
fetchSpotifyStatus time to complete in headless Chrome.
While here, softened validateURL's loopback message to acknowledge the
on-device-install case (AfterTouch running on the speaker itself, where
loopback works) instead of unconditionally telling users they're
wrong. The validation still flags 127.0.0.1 / localhost since it's the
wrong answer 99% of the time, but the message now frames the
constraint rather than scolding.
docs/images/ui-*.png regenerated against the new pipeline.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
103 lines
3.4 KiB
Bash
Executable File
103 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Orchestrates an end-to-end screenshot capture: spins up a clean
|
|
# soundtouch-service + dummy-speaker, drives the web UI in headless
|
|
# Chrome via the chromedp runner, then tears everything down.
|
|
#
|
|
# Outputs to docs/images/ by default. Override with OUT_DIR=/some/path.
|
|
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
|
|
cd "$REPO_ROOT"
|
|
|
|
OUT_DIR="${OUT_DIR:-docs/images}"
|
|
SERVICE_PORT="${SERVICE_PORT:-8000}"
|
|
SPEAKER_PORT="${SPEAKER_PORT:-8090}"
|
|
DATA_DIR="$(mktemp -d -t soundtouch-screenshots-XXXXXX)"
|
|
LOG_DIR="$(mktemp -d -t soundtouch-screenshot-logs-XXXXXX)"
|
|
|
|
SERVICE_PID=""
|
|
SPEAKER_PID=""
|
|
|
|
cleanup() {
|
|
set +e
|
|
if [ -n "$SPEAKER_PID" ] && kill -0 "$SPEAKER_PID" 2>/dev/null; then
|
|
kill "$SPEAKER_PID"
|
|
wait "$SPEAKER_PID" 2>/dev/null
|
|
fi
|
|
if [ -n "$SERVICE_PID" ] && kill -0 "$SERVICE_PID" 2>/dev/null; then
|
|
kill "$SERVICE_PID"
|
|
wait "$SERVICE_PID" 2>/dev/null
|
|
fi
|
|
rm -rf "$DATA_DIR"
|
|
echo "logs retained at $LOG_DIR"
|
|
}
|
|
trap cleanup EXIT
|
|
|
|
echo "==> building binaries"
|
|
go build -o "$LOG_DIR/soundtouch-service" ./cmd/soundtouch-service
|
|
go build -o "$LOG_DIR/dummy-speaker" ./cmd/dummy-speaker
|
|
go build -o "$LOG_DIR/screenshots" ./scripts/screenshots
|
|
|
|
echo "==> seeding settings.json (aftertouch.localhost + discovery off to avoid leaking real network info)"
|
|
# `aftertouch.localhost` is RFC 6761: any *.localhost name resolves to
|
|
# loopback via the system resolver in milliseconds (verified ~8ms on
|
|
# macOS / glibc / systemd-resolved). That gives us a brand-friendly URL
|
|
# in the screenshots without the ~5s DNS-timeout cliff that bites on
|
|
# unresolvable hostnames like aftertouch.local — that cliff compounds
|
|
# across /setup/settings + /setup/summary and pushes past the chromedp
|
|
# 30s per-shot budget.
|
|
cat > "$DATA_DIR/settings.json" <<'EOF'
|
|
{
|
|
"server_url": "http://aftertouch.localhost:8000",
|
|
"https_server_url": "https://aftertouch.localhost:8443",
|
|
"discovery_enabled": false,
|
|
"discovery_interval": "1h"
|
|
}
|
|
EOF
|
|
|
|
echo "==> starting soundtouch-service on :$SERVICE_PORT (data: $DATA_DIR)"
|
|
"$LOG_DIR/soundtouch-service" --port "$SERVICE_PORT" --data-dir "$DATA_DIR" \
|
|
> "$LOG_DIR/service.log" 2>&1 &
|
|
SERVICE_PID=$!
|
|
|
|
echo "==> waiting for service to be ready"
|
|
for i in $(seq 1 30); do
|
|
if curl -fsS "http://127.0.0.1:$SERVICE_PORT/setup/devices" > /dev/null 2>&1; then
|
|
break
|
|
fi
|
|
if ! kill -0 "$SERVICE_PID" 2>/dev/null; then
|
|
echo "service died early; log tail:"
|
|
tail -40 "$LOG_DIR/service.log"
|
|
exit 1
|
|
fi
|
|
sleep 0.5
|
|
done
|
|
|
|
echo "==> starting dummy-speaker on :$SPEAKER_PORT (registering with service)"
|
|
# Register as bare IP (no port) so the service appends :8090 for HTTP and
|
|
# :17000 for telnet exactly the way it does with real hardware. This is
|
|
# also why the listeners below bind to the canonical Bose ports.
|
|
"$LOG_DIR/dummy-speaker" \
|
|
--listen "127.0.0.1:$SPEAKER_PORT" \
|
|
--telnet-listen "127.0.0.1:17000" \
|
|
--register "http://127.0.0.1:$SERVICE_PORT" \
|
|
--register-as "127.0.0.1" \
|
|
> "$LOG_DIR/speaker.log" 2>&1 &
|
|
SPEAKER_PID=$!
|
|
sleep 1
|
|
|
|
if ! kill -0 "$SPEAKER_PID" 2>/dev/null; then
|
|
echo "dummy-speaker died early; log tail:"
|
|
tail -40 "$LOG_DIR/speaker.log"
|
|
exit 1
|
|
fi
|
|
|
|
echo "==> capturing screenshots into $OUT_DIR"
|
|
"$LOG_DIR/screenshots" \
|
|
--base "http://127.0.0.1:$SERVICE_PORT" \
|
|
--manifest scripts/screenshots/manifest.json \
|
|
--out "$OUT_DIR"
|
|
|
|
echo "==> done"
|