Skip to content

Commit

Permalink
Merge pull request #68 from ethpandaops/feat/uninstall
Browse files Browse the repository at this point in the history
feat: add uninstall functionality
  • Loading branch information
mattevans authored Jan 17, 2025
2 parents 16b5d7c + b2c5c1d commit be65648
Show file tree
Hide file tree
Showing 3 changed files with 294 additions and 3 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,15 @@ This repository contains the installer for the [contributoor](https://github.com
```
</details>

<details>
<summary>😔 Uninstall</summary>

Uninstalling contributoor can be done by running the installer with the `-u` flag:
```bash
curl -O https://raw.githubusercontent.com/ethpandaops/contributoor-installer/refs/heads/master/install.sh && chmod +x install.sh && ./install.sh -u
```
</details>

## ⚙️ Post-Installation

> **Note:** you may need to start a new shell session before you can run the `contributoor` command.
Expand Down
198 changes: 197 additions & 1 deletion install.bats
Original file line number Diff line number Diff line change
Expand Up @@ -862,10 +862,18 @@ EOF
"launchctl")
case "$2" in
"list") echo "12345 0 io.ethpandaops.contributoor" ;;
"stop") printf "\n${COLOR_GREEN}✓ Stopped launchd service${COLOR_RESET}" ;;
"unload") printf "\n${COLOR_GREEN}✓ Removed launchd service files${COLOR_RESET}" ;;
*) return 0 ;;
esac
;;
*) return 0 ;;
"rm")
"${@:1}"
;;
*)
"${@:2}"
return 0
;;
esac
}
export -f sudo
Expand Down Expand Up @@ -994,4 +1002,192 @@ EOF

[ "$result" -eq 0 ]
echo "$output" | grep -q "You can start contributoor later"
}

@test "uninstall handles user confirmation correctly" {
# Create test environment
mkdir -p "$TEST_DIR/.contributoor"
touch "$TEST_DIR/.zshrc"
echo 'export PATH="$PATH:/some/path/.contributoor/bin"' >> "$TEST_DIR/.zshrc"

# Setup mock functions
function detect_platform() { echo "darwin"; }
function sudo() { "${@:2}"; return 0; }
function docker() {
case "$1" in
"ps") echo "123 contributoor" ;;
"images") echo "456 ethpandaops/contributoor" ;;
"stop") return 0 ;;
"rm") return 0 ;;
"rmi") return 0 ;;
*) return 0 ;;
esac
}
export -f detect_platform sudo docker
export HOME="$TEST_DIR"

# Test 'no' response
run bash -c '
source ./install.sh
printf "n\n" | uninstall
'
[ "$status" -eq 1 ]
echo "$output" | grep -q "Uninstall cancelled"

# Test 'yes' response
run bash -c '
source ./install.sh
printf "y\n" | uninstall
'
[ "$status" -eq 0 ]
echo "$output" | grep -q "Uninstalling contributoor"
echo "$output" | grep -q "Contributoor has been uninstalled successfully"
}

@test "uninstall cleans up all components" {
# Create test environment
mkdir -p "$TEST_DIR/.contributoor/bin"
touch "$TEST_DIR/.zshrc"
echo 'export PATH="$PATH:/some/path/.contributoor/bin"' >> "$TEST_DIR/.zshrc"
export HOME="$TEST_DIR"

# Run uninstall with 'yes' response
run bash -c '
source ./install.sh
# Setup mock functions
detect_platform() { echo "linux"; }
command() {
case "$2" in
"systemctl") return 0 ;;
"docker") return 0 ;;
*) command "$@" ;;
esac
}
sudo() {
case "$1" in
"systemctl")
case "$2" in
"list-unit-files") echo "contributoor.service enabled" ;;
"stop") printf "\n${COLOR_GREEN}✓ Stopped systemd service${COLOR_RESET}" ;;
"disable") printf "\n${COLOR_GREEN}✓ Disabled systemd service${COLOR_RESET}" ;;
*) return 0 ;;
esac
;;
"rm")
"${@:1}"
;;
*)
"${@:2}"
return 0
;;
esac
}
docker() {
case "$1" in
"ps")
[ "$2" = "-a" ] && echo "123 contributoor" || echo "123 contributoor"
;;
"images") echo "456 ethpandaops/contributoor" ;;
"stop") printf "\n${COLOR_GREEN}✓ Stopped Docker containers${COLOR_RESET}" ;;
"rm") printf "\n${COLOR_GREEN}✓ Removed Docker containers${COLOR_RESET}" ;;
"rmi") printf "\n${COLOR_GREEN}✓ Removed Docker images${COLOR_RESET}" ;;
*) return 0 ;;
esac
}
export -f detect_platform command sudo docker
printf "y\n" | uninstall
'

# Check status and output
[ "$status" -eq 0 ]

# Verify systemd cleanup
echo "$output" | grep -q "Stopped systemd service"
echo "$output" | grep -q "Removed systemd service files"

# Verify docker cleanup
echo "$output" | grep -q "Stopped Docker containers"
echo "$output" | grep -q "Removed Docker containers"
echo "$output" | grep -q "Removed Docker images"

# Verify PATH cleanup
echo "$output" | grep -q "Cleaned PATH from"
! grep -q "contributoor" "$TEST_DIR/.zshrc"

# Verify directory cleanup
[ ! -d "$TEST_DIR/.contributoor" ]
}

@test "uninstall handles darwin platform correctly" {
# Create test environment
mkdir -p "$TEST_DIR/.contributoor"
export HOME="$TEST_DIR"

# Run uninstall with 'yes' response
run bash -c '
source ./install.sh
# Setup mock functions
detect_platform() { echo "darwin"; }
sudo() {
case "$1" in
"launchctl")
case "$2" in
"list") echo "123 0 io.ethpandaops.contributoor" ;;
"stop") printf "\n${COLOR_GREEN}✓ Stopped launchd service${COLOR_RESET}" ;;
"unload") printf "\n${COLOR_GREEN}✓ Removed launchd service files${COLOR_RESET}" ;;
*) return 0 ;;
esac
;;
"rm")
"${@:1}"
;;
*)
"${@:2}"
return 0
;;
esac
}
export -f detect_platform sudo
printf "y\n" | uninstall
'

# Check status and output
[ "$status" -eq 0 ]
echo "$output" | grep -q "Stopped launchd service"
echo "$output" | grep -q "Removed launchd service files"
}

@test "uninstall handles missing components gracefully" {
# Create minimal test environment.
mkdir -p "$TEST_DIR"

# Setup mock functions.
function detect_platform() { echo "linux"; }
function command() {
case "$2" in
"systemctl") return 1 ;; # systemd not available
"docker") return 1 ;; # docker not available
*) command "$@" ;;
esac
}
function sudo() {
"${@:2}"
return 0
}
export -f detect_platform command sudo
export HOME="$TEST_DIR"

# Run uninstall with 'yes' response.
run bash -c '
source ./install.sh
printf "y\n" | uninstall
'

# Should complete successfully even with nothing to clean.
[ "$status" -eq 0 ]
echo "$output" | grep -q "Contributoor has been uninstalled successfully"
}
90 changes: 88 additions & 2 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,10 @@ warn() {
}

usage() {
echo "Usage: $0 [-p path] [-v version]"
echo "Usage: $0 [-p path] [-v version] [-u]"
echo " -p: Path to install contributoor (default: $HOME/.contributoor)"
echo " -v: Version of contributoor to install without 'v' prefix (default: latest, example: 0.0.6)"
echo " -u: Uninstall Contributoor"
exit 1
}

Expand Down Expand Up @@ -592,12 +593,97 @@ EOF
}
}

uninstall() {
printf "\n${COLOR_RED}Warning, this will:${COLOR_RESET}\n"
printf " • Stop and remove any contributoor services (systemd/launchd)\n"
printf " • Stop and remove any contributoor Docker containers and images\n"
printf " • Remove contributoor from your PATH\n"
printf " • Delete all contributoor data from ${HOME}/.contributoor\n\n"
printf "Are you sure you want to uninstall? [y/N]: "
read -r confirm
case "$(echo "$confirm" | tr '[:upper:]' '[:lower:]')" in
y|yes) ;;
*) printf "\nUninstall cancelled\n"; exit 1 ;;
esac

printf "\n${COLOR_RED}Uninstalling contributoor...${COLOR_RESET}\n"

# First stop all services based on platform
case "$(detect_platform)" in
"darwin")
if sudo launchctl list | grep -q "io.ethpandaops.contributoor"; then
sudo launchctl stop io.ethpandaops.contributoor
sudo launchctl unload -w "/Library/LaunchDaemons/io.ethpandaops.contributoor.plist"
success "Stopped launchd service"

sudo rm -f "/Library/LaunchDaemons/io.ethpandaops.contributoor.plist"
success "Removed launchd service files"
fi
;;
*)
if command -v systemctl >/dev/null 2>&1 && sudo systemctl list-unit-files | grep -q "contributoor.service"; then
sudo systemctl stop contributoor.service
success "Stopped systemd service"

sudo systemctl disable contributoor.service >/dev/null 2>&1
sudo rm -f "/etc/systemd/system/contributoor.service"
sudo rm -rf "/etc/systemd/system/contributoor.service.d"
sudo rm -f "/etc/systemd/system/contributoor.service.wants"
sudo rm -f "/etc/systemd/system/multi-user.target.wants/contributoor.service"
sudo systemctl daemon-reload
success "Removed systemd service files"
fi
;;
esac

# Stop and clean up docker containers and images if they exist
if command -v docker >/dev/null 2>&1; then
# Stop running containers first
if docker ps | grep -q "contributoor"; then
docker stop $(docker ps | grep "contributoor" | awk '{print $1}') >/dev/null 2>&1
success "Stopped Docker containers"
fi

# Remove containers
if docker ps -a | grep -q "contributoor"; then
docker rm -f $(docker ps -a | grep "contributoor" | awk '{print $1}') >/dev/null 2>&1
success "Removed Docker containers"
fi

# Remove images
if docker images | grep -q "ethpandaops/contributoor"; then
docker rmi -f $(docker images | grep "ethpandaops/contributoor" | awk '{print $3}') >/dev/null 2>&1
success "Removed Docker images"
fi
fi

# Remove PATH entry from shell config
for rc in "$HOME/.bashrc" "$HOME/.zshrc" "$HOME/.bash_profile" "$HOME/.profile"; do
if [ -f "$rc" ]; then
temp_file=$(mktemp)
grep -v "export PATH=.*contributoor.*bin" "$rc" > "$temp_file"
mv "$temp_file" "$rc"
success "Cleaned PATH from $rc"
fi
done

# Remove contributoor directory
if [ -d "$HOME/.contributoor" ]; then
rm -rf "$HOME/.contributoor"
success "Removed contributoor directory"
fi

printf "\n\n${COLOR_GREEN}Contributoor has been uninstalled successfully${COLOR_RESET}\n\n"
exit 0
}

main() {
# Parse arguments
while getopts "p:v:h" FLAG; do
while getopts "p:v:hu" FLAG; do
case "$FLAG" in
p) CONTRIBUTOOR_PATH="$OPTARG" ;;
v) CONTRIBUTOOR_VERSION="$OPTARG" ;;
u) uninstall ;;
h) usage ;;
*) usage ;;
esac
Expand Down

0 comments on commit be65648

Please sign in to comment.