obm/scripts/install.sh
MermaidMan 21f2bd3a9d feat: add curl|sh one-liner install script
- Add scripts/install.sh for easy installation via curl
- Auto-detects OS (linux, darwin, windows) and arch (amd64, arm64)
- Supports version pinning: sh -s -- v1.2.3
- Installs to /usr/local/bin or ~/.local/bin as fallback
- Updates release workflow to include install.sh in release assets
- Adds README.md with installation documentation
2026-05-22 15:43:19 +00:00

289 lines
No EOL
7.5 KiB
Bash
Executable file

#!/bin/sh
# obm install script - curl | sh one-liner installer
# Usage: curl -fsSL https://raw.githubusercontent.com/openboatmobile/obm/main/scripts/install.sh | sh
# Or: curl -fsSL https://raw.githubusercontent.com/openboatmobile/obm/main/scripts/install.sh | sh -s -- v1.2.3
set -e
# Configuration
GITHUB_REPO="openboatmobile/obm"
BINARY_NAME="obm"
INSTALL_DIR_DEFAULT="/usr/local/bin"
# Colors for output (only if terminal)
if [ -t 1 ]; then
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[0;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
else
RED=''
GREEN=''
YELLOW=''
BLUE=''
NC=''
fi
info() {
printf "${BLUE}==>${NC} %s\n" "$1"
}
success() {
printf "${GREEN}${NC} %s\n" "$1"
}
warn() {
printf "${YELLOW}!${NC} %s\n" "$1" >&2
}
error() {
printf "${RED}${NC} %s\n" "$1" >&2
exit 1
}
# Detect operating system
detect_os() {
case "$(uname -s)" in
Linux*) echo "linux";;
Darwin*) echo "darwin";;
CYGWIN*) echo "windows";;
MINGW*) echo "windows";;
MSYS*) echo "windows";;
*) error "Unsupported OS: $(uname -s)";;
esac
}
# Detect architecture
detect_arch() {
arch="$(uname -m)"
case "$arch" in
x86_64|amd64) echo "amd64";;
aarch64|arm64) echo "arm64";;
armv7l|armv7) echo "arm64";; # Map armv7 to arm64 (may not work)
armv6) echo "arm64";; # Map armv6 to arm64 (may not work)
i386|i686) echo "amd64";; # Map 32-bit to amd64 (may not work)
*) error "Unsupported architecture: $arch";;
esac
}
# Get latest release version from GitHub API
get_latest_version() {
api_url="https://api.github.com/repos/${GITHUB_REPO}/releases/latest"
# Try curl first, fall back to wget
if command -v curl >/dev/null 2>&1; then
version=$(curl -fsSL "$api_url" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
elif command -v wget >/dev/null 2>&1; then
version=$(wget -qO- "$api_url" | grep '"tag_name":' | sed -E 's/.*"([^"]+)".*/\1/')
else
error "Neither curl nor wget found. Please install one of them."
fi
if [ -z "$version" ]; then
error "Could not determine latest version"
fi
echo "$version"
}
# Download the binary
download_binary() {
version="$1"
os="$2"
arch="$3"
dest="$4"
# Build download URL
platform="${os}-${arch}"
if [ "$os" = "windows" ]; then
archive_name="obm-${platform}.zip"
binary_name="obm.exe"
else
archive_name="obm-${platform}.tar.gz"
binary_name="obm"
fi
download_url="https://github.com/${GITHUB_REPO}/releases/download/${version}/${archive_name}"
info "Downloading $archive_name..."
# Create temp directory
tmp_dir=$(mktemp -d)
trap 'rm -rf "$tmp_dir"' EXIT
archive_path="${tmp_dir}/${archive_name}"
# Download
if command -v curl >/dev/null 2>&1; then
if ! curl -fsSL "$download_url" -o "$archive_path"; then
error "Failed to download from $download_url"
fi
elif command -v wget >/dev/null 2>&1; then
if ! wget -q "$download_url" -O "$archive_path"; then
error "Failed to download from $download_url"
fi
fi
# Verify download
if [ ! -f "$archive_path" ] || [ ! -s "$archive_path" ]; then
error "Download failed or file is empty"
fi
info "Extracting..."
# Extract
if [ "$os" = "windows" ]; then
if command -v unzip >/dev/null 2>&1; then
if ! unzip -q "$archive_path" -d "$tmp_dir"; then
error "Failed to extract zip archive"
fi
else
error "unzip not found. Please install unzip."
fi
else
if ! tar -xzf "$archive_path" -C "$tmp_dir"; then
error "Failed to extract tar.gz archive"
fi
fi
# Find the binary (it may be in a subdirectory or at root)
extracted_binary=$(find "$tmp_dir" -name "$binary_name" -type f | head -n1)
if [ -z "$extracted_binary" ]; then
error "Binary not found in archive"
fi
# Move to destination
mv "$extracted_binary" "$dest"
chmod +x "$dest"
}
# Check if we have write permission to install directory
check_install_dir() {
dir="$1"
if [ -d "$dir" ]; then
# Directory exists, check write permission
if [ ! -w "$dir" ]; then
return 1
fi
else
# Directory doesn't exist, check parent
parent=$(dirname "$dir")
if [ ! -w "$parent" ]; then
return 1
fi
fi
return 0
}
# Main installation logic
main() {
version=""
# Parse arguments
while [ $# -gt 0 ]; do
case "$1" in
v*)
version="$1"
shift
;;
*)
warn "Unknown argument: $1"
shift
;;
esac
done
# Detect platform
os=$(detect_os)
arch=$(detect_arch)
info "Detected platform: ${os}-${arch}"
# Get version if not specified
if [ -z "$version" ]; then
info "Fetching latest version..."
version=$(get_latest_version)
fi
info "Installing ${BINARY_NAME} ${version}"
# Determine install directory
install_dir=""
binary_path=""
# Try default locations in order
for dir in "$INSTALL_DIR_DEFAULT" "/usr/bin" "$HOME/.local/bin" "$HOME/bin"; do
if check_install_dir "$dir"; then
install_dir="$dir"
break
fi
done
# If no writable system directory, use home directory
if [ -z "$install_dir" ]; then
info "No writable system directory found"
# Create ~/.local/bin if it doesn't exist
install_dir="$HOME/.local/bin"
mkdir -p "$install_dir"
success "Created $install_dir"
# Check if ~/.local/bin is in PATH
case ":$PATH:" in
*":$install_dir:"*)
;;
*)
warn "~/.local/bin is not in your PATH"
warn "Add 'export PATH=\"\$HOME/.local/bin:\$PATH\"' to your shell config"
;;
esac
fi
binary_path="${install_dir}/${BINARY_NAME}"
# Check for existing installation
if [ -f "$binary_path" ]; then
warn "Removing existing installation at $binary_path"
rm -f "$binary_path"
fi
# Download and install
download_binary "$version" "$os" "$arch" "$binary_path"
# Verify installation
if [ ! -f "$binary_path" ]; then
error "Installation failed - binary not found at $binary_path"
fi
success "Installed ${BINARY_NAME} to ${binary_path}"
# Show version
installed_version=$("$binary_path" version 2>/dev/null || echo "unknown")
if [ "$installed_version" != "unknown" ]; then
success "Version: $installed_version"
fi
# Final message
echo ""
success "Installation complete!"
info "Run '${BINARY_NAME} --help' to get started"
# Reminder about PATH if needed
case ":$PATH:" in
*":$install_dir:"*)
;;
*)
echo ""
warn "To use ${BINARY_NAME}, add ${install_dir} to your PATH:"
echo " export PATH=\"${install_dir}:\$PATH\""
echo ""
warn "Or add to your shell config (~/.bashrc, ~/.zshrc):"
echo " echo 'export PATH=\"${install_dir}:\$PATH\"' >> ~/.bashrc"
;;
esac
}
# Run main
main "$@"