115 lines
5.6 KiB
Bash
Executable File
115 lines
5.6 KiB
Bash
Executable File
#!/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."
|