#!/usr/bin/env sh set -e # Configuration PROGNAME="shai" REPO="ovh/shai" BINARY_NAME="shai" INSTALL_DIR="$HOME/.local/bin" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Helper functions log_info() { echo "${BLUE}[INFO]${NC} $1" } log_success() { echo "${GREEN}[SUCCESS]${NC} $1" } log_warn() { echo "${YELLOW}[WARN]${NC} $1" } log_error() { echo "${RED}[ERROR]${NC} $1" } # Detect OS and architecture detect_platform() { local os arch platform # Detect OS case "$(uname -s)" in Linux*) os="linux" ;; Darwin*) os="macos" ;; CYGWIN*|MINGW*|MSYS*) os="windows" ;; *) log_error "Unsupported OS: $(uname -s)" exit 1 ;; esac # Detect architecture case "$(uname -m)" in x86_64|amd64) arch="x86_64" ;; arm64|aarch64) arch="aarch64" ;; *) log_error "Unsupported architecture: $(uname -m)" exit 1 ;; esac # Special handling for macOS (only x86_64 and aarch64 available) if [ "$os" = "macos" ]; then if [ "$arch" = "x86_64" ]; then platform="macos-x86_64" elif [ "$arch" = "aarch64" ]; then platform="macos-aarch64" fi elif [ "$os" = "linux" ]; then platform="linux-x86_64" elif [ "$os" = "windows" ]; then platform="windows-x86_64.exe" BINARY_NAME="${BINARY_NAME}.exe" fi echo "$platform" } # Generate the full download binary file name # Arguments: $1 - Platform # $2 - Release Tag get_download_binary_name() { platform="${1}" release_tag="${2}" bin_name="" # Releases tagged with an actual version number (e.g. v0.1.3) do not embed the tag in the download binary name if [ -n "${release_tag}" ] && ! echo "${release_tag}" | grep -Eoq '^v?[0-9]*\.?([0-9])*\.?([0-9])*$'; then bin_name="${PROGNAME}-${release_tag}-${platform}" else bin_name="${PROGNAME}-${platform}" fi echo "${bin_name}" } # Get latest release info from GitHub API get_latest_release() { local api_url="https://api.github.com/repos/$REPO/releases/latest" log_info "Fetching latest release information..." # Try with curl first, then wget if command -v curl >/dev/null 2>&1; then curl -s "$api_url" elif command -v wget >/dev/null 2>&1; then wget -qO- "$api_url" else log_error "Neither curl nor wget is available. Please install one of them." exit 1 fi } # Get release info for a specific tag from GitHub API get_release_for_tag() { release_tag=${1} local api_tags_url="https://api.github.com/repos/${REPO}/releases/tags/${release_tag}" log_info "Fetching release information for tag ${release_tag}..." # Try with curl first, then wget if command -v curl >/dev/null 2>&1; then curl -s "$api_tags_url" elif command -v wget >/dev/null 2>&1; then wget -qO- "$api_tags_url" else log_error "Neither curl nor wget is available. Please install one of them." exit 1 fi } # Download binary download_binary() { local download_url="$1" local output_file="$2" log_info "Downloading $BINARY_NAME from $download_url" if command -v curl >/dev/null 2>&1; then curl -L -o "$output_file" "$download_url" elif command -v wget >/dev/null 2>&1; then wget -O "$output_file" "$download_url" else log_error "Neither curl nor wget is available" exit 1 fi } # Create install directory create_install_dir() { if [ ! -d "$INSTALL_DIR" ]; then log_info "Creating install directory: $INSTALL_DIR" mkdir -p "$INSTALL_DIR" fi } # Add to PATH if not already there update_path() { local shell_profile="" # Detect shell profile if [ -n "$ZSH_VERSION" ]; then shell_profile="$HOME/.zshrc" elif [ -n "$BASH_VERSION" ]; then if [ -f "$HOME/.bash_profile" ]; then shell_profile="$HOME/.bash_profile" else shell_profile="$HOME/.bashrc" fi fi # Check if directory is already in PATH if [ "${PATH#*:"$INSTALL_DIR":}" = "$PATH" ] && [ "${PATH#"$INSTALL_DIR":}" = "$PATH" ] && [ "${PATH%:"$INSTALL_DIR"}" = "$PATH" ] && [ "$PATH" != "$INSTALL_DIR" ]; then if [ -n "$shell_profile" ] && [ -f "$shell_profile" ]; then echo "export PATH=\"\$PATH:$INSTALL_DIR\"" >> "$shell_profile" log_success "Added $INSTALL_DIR to PATH in $shell_profile" log_warn "Please run 'source $shell_profile' or restart your terminal" else log_warn "Could not automatically add to PATH. Please add $INSTALL_DIR to your PATH manually" fi fi } # Main installation function main() { log_info "Installing $BINARY_NAME..." # Detect platform local platform platform=$(detect_platform) log_info "Detected platform: $platform" # Get a release local release_json if [ -n "${SHAI_RELEASE}" ] && [ "${SHAI_RELEASE}" != "latest" ]; then release_json=$(get_release_for_tag "${SHAI_RELEASE}") download_bin_name=$(get_download_binary_name "${platform}" "${SHAI_RELEASE}") else release_json=$(get_latest_release) download_bin_name=$(get_download_binary_name "${platform}") fi if [ -z "$release_json" ]; then log_error "Failed to fetch release information" exit 1 fi # Extract download URL local download_url download_url=$(echo "$release_json" | grep -o "\"browser_download_url\":[[:space:]]*\"[^\"]*${download_bin_name}[^\"]*\"" | cut -d'"' -f4) if [ -z "$download_url" ]; then log_error "Could not find download URL for platform: $platform" log_error "Available assets:" echo "$release_json" | grep -o "\"name\":[[:space:]]*\"[^\"]*\"" | cut -d'"' -f4 exit 1 fi # Create install directory create_install_dir # Download binary local temp_file="/tmp/$platform" download_binary "$download_url" "$temp_file" # Install binary local install_path="$INSTALL_DIR/$BINARY_NAME" mv "$temp_file" "$install_path" chmod +x "$install_path" log_success "$BINARY_NAME installed to $install_path" # Update PATH update_path # Verify installation if command -v "$BINARY_NAME" >/dev/null 2>&1; then log_success "Installation completed! You can now run '$BINARY_NAME'" else log_success "Installation completed! You can run '$install_path' or add $INSTALL_DIR to your PATH" fi } # Parse command line arguments while [ $# -gt 0 ]; do case $1 in --install-dir) INSTALL_DIR="$2" shift 2 ;; --help) echo "Usage: $0 [--install-dir DIR] [--help]" echo "" echo "Options:" echo " --install-dir DIR Install to DIR (default: $HOME/.local/bin)" echo " --help Show this help message" exit 0 ;; *) log_error "Unknown option: $1" exit 1 ;; esac done # Run main function main