feat(uninstall): one-command full uninstall with confirmation
- uninstall.sh: removes pi-kit from settings.json (string + gated object entries), the package clone, kit-installed public skills, ~/.config/pi-kit (env.sh with tokens, audit.jsonl) and the shell-rc sourcing block - confirmation prompt by default; PI_KIT_UNINSTALL=1 for non-interactive, PI_KIT_KEEP_CONFIG=1 / PI_KIT_KEEP_SKILLS=1 to retain parts - works without the pi binary (settings edited directly); notes how to remove pi itself - tests: test/uninstall.test.sh against a throwaway $HOME (14 checks: full/partial removal, refusal without flag, idempotent re-run), wired into npm test
This commit is contained in:
@@ -0,0 +1,99 @@
|
||||
#!/usr/bin/env bash
|
||||
# Tests for uninstall.sh against a throwaway $HOME (no real machine state touched).
|
||||
# Run via `npm test` or directly: bash test/uninstall.test.sh
|
||||
set -euo pipefail
|
||||
|
||||
ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
UNINSTALL="$ROOT/uninstall.sh"
|
||||
FAILS=0
|
||||
|
||||
check() { # <name> <bash-expression>
|
||||
local name="$1"
|
||||
if bash -c "$2"; then
|
||||
echo "PASS $name"
|
||||
else
|
||||
echo "FAIL $name"
|
||||
FAILS=$((FAILS + 1))
|
||||
fi
|
||||
}
|
||||
|
||||
# Fresh fake home with everything the kit can leave behind.
|
||||
setup_fake_home() {
|
||||
export HOME="$(mktemp -d)"
|
||||
export SHELL=/bin/bash
|
||||
export PI_KIT_UNINSTALL=1
|
||||
export PI_KIT_KEEP_CONFIG=0
|
||||
export PI_KIT_KEEP_SKILLS=0
|
||||
|
||||
mkdir -p "$HOME/.pi/agent/git/git.codelab.vc/ai/pi-kit"
|
||||
mkdir -p "$HOME/.agents/skills"
|
||||
mkdir -p "$HOME/.config/pi-kit"
|
||||
|
||||
cat >"$HOME/.pi/agent/settings.json" <<'JSON'
|
||||
{
|
||||
"packages": [
|
||||
"git:github.com/someone/other",
|
||||
{ "source": "git:git.codelab.vc/ai/pi-kit@stable", "skills": ["skills/go-standards"] },
|
||||
"git:git.codelab.vc/ai/pi-kit@beta"
|
||||
]
|
||||
}
|
||||
JSON
|
||||
echo "export JIRA_TOKEN='dummy'" >"$HOME/.config/pi-kit/env.sh"
|
||||
cat >"$HOME/.agents/skills/grill-me" <<'EOF'
|
||||
skill content
|
||||
EOF
|
||||
cat >"$HOME/.bashrc" <<'RC'
|
||||
# user content
|
||||
export FOO=1
|
||||
|
||||
# >>> pi-kit >>>
|
||||
[ -f "$HOME/.config/pi-kit/env.sh" ] && . "$HOME/.config/pi-kit/env.sh"
|
||||
# <<< pi-kit <<<
|
||||
|
||||
# more user content
|
||||
RC
|
||||
}
|
||||
|
||||
# --- 1. Full uninstall --------------------------------------------------------
|
||||
setup_fake_home
|
||||
bash "$UNINSTALL" >/dev/null
|
||||
check "uninstall: settings.json keeps other packages" "grep -q 'git:github.com/someone/other' \"$HOME/.pi/agent/settings.json\""
|
||||
check "uninstall: settings.json drops object-form pi-kit" "! grep -q 'pi-kit' \"$HOME/.pi/agent/settings.json\""
|
||||
check "uninstall: clone dir removed" "test ! -e \"$HOME/.pi/agent/git/git.codelab.vc/ai/pi-kit\""
|
||||
check "uninstall: config dir removed" "test ! -e \"$HOME/.config/pi-kit\""
|
||||
check "uninstall: rc block removed" "! grep -q 'pi-kit' \"$HOME/.bashrc\""
|
||||
check "uninstall: rc user content preserved" "grep -q 'export FOO=1' \"$HOME/.bashrc\" && grep -q 'more user content' \"$HOME/.bashrc\""
|
||||
check "uninstall: public skill removed" "test ! -e \"$HOME/.agents/skills/grill-me\""
|
||||
|
||||
# --- 2. Keep config (secrets + rc) --------------------------------------------
|
||||
setup_fake_home
|
||||
PI_KIT_KEEP_CONFIG=1 bash "$UNINSTALL" >/dev/null
|
||||
check "keep-config: env.sh kept" "test -e \"$HOME/.config/pi-kit/env.sh\""
|
||||
check "keep-config: rc block kept" "grep -q 'pi-kit' \"$HOME/.bashrc\""
|
||||
check "keep-config: package still removed" "! grep -q 'pi-kit' \"$HOME/.pi/agent/settings.json\""
|
||||
|
||||
# --- 3. Keep skills ------------------------------------------------------------
|
||||
setup_fake_home
|
||||
PI_KIT_KEEP_SKILLS=1 bash "$UNINSTALL" >/dev/null
|
||||
check "keep-skills: skill kept" "test -e \"$HOME/.agents/skills/grill-me\""
|
||||
|
||||
# --- 4. Non-interactive without flag must refuse ---------------------------------
|
||||
setup_fake_home
|
||||
PI_KIT_UNINSTALL=0 bash "$UNINSTALL" >/dev/null 2>&1 && RC=0 || RC=$?
|
||||
check "uninstall: refuses without confirmation flag in non-interactive mode" "test \"$RC\" -ne 0"
|
||||
check "uninstall: nothing removed on refusal" "grep -q 'pi-kit' \"$HOME/.pi/agent/settings.json\" && test -e \"$HOME/.config/pi-kit/env.sh\""
|
||||
|
||||
# --- 5. Idempotent re-run -------------------------------------------------------
|
||||
setup_fake_home
|
||||
bash "$UNINSTALL" >/dev/null
|
||||
bash "$UNINSTALL" >/dev/null 2>&1 || true
|
||||
check "uninstall: re-run is harmless" "test ! -e \"$HOME/.config/pi-kit\" && ! grep -q 'pi-kit' \"$HOME/.pi/agent/settings.json\""
|
||||
|
||||
echo ""
|
||||
if [ "$FAILS" -eq 0 ]; then
|
||||
echo "uninstall tests: ALL PASS"
|
||||
exit 0
|
||||
else
|
||||
echo "uninstall tests: $FAILS FAILED"
|
||||
exit 1
|
||||
fi
|
||||
Reference in New Issue
Block a user