fix: harden the install / update / uninstall scripts
Nightly Build / build (push) Successful in 7m50s
Nightly Build / build (push) Successful in 7m50s
Four things found while re-reading the family of scripts around the logout fix. Both installers piped curl straight into tar, so a truncated download half-extracted — and the installer explicitly supports reinstalling over an existing install, which turned an interrupted download into a tree mixing old and new files with no error saying so. They now download to a temp file and verify the archive in a staging dir before writing anything to the install directory: the ordering update.sh has had since it was written, for the same reason. update.sh never removed files deleted upstream. Extracting over the install dir only adds and overwrites, so a renamed page under docs/ kept being mounted read-only into every container for the assistant to read, and a removed command kept being discovered. It now prunes, from the directories the tarball owns end to end (web, commands, skills, docs), whatever the already-verified staging copy does not have. Pruning after the extraction rather than replacing the directory keeps every intermediate state a complete install. agents/ is deliberately excluded: dropping in an agent is a documented extension point, so that directory is not ours alone and pruning it would delete somebody's work. uninstall.sh fed `docker ps -aq --filter 'name=skald-'` to `docker rm -f`. Docker's name filter is a regex matched anywhere in the name, not a prefix, so any unrelated container merely containing "skald-" was force-removed. Anchored to ^skald-. uninstall.sh also matched uname's raw Linux/Darwin while its three siblings normalize to lowercase. It was correct on its own, but being the odd one out of four copy-paste relatives is precisely how update.sh acquired its no-op case arms, so it now normalizes like the others. Finally, the uninstaller reports that lingering is still enabled and how to turn it off, rather than disabling it: it is a persistent per-user setting other user services may rely on by now, so taking it back silently would stop those too.
This commit is contained in:
+35
-5
@@ -37,7 +37,16 @@ else
|
||||
fi
|
||||
|
||||
# ── Detect OS ─────────────────────────────────────────────────────────────────
|
||||
OS="$(uname -s)"
|
||||
# Normalized to lowercase like every sibling script (install.sh, install-nightly.sh,
|
||||
# update.sh). This file used to match uname's raw `Linux`/`Darwin`, which was
|
||||
# correct on its own but made the four scripts disagree — and a `case` copied
|
||||
# between two of them is exactly how update.sh ended up with stop_service and
|
||||
# start_service as silent no-ops.
|
||||
case "$(uname -s)" in
|
||||
Linux) OS="linux" ;;
|
||||
Darwin) OS="darwin" ;;
|
||||
*) OS="$(uname -s)" ;;
|
||||
esac
|
||||
|
||||
echo ""
|
||||
printf "\033[1m🗑️ Skald Circle — Uninstaller\033[0m\n"
|
||||
@@ -69,7 +78,7 @@ fi
|
||||
|
||||
# ── Stop & remove daemon ──────────────────────────────────────────────────────
|
||||
case "$OS" in
|
||||
Linux)
|
||||
linux)
|
||||
SERVICE_NAME="skald-circle.service"
|
||||
SERVICE_PATH="$HOME/.config/systemd/user/$SERVICE_NAME"
|
||||
|
||||
@@ -90,7 +99,7 @@ case "$OS" in
|
||||
fi
|
||||
;;
|
||||
|
||||
Darwin)
|
||||
darwin)
|
||||
PLIST="$HOME/Library/LaunchAgents/com.skald.circle.plist"
|
||||
|
||||
if [ -f "$PLIST" ]; then
|
||||
@@ -114,7 +123,10 @@ esac
|
||||
# mid-cleanup; removing them here also frees the (sometimes root-owned) mount
|
||||
# files that would otherwise force the sudo fallback on the rm below.
|
||||
if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
|
||||
CONTAINERS="$(docker ps -aq --filter 'name=skald-' 2>/dev/null || true)"
|
||||
# Anchored: Docker's name filter is a regex matched anywhere in the name, so
|
||||
# an unanchored `skald-` also selects somebody else's `my-skald-proxy` — and
|
||||
# the next line is `docker rm -f`. Ours are always `skald-{userid}`.
|
||||
CONTAINERS="$(docker ps -aq --filter 'name=^skald-' 2>/dev/null || true)"
|
||||
if [ -n "$CONTAINERS" ]; then
|
||||
info "🐳 Removing Skald Docker containers …"
|
||||
# shellcheck disable=SC2086 # word-splitting is intentional (multiple IDs)
|
||||
@@ -128,7 +140,7 @@ if command -v docker >/dev/null 2>&1 && docker info >/dev/null 2>&1; then
|
||||
fi
|
||||
elif command -v docker >/dev/null 2>&1; then
|
||||
warn "Docker daemon not reachable — skipping container cleanup."
|
||||
warn "Remove leftovers later with: docker rm -f \$(docker ps -aq --filter name=skald-)"
|
||||
warn "Remove leftovers later with: docker rm -f \$(docker ps -aq --filter name=^skald-)"
|
||||
fi
|
||||
|
||||
# ── Remove installation directory ─────────────────────────────────────────────
|
||||
@@ -151,6 +163,24 @@ fi
|
||||
|
||||
echo ""
|
||||
info "✅ Skald Circle has been uninstalled."
|
||||
|
||||
# The installer enables systemd lingering for this user, which is a persistent
|
||||
# per-user setting and not ours to take back: any other `systemctl --user`
|
||||
# service on this box may be relying on it by now, and silently disabling it
|
||||
# would stop those too. So we say it and leave the choice to the human.
|
||||
if [ "$OS" = "linux" ] && command -v loginctl >/dev/null 2>&1; then
|
||||
case "$(loginctl show-user "${USER:-$(id -un)}" --property=Linger 2>/dev/null || true)" in
|
||||
*=yes)
|
||||
echo ""
|
||||
echo " Note: systemd lingering is still enabled for ${USER:-$(id -un)}."
|
||||
echo " It was enabled at install so the server survived logout. If no other"
|
||||
echo " user service needs it, turn it off with:"
|
||||
echo " sudo loginctl disable-linger ${USER:-$(id -un)}"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo " If you want to reinstall:"
|
||||
echo " curl -fsSL https://builds.skaldagent.net/install.sh | bash"
|
||||
echo " curl -fsSL https://builds.skaldagent.net/install-nightly.sh | bash"
|
||||
|
||||
Reference in New Issue
Block a user