diff --git a/install.sh b/install.sh new file mode 100755 index 0000000..00e9e0a --- /dev/null +++ b/install.sh @@ -0,0 +1,114 @@ +#!/usr/bin/env bash +# ============================================================================== +# install.sh — HanaToolbox installer +# Downloads the latest native AOT binary from Gitea and installs it. +# Optionally runs the onboarding wizard for first-time setup. +# +# Usage: +# curl -fsSL https://git.technopunk.space/tomi/HanaToolbox/raw/branch/main/install.sh | bash +# # or with onboard: +# curl -fsSL .../install.sh | bash -s -- --onboard +# ============================================================================== +set -euo pipefail + +# ── Config ──────────────────────────────────────────────────────────────────── +REPO_API="https://git.technopunk.space/api/v1/repos/tomi/HanaToolbox/releases/latest" +BINARY_NAME="hanatoolbox" +INSTALL_DIR="/usr/local/bin" +INSTALL_PATH="${INSTALL_DIR}/${BINARY_NAME}" + +# ── Colours ─────────────────────────────────────────────────────────────────── +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' +CYAN='\033[0;36m'; RESET='\033[0m' + +info() { echo -e "${CYAN}ℹ $*${RESET}"; } +success() { echo -e "${GREEN}✅ $*${RESET}"; } +warn() { echo -e "${YELLOW}⚠ $*${RESET}"; } +error() { echo -e "${RED}❌ $*${RESET}" >&2; exit 1; } + +# ── Arg parsing ─────────────────────────────────────────────────────────────── +RUN_ONBOARD=false +for arg in "$@"; do + [[ "$arg" == "--onboard" ]] && RUN_ONBOARD=true +done + +# ── Root check ──────────────────────────────────────────────────────────────── +if [[ $EUID -ne 0 ]]; then + error "This installer must be run as root (sudo or root shell)." +fi + +# ── Dependency check ────────────────────────────────────────────────────────── +for tool in curl jq; do + if ! command -v "$tool" &>/dev/null; then + error "Required tool '${tool}' is not installed. Install it and re-run." + fi +done + +# ── Fetch latest release info ───────────────────────────────────────────────── +info "Fetching latest release from Gitea..." +RELEASE_JSON=$(curl -fsSL "$REPO_API") \ + || error "Failed to fetch release info from ${REPO_API}" + +TAG=$(echo "$RELEASE_JSON" | jq -r '.tag_name') \ + || error "Could not parse tag_name from release JSON." + +if [[ -z "$TAG" || "$TAG" == "null" ]]; then + error "No release found in the repository yet. Publish a release first." +fi + +info "Latest release: ${TAG}" + +# ── Find the binary asset ───────────────────────────────────────────────────── +DOWNLOAD_URL=$(echo "$RELEASE_JSON" \ + | jq -r --arg name "$BINARY_NAME" \ + '.assets[] | select(.name == $name) | .browser_download_url') + +if [[ -z "$DOWNLOAD_URL" || "$DOWNLOAD_URL" == "null" ]]; then + error "No asset named '${BINARY_NAME}' found in release ${TAG}." +fi + +info "Download URL: ${DOWNLOAD_URL}" + +# ── Download ────────────────────────────────────────────────────────────────── +TMP_FILE=$(mktemp) +trap 'rm -f "$TMP_FILE"' EXIT + +info "Downloading ${BINARY_NAME} ${TAG}..." +curl -fsSL --progress-bar -o "$TMP_FILE" "$DOWNLOAD_URL" \ + || error "Download failed." + +# ── Install ─────────────────────────────────────────────────────────────────── +# Backup current binary if it exists +if [[ -f "$INSTALL_PATH" ]]; then + cp "$INSTALL_PATH" "${INSTALL_PATH}.bak" + warn "Previous binary backed up to ${INSTALL_PATH}.bak" +fi + +install -m 0755 "$TMP_FILE" "$INSTALL_PATH" +success "${BINARY_NAME} ${TAG} installed to ${INSTALL_PATH}" + +# ── Verify ──────────────────────────────────────────────────────────────────── +if ! "$INSTALL_PATH" --help &>/dev/null; then + warn "Binary installed but failed self-test. Check architecture compatibility." +else + success "Self-test passed." +fi + +# ── Cron entry hint ─────────────────────────────────────────────────────────── +CRON_FILE="/etc/cron.d/hanatoolbox" +if [[ ! -f "$CRON_FILE" ]]; then + echo -e "\n${CYAN}To enable scheduled tasks, add this cron entry:${RESET}" + echo -e " ${YELLOW}* * * * * root ${INSTALL_PATH} cron${RESET}" + echo -e " e.g.: echo '* * * * * root ${INSTALL_PATH} cron' > ${CRON_FILE}" + echo "" +fi + +# ── Onboard ─────────────────────────────────────────────────────────────────── +if [[ "$RUN_ONBOARD" == true ]]; then + echo "" + info "Starting onboarding wizard..." + exec "$INSTALL_PATH" onboard +fi + +echo "" +success "Installation complete! Run '${BINARY_NAME} onboard' to configure."