#!/bin/sh # install.sh - Install Aideris CLI from Gitea releases # Usage: curl -fsSL https://gitea.clickthings.net/whuang/aideris-cli-dist/raw/branch/main/install.sh | sh # Or: ./install.sh [--version VERSION] [--bin-dir DIR] [--dry-run] [--verbose] set -e # Configuration REPO_OWNER="whuang" REPO_NAME="aideris-cli-dist" GITEA_URL="https://gitea.clickthings.net" BINARY_NAME="aideris-cli" DEFAULT_BIN_DIR="/usr/local/bin" # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' NC='\033[0m' # Parse command line arguments VERSION="" BIN_DIR="" DRY_RUN=false VERBOSE=false FORCE=false usage() { cat << 'EOF' Usage: install.sh [OPTIONS] Install Aideris CLI from Gitea releases. Options: --version VERSION Install specific version (default: latest) --bin-dir DIR Installation directory (default: /usr/local/bin) --dry-run Show what would be done without executing --verbose Enable verbose output --force Force reinstall even if already installed -h, --help Show this help message Examples: # Install latest version curl -fsSL https://gitea.clickthings.net/whuang/aideris-cli-dist/raw/branch/main/install.sh | sh # Install specific version ./install.sh --version v1.0.0 # Install to custom directory ./install.sh --bin-dir ~/.local/bin # Dry run to preview changes ./install.sh --dry-run EOF exit 0 } while [ $# -gt 0 ]; do case "$1" in --version) VERSION="$2" shift 2 ;; --bin-dir) BIN_DIR="$2" shift 2 ;; --dry-run) DRY_RUN=true shift ;; --verbose) VERBOSE=true shift ;; --force) FORCE=true shift ;; -h|--help) usage ;; *) echo "Unknown option: $1" echo "Use --help for usage information" exit 1 ;; esac done # Set defaults BIN_DIR="${BIN_DIR:-$DEFAULT_BIN_DIR}" # Logging functions log() { printf "${BLUE}[INFO]${NC} %s\n" "$1" } log_success() { printf "${GREEN}[SUCCESS]${NC} %s\n" "$1" } log_warn() { printf "${YELLOW}[WARN]${NC} %s\n" "$1" } log_error() { printf "${RED}[ERROR]${NC} %s\n" "$1" } debug() { if [ "$VERBOSE" = true ]; then printf "${BLUE}[DEBUG]${NC} %s\n" "$1" fi } # Detect OS and Architecture detect_platform() { OS=$(uname -s | tr '[:upper:]' '[:lower:]') ARCH=$(uname -m) case "$ARCH" in x86_64|amd64) ARCH="amd64" ;; aarch64|arm64) ARCH="arm64" ;; armv7l|armv7) ARCH="armv7" ;; i386|i686) ARCH="386" ;; *) log_error "Unsupported architecture: $ARCH" exit 1 ;; esac case "$OS" in linux) OS="linux" ;; darwin) OS="darwin" ;; *) log_error "Unsupported operating system: $OS" exit 1 ;; esac debug "Detected platform: $OS/$ARCH" } # Check if binary is already installed check_existing_installation() { if [ -f "${BIN_DIR}/${BINARY_NAME}" ] && [ "$FORCE" = false ]; then log_warn "${BINARY_NAME} is already installed at ${BIN_DIR}/${BINARY_NAME}" log "Use --force to reinstall or --version to install a specific version" exit 0 fi } # Get the latest version from Gitea get_latest_version() { if [ -n "$VERSION" ]; then return 0 fi log "Fetching latest version from Gitea..." # Try to get latest release from Gitea API API_URL="${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/releases/latest" debug "API URL: $API_URL" LATEST_RELEASE=$(curl -fsSL "$API_URL" 2>/dev/null || echo "") if [ -n "$LATEST_RELEASE" ]; then VERSION=$(echo "$LATEST_RELEASE" | grep -o '"tag_name":"[^"]*"' | head -1 | cut -d'"' -f4) if [ -n "$VERSION" ]; then debug "Latest version: $VERSION" return 0 fi fi # Fallback: try to get from tags TAGS_URL="${GITEA_URL}/api/v1/repos/${REPO_OWNER}/${REPO_NAME}/tags" debug "Tags URL: $TAGS_URL" TAGS=$(curl -fsSL "$TAGS_URL" 2>/dev/null || echo "") if [ -n "$TAGS" ]; then VERSION=$(echo "$TAGS" | grep -o '"name":"[^"]*"' | head -1 | cut -d'"' -f4) if [ -n "$VERSION" ]; then debug "Latest tag: $VERSION" return 0 fi fi log_error "Could not determine latest version. Please specify --version." exit 1 } # Build download URL build_download_url() { # Remove 'v' prefix if present for filename VERSION_NUM="${VERSION#v}" # Construct the download URL # Format: https://gitea.example.com/owner/repo/releases/download/v1.0.0/aideris-cli-linux-amd64 DOWNLOAD_URL="${GITEA_URL}/${REPO_OWNER}/${REPO_NAME}/releases/download/${VERSION}/${BINARY_NAME}-${OS}-${ARCH}" debug "Download URL: $DOWNLOAD_URL" } # Download and install download_and_install() { if [ "$DRY_RUN" = true ]; then log "[DRY RUN] Would download from: $DOWNLOAD_URL" log "[DRY RUN] Would install to: ${BIN_DIR}/${BINARY_NAME}" return 0 fi # Create temp directory for download TEMP_DIR=$(mktemp -d) DOWNLOAD_PATH="${TEMP_DIR}/${BINARY_NAME}" log "Downloading ${BINARY_NAME} ${VERSION} for ${OS}/${ARCH}..." debug "Downloading to: $DOWNLOAD_PATH" # Download the binary HTTP_CODE=$(curl -fsSL -w "%{http_code}" -o "$DOWNLOAD_PATH" "$DOWNLOAD_URL" 2>/dev/null || echo "000") if [ "$HTTP_CODE" != "200" ]; then rm -f "$DOWNLOAD_PATH" log_error "Failed to download binary (HTTP $HTTP_CODE)" log_error "URL: $DOWNLOAD_URL" log "Available platforms are typically:" log " - aideris-cli-linux-amd64" log " - aideris-cli-linux-arm64" log " - aideris-cli-darwin-amd64" log " - aideris-cli-darwin-arm64" rm -rf "$TEMP_DIR" exit 1 fi # Make executable chmod +x "$DOWNLOAD_PATH" # Verify binary is valid ELF/Mach-O if ! file "$DOWNLOAD_PATH" | grep -qE "(ELF|Mach-O)"; then log_warn "Binary file type check failed (may still be valid)" debug "File type: $(file "$DOWNLOAD_PATH")" fi # Create bin directory if it doesn't exist if [ ! -d "$BIN_DIR" ]; then log "Creating directory: $BIN_DIR" if [ "$BIN_DIR" = "$DEFAULT_BIN_DIR" ]; then # For system directories, need sudo log "This requires root privileges." echo -n "Use sudo? [y/N]: " read -r answer case "$answer" in [yY]|[yY][eE][sS]) sudo mkdir -p "$BIN_DIR" ;; *) rm -rf "$TEMP_DIR" log_error "Installation cancelled" exit 1 ;; esac else mkdir -p "$BIN_DIR" fi fi # Install the binary log "Installing ${BINARY_NAME} to ${BIN_DIR}..." if [ "$BIN_DIR" = "$DEFAULT_BIN_DIR" ] && [ ! -w "$BIN_DIR" ]; then sudo cp "$DOWNLOAD_PATH" "${BIN_DIR}/${BINARY_NAME}" sudo chmod 755 "${BIN_DIR}/${BINARY_NAME}" else cp "$DOWNLOAD_PATH" "${BIN_DIR}/${BINARY_NAME}" chmod 755 "${BIN_DIR}/${BINARY_NAME}" fi # Cleanup rm -rf "$TEMP_DIR" } # Verify installation verify_installation() { if [ "$DRY_RUN" = true ]; then log "[DRY RUN] Would verify installation" return 0 fi if [ -f "${BIN_DIR}/${BINARY_NAME}" ]; then log_success "Installation complete!" # Check if bin dir is in PATH case ":$PATH:" in *":${BIN_DIR}:"*) ;; *) log_warn "${BIN_DIR} is not in your PATH" log "Add it with: export PATH=\"${BIN_DIR}:\$PATH\"" ;; esac # Show version log "Installing ${BINARY_NAME} version ${VERSION} to ${BIN_DIR}" echo "" echo "Verify installation with:" echo " ${BIN_DIR}/${BINARY_NAME} --help" echo "" echo "Quick start:" echo " ${BINARY_NAME} onboard --email \"your@email.com\"" else log_error "Installation failed - binary not found at ${BIN_DIR}/${BINARY_NAME}" exit 1 fi } # Main execution main() { echo "" echo "========================================" echo " Aideris CLI Installer" echo "========================================" echo "" # Detect platform detect_platform log "Platform detected: ${OS}/${ARCH}" # Check existing installation check_existing_installation # Get version get_latest_version log "Target version: ${VERSION}" # Build download URL build_download_url # Download and install download_and_install # Verify installation verify_installation } # Run main main