Skip to content
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ apps/addon/web-dist/
# Git worktrees (project-local)
.worktrees/

# Superset workspace-local HA ownership marker (see .superset/ha.sh)
.superset/.ha-started

# OS
.DS_Store
.claude/
Expand Down
5 changes: 5 additions & 0 deletions .superset/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"setup": ["./.superset/setup.sh"],
"run": ["pnpm dev"],
"teardown": ["./.superset/teardown.sh"]
}
85 changes: 85 additions & 0 deletions .superset/ha.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
#!/usr/bin/env bash
# Workspace-aware control for the local Home Assistant dev stack.
#
# The HA dev container is a singleton: dev/ha-stack.yml hardcodes
# container_name: lovelacer-dev-ha and binds port 8123, so only one instance
# can run across the main repo and all worktrees. Use this wrapper instead of
# `pnpm dev:ha` inside a Superset workspace so teardown only stops the stack
# this workspace actually started (tracked via a workspace-local marker).
#
# ./.superset/ha.sh up # start HA + record ownership
# ./.superset/ha.sh down # stop HA + clear ownership
#
# `down` refuses to act unless this workspace owns the *currently running*
# container, so it can't stop a container the main repo or another workspace
# started. The marker stores the started container id and is revalidated before
# every stop, so a stale marker (e.g. after a `pnpm dev:ha:down` force-stop and
# a restart elsewhere) is cleared rather than acted on. To force-stop the shared
# stack from any checkout, use `pnpm dev:ha:down` directly.
set -euo pipefail

marker=".superset/.ha-started"

# Echo the running lovelacer-dev-ha container id, or nothing if it isn't up.
ha_container_id() {
docker inspect -f '{{.Id}}' lovelacer-dev-ha 2>/dev/null || true
}

case "${1:-}" in
up)
# ha_container_id uses `docker inspect`, so this sees an existing
# lovelacer-dev-ha in ANY state (running, stopped, exited) — not just
# running ones — and avoids adopting/restarting another checkout's stopped
# singleton.
existing_id=$(ha_container_id)
if [ -n "$existing_id" ]; then
if [ -f "$marker" ] && [ "$(cat "$marker")" = "$existing_id" ]; then
# This workspace already owns this exact container — (re)start it.
docker compose -f dev/ha-stack.yml up -d
else
echo "lovelacer-dev-ha already exists (started by another checkout)." >&2
echo "Leaving it untouched and not claiming ownership from this workspace." >&2
fi
exit 0
fi
# No container exists in any state — create one and claim ownership.
# A fresh per-worktree dev/ha-config means a brand-new HA with its own
# onboarding — any HA_TOKEN copied from the root .env won't authenticate.
fresh=0
[ -e dev/ha-config/.storage ] || fresh=1
docker compose -f dev/ha-stack.yml up -d
# Record the started container id so later down/teardown can prove ownership.
ha_container_id > "$marker"
if [ "$fresh" -eq 1 ]; then
echo "Started a fresh HA instance (empty dev/ha-config) on http://localhost:8123." >&2
echo "Any HA_TOKEN copied from the root .env will NOT work against it —" >&2
echo "onboard, generate a new long-lived token, and set HA_TOKEN in .env." >&2
fi
;;
down)
if [ ! -f "$marker" ]; then
echo "This workspace did not start HA (no $marker); refusing to stop the shared stack." >&2
echo "Use 'pnpm dev:ha:down' if you really want to stop it." >&2
exit 0
fi
owned_id=$(cat "$marker")
current_id=$(ha_container_id)
if [ -z "$current_id" ]; then
echo "The HA container this workspace started is no longer running; clearing stale marker." >&2
rm -f "$marker"
exit 0
fi
if [ "$current_id" != "$owned_id" ]; then
echo "Running lovelacer-dev-ha was started by another checkout; not stopping it." >&2
echo "Clearing this workspace's stale marker." >&2
rm -f "$marker"
exit 0
fi
docker compose -f dev/ha-stack.yml down
Comment thread
akadlec marked this conversation as resolved.
rm -f "$marker"
;;
*)
echo "usage: $0 up|down" >&2
exit 1
;;
esac
23 changes: 23 additions & 0 deletions .superset/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/usr/bin/env bash
# Superset workspace setup for Lovelacer.
# Installs workspace deps and seeds a local .env.
set -euo pipefail

# Install all pnpm workspace dependencies (frozen lockfile for reproducibility).
corepack enable >/dev/null 2>&1 || true
pnpm install --frozen-lockfile

# Seed .env: prefer the root repo's .env (carries HA_TOKEN etc.), else fall back
# to the committed example so the server has sane defaults. The copied HA_TOKEN
# targets the shared HA at localhost:8123; if this workspace later starts its
# own fresh HA via ./.superset/ha.sh up, that token won't match and must be
# regenerated (ha.sh up warns when that happens).
if [ ! -f .env ]; then
if [ -n "${SUPERSET_ROOT_PATH:-}" ] && [ -f "$SUPERSET_ROOT_PATH/.env" ]; then
cp "$SUPERSET_ROOT_PATH/.env" .env
Comment thread
akadlec marked this conversation as resolved.
echo "Copied .env from root repo (HA_TOKEN targets the existing shared HA)."
else
cp .env.example .env
echo "No root .env found; copied .env.example. Fill in HA_TOKEN before running."
fi
fi
16 changes: 16 additions & 0 deletions .superset/teardown.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#!/usr/bin/env bash
# Superset workspace teardown for Lovelacer.
#
# Only stops the local Home Assistant dev stack if THIS workspace started it and
# still owns the running container. The HA container is shared across the main
# repo and worktrees — a blanket `docker compose down` here would otherwise stop
# a container another checkout is relying on. Ownership (including stale-marker
# revalidation) lives in ha.sh down, which we delegate to so the logic stays in
# one place.
set -euo pipefail

marker=".superset/.ha-started"

if [ -f "$marker" ]; then
./.superset/ha.sh down
fi