diff --git a/.claude/settings.local.json b/.claude/settings.local.json index f6ac8ff..4b30013 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -4,7 +4,8 @@ "Bash(go test:*)", "Bash(go fmt:*)", "Bash(go vet:*)", - "Bash(go build:*)" + "Bash(go build:*)", + "Bash(chmod:*)" ], "deny": [], "ask": [] diff --git a/README.md b/README.md index fbd5bd2..e801a78 100644 --- a/README.md +++ b/README.md @@ -13,12 +13,36 @@ A command-line interface for interacting with JuliaHub, a platform for Julia com ## Installation -### Download Binary +### Quick Install (Recommended) + +Install the latest release automatically: + +```bash +curl -sSfL https://raw.githubusercontent.com/JuliaComputing/gojuliahub/main/install.sh | sh +``` + +Or download and run the script manually: + +```bash +wget https://raw.githubusercontent.com/JuliaComputing/gojuliahub/main/install.sh +chmod +x install.sh +./install.sh +``` + +**Options:** +- `--install-dir DIR`: Custom installation directory (default: `$HOME/.local/bin`) +- `--help`: Show help message + +**Custom installation directory example:** +```bash +curl -sSfL https://raw.githubusercontent.com/JuliaComputing/gojuliahub/main/install.sh | sh -s -- --install-dir /usr/local/bin +``` + +### Download Binary Manually Download the latest release from the [GitHub releases page](https://github.com/JuliaComputing/gojuliahub/releases). Available for: - - Linux (amd64, arm64) - macOS (amd64, arm64) - Windows (amd64, arm64) @@ -27,7 +51,7 @@ Available for: ```bash git clone https://github.com/JuliaComputing/gojuliahub -cd jh +cd gojuliahub go build -o jh . ``` diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..2873233 --- /dev/null +++ b/install.sh @@ -0,0 +1,235 @@ +#!/bin/bash + +# JuliaHub CLI (jh) installer script +# This script downloads and installs the latest release of jh from GitHub + +set -e + +# Configuration +REPO_OWNER="JuliaComputing" +REPO_NAME="gojuliahub" +BINARY_NAME="jh" +INSTALL_DIR="${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 + +# Logging functions +info() { + echo -e "${BLUE}INFO${NC}: $1" +} + +success() { + echo -e "${GREEN}SUCCESS${NC}: $1" +} + +warning() { + echo -e "${YELLOW}WARNING${NC}: $1" +} + +error() { + echo -e "${RED}ERROR${NC}: $1" >&2 + exit 1 +} + +# Detect OS and architecture +detect_platform() { + local os arch + + # Detect OS + case "$(uname -s)" in + Linux*) os="linux";; + Darwin*) os="darwin";; + CYGWIN*|MINGW*|MSYS*) os="windows";; + *) error "Unsupported operating system: $(uname -s)";; + esac + + # Detect architecture + case "$(uname -m)" in + x86_64|amd64) arch="amd64";; + aarch64|arm64) arch="arm64";; + *) error "Unsupported architecture: $(uname -m)";; + esac + + echo "${os}-${arch}" +} + +# Check if command exists +command_exists() { + command -v "$1" >/dev/null 2>&1 +} + +# Get latest release version from GitHub API +get_latest_version() { + local api_url="https://api.github.com/repos/${REPO_OWNER}/${REPO_NAME}/releases/latest" + + if command_exists curl; then + curl -s "$api_url" | grep '"tag_name":' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/' + elif command_exists wget; then + wget -qO- "$api_url" | grep '"tag_name":' | sed -E 's/.*"tag_name": "([^"]+)".*/\1/' + else + error "curl or wget is required to download the release" + fi +} + +# Download and install binary +install_binary() { + local platform="$1" + local version="$2" + local os_part="${platform%-*}" + local arch_part="${platform#*-}" + + # Construct download URL + local binary_name="${BINARY_NAME}-${os_part}-${arch_part}" + if [ "$os_part" = "windows" ]; then + binary_name="${binary_name}.exe" + fi + + local download_url="https://github.com/${REPO_OWNER}/${REPO_NAME}/releases/download/${version}/${binary_name}" + + info "Downloading ${BINARY_NAME} ${version} for ${platform}..." + info "Download URL: $download_url" + + # Create install directory if it doesn't exist + mkdir -p "$INSTALL_DIR" + + # Download binary + local temp_file="${INSTALL_DIR}/${binary_name}.tmp" + local final_file="${INSTALL_DIR}/${BINARY_NAME}" + + if [ "$os_part" = "windows" ]; then + final_file="${final_file}.exe" + fi + + if command_exists curl; then + curl -L -o "$temp_file" "$download_url" + elif command_exists wget; then + wget -O "$temp_file" "$download_url" + else + error "curl or wget is required to download the release" + fi + + # Verify download was successful + if [ ! -f "$temp_file" ] || [ ! -s "$temp_file" ]; then + rm -f "$temp_file" + error "Failed to download binary from $download_url" + fi + + # Move to final location and make executable + mv "$temp_file" "$final_file" + chmod +x "$final_file" + + success "Installed ${BINARY_NAME} to $final_file" + + # Check if install directory is in PATH + case ":$PATH:" in + *":$INSTALL_DIR:"*) ;; + *) warning "$INSTALL_DIR is not in your PATH. Add it to your shell profile:" + echo " echo 'export PATH=\"$INSTALL_DIR:\$PATH\"' >> ~/.bashrc" + echo " echo 'export PATH=\"$INSTALL_DIR:\$PATH\"' >> ~/.zshrc" + ;; + esac +} + +# Verify installation +verify_installation() { + local binary_path="${INSTALL_DIR}/${BINARY_NAME}" + if [ "$(uname -s)" = "CYGWIN" ] || [ "$(uname -s)" = "MINGW" ] || [ "$(uname -s)" = "MSYS" ]; then + binary_path="${binary_path}.exe" + fi + + if [ -x "$binary_path" ]; then + local version_output + if version_output=$("$binary_path" --version 2>/dev/null); then + success "Installation verified: $version_output" + info "Run '$BINARY_NAME --help' to get started" + else + warning "Binary installed but version check failed" + fi + else + error "Installation failed: binary not found or not executable" + fi +} + +# Main installation function +main() { + echo "JuliaHub CLI (${BINARY_NAME}) Installer" + echo "======================================" + + # Detect platform + local platform + platform=$(detect_platform) + info "Detected platform: $platform" + + # Get latest version + info "Fetching latest release information..." + local version + version=$(get_latest_version) + + if [ -z "$version" ]; then + error "Failed to get latest version information" + fi + + info "Latest version: $version" + + # Check if binary already exists + local existing_binary="${INSTALL_DIR}/${BINARY_NAME}" + if [ "$(uname -s | tr '[:upper:]' '[:lower:]')" = "windows" ]; then + existing_binary="${existing_binary}.exe" + fi + + if [ -f "$existing_binary" ]; then + if current_version=$("$existing_binary" --version 2>/dev/null); then + info "Current installation: $current_version" + if echo "$current_version" | grep -q "$version"; then + info "Latest version is already installed" + exit 0 + fi + fi + warning "Existing installation found. It will be replaced." + fi + + # Install binary + install_binary "$platform" "$version" + + # Verify installation + verify_installation + + echo "" + success "Installation complete!" + info "You can now use '${BINARY_NAME}' to interact with JuliaHub" + info "Start with: ${BINARY_NAME} auth login" +} + +# Parse command line arguments +while [[ $# -gt 0 ]]; do + case $1 in + --install-dir) + INSTALL_DIR="$2" + shift 2 + ;; + --help|-h) + echo "JuliaHub CLI Installer" + echo "" + echo "Usage: $0 [options]" + echo "" + echo "Options:" + echo " --install-dir DIR Install directory (default: \$HOME/.local/bin)" + echo " --help, -h Show this help message" + echo "" + echo "Environment variables:" + echo " INSTALL_DIR Same as --install-dir" + exit 0 + ;; + *) + error "Unknown option: $1. Use --help for usage information." + ;; + esac +done + +# Run main installation +main \ No newline at end of file