#!/bin/bash # Flint Installer Wrapper # Downloads and runs the Flint installer with version management. # # Usage: # curl -fsSL https://get.flint2.rocks | sudo bash # Latest stable # curl -fsSL https://get.flint2.rocks | sudo bash -s -- --dev # Development # curl -fsSL https://get.flint2.rocks | sudo bash -s -- -v 0.16.0 # Specific version # curl -fsSL https://get.flint2.rocks | sudo bash -s -- --help # Help # # Or download and run manually: # curl -fsSL https://get.flint2.rocks -o get-flint.sh # chmod +x get-flint.sh # sudo ./get-flint.sh [OPTIONS] set -euo pipefail # Configuration DOWNLOAD_SERVER="${FLINT_DOWNLOAD_SERVER:-https://get.flint2.rocks}" INSTALL_DIR="${FLINT_INSTALL_DIR:-/tmp}" INSTALLER_NAME="flint-install.py" # Colors (disabled if not a terminal) if [ -t 1 ]; then RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color else RED='' GREEN='' YELLOW='' BLUE='' NC='' fi # Logging functions info() { echo -e "${GREEN}[INFO]${NC} $*"; } warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } error() { echo -e "${RED}[ERROR]${NC} $*" >&2; } debug() { [ "${VERBOSE:-}" = "1" ] && echo -e "${BLUE}[DEBUG]${NC} $*" || true; } # Print banner banner() { echo "" echo -e "${GREEN} ╔═╗╦ ╦╔╗╔╔╦╗ 2${NC}" echo -e "${GREEN} ╠╣ ║ ║║║║ ║${NC}" echo -e "${GREEN} ╚ ╩═╝╩╝╚╝ ╩${NC}" echo -e "${BLUE} Shopfloor Intelligence & Integration${NC}" echo "" } # Print usage usage() { cat << EOF Flint Installer - Downloads and runs the Flint installer USAGE: curl -fsSL https://get.flint2.rocks | sudo bash [-- OPTIONS] Or: sudo ./get-flint.sh [OPTIONS] OPTIONS: -v, --version VERSION Install specific version (e.g., 0.16.0) -d, --dev Install latest development version -l, --list List available versions -c, --check Download only, don't run installer -V, --verbose Enable verbose output -h, --help Show this help message EXAMPLES: # Install latest stable version curl -fsSL https://get.flint2.rocks | sudo bash # Install latest development version curl -fsSL https://get.flint2.rocks | sudo bash -s -- --dev # Install specific version curl -fsSL https://get.flint2.rocks | sudo bash -s -- -v 0.16.0 # List available versions curl -fsSL https://get.flint2.rocks | bash -s -- --list ENVIRONMENT VARIABLES: FLINT_DOWNLOAD_SERVER Override download server URL FLINT_INSTALL_DIR Override temporary install directory EOF } # Check requirements check_requirements() { local missing=() for cmd in curl python3; do if ! command -v "$cmd" &> /dev/null; then missing+=("$cmd") fi done if [ ${#missing[@]} -ne 0 ]; then error "Missing required commands: ${missing[*]}" error "Please install them and try again." exit 1 fi # Check Python version local py_version py_version=$(python3 -c 'import sys; print(f"{sys.version_info.major}.{sys.version_info.minor}")') local py_major py_minor py_major=$(echo "$py_version" | cut -d. -f1) py_minor=$(echo "$py_version" | cut -d. -f2) if [ "$py_major" -lt 3 ] || { [ "$py_major" -eq 3 ] && [ "$py_minor" -lt 8 ]; }; then error "Python 3.8+ required, found $py_version" exit 1 fi debug "Python version: $py_version" } # Check if running as root check_root() { if [ "$EUID" -ne 0 ]; then error "This installer must be run as root (use sudo)" exit 1 fi } # Fetch available versions from server list_versions() { info "Fetching available versions..." # Try to get version list from server local versions_url="${DOWNLOAD_SERVER}/install/versions.json" local versions if versions=$(curl -fsSL "$versions_url" 2>/dev/null); then echo "" echo "Available versions:" echo "$versions" | python3 -c " import json, sys data = json.load(sys.stdin) if 'stable' in data: print(f\" Latest stable: {data['stable']}\") if 'dev' in data: print(f\" Latest dev: {data['dev']}\") if 'versions' in data: print(' All versions:') for v in data['versions'][:10]: print(f' - {v}') if len(data['versions']) > 10: print(f' ... and {len(data[\"versions\"]) - 10} more') " else # Fallback: show known paths echo "" echo "Available installation paths:" echo " ${DOWNLOAD_SERVER}/install/latest/ - Latest stable version" echo " ${DOWNLOAD_SERVER}/install/dev-latest/ - Latest development version" echo " ${DOWNLOAD_SERVER}/install// - Specific version (e.g., 0.16.0)" echo "" warn "Could not fetch version list from server" fi } # Download installer # Note: All log output goes to stderr so stdout only returns the file path download_installer() { local version_path="$1" local url="${DOWNLOAD_SERVER}/install/${version_path}/${INSTALLER_NAME}" local dest="${INSTALL_DIR}/${INSTALLER_NAME}" info "Downloading installer from: $url" >&2 # Download with progress (progress bar goes to stderr by default) if ! curl -fSL --progress-bar "$url" -o "$dest"; then error "Failed to download installer from $url" error "Please check your network connection and try again." exit 1 fi # Verify it's a Python file if ! head -1 "$dest" | grep -q "python"; then error "Downloaded file does not appear to be a valid Python script" rm -f "$dest" exit 1 fi # Try to download and verify checksum local checksum_url="${url}.sha256" local checksum_file="${dest}.sha256" if curl -fsSL "$checksum_url" -o "$checksum_file" 2>/dev/null; then debug "Verifying checksum..." >&2 local expected actual expected=$(cat "$checksum_file" | awk '{print $1}') actual=$(sha256sum "$dest" | awk '{print $1}') if [ "$expected" != "$actual" ]; then error "Checksum verification failed!" error "Expected: $expected" error "Got: $actual" rm -f "$dest" "$checksum_file" exit 1 fi info "Checksum verified" >&2 rm -f "$checksum_file" else debug "No checksum file available (optional)" >&2 fi chmod +x "$dest" echo "$dest" } # Main function main() { local version_path="latest" local check_only=0 local list_only=0 # Parse arguments while [ $# -gt 0 ]; do case "$1" in -v|--version) if [ -z "${2:-}" ]; then error "Version argument requires a value" exit 1 fi version_path="$2" shift 2 ;; -d|--dev) version_path="dev-latest" shift ;; -l|--list) list_only=1 shift ;; -c|--check) check_only=1 shift ;; -V|--verbose) VERBOSE=1 shift ;; -h|--help) usage exit 0 ;; --) shift break ;; -*) error "Unknown option: $1" usage exit 1 ;; *) break ;; esac done # Note: Don't show banner here - Python installer shows it # List versions and exit if [ "$list_only" -eq 1 ]; then list_versions exit 0 fi # Check requirements check_requirements # Check root (except for list/help) check_root info "Version: $version_path" # Download installer local installer_path installer_path=$(download_installer "$version_path") info "Installer downloaded to: $installer_path" # Check only mode if [ "$check_only" -eq 1 ]; then info "Check mode: installer downloaded but not executed" info "To run manually: sudo python3 $installer_path" exit 0 fi # Run installer echo "" info "Starting Flint installer..." echo "" # Reconnect stdin to terminal (consumed by curl pipe) for interactive prompts # Pass remaining arguments to the Python installer exec python3 "$installer_path" "$@" < /dev/tty } # Run main function main "$@"