#!/usr/bin/env bash # # Build a portable Linux distribution of LedGrab. # Produces a self-contained tarball with virtualenv and launcher script. # # Usage: # ./build-dist.sh [VERSION] # ./build-dist.sh v0.1.0-alpha.1 set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" BUILD_DIR="$SCRIPT_DIR/build" DIST_NAME="LedGrab" DIST_DIR="$BUILD_DIR/$DIST_NAME" SERVER_DIR="$SCRIPT_DIR/server" VENV_DIR="$DIST_DIR/venv" APP_DIR="$DIST_DIR/app" source "$SCRIPT_DIR/build-common.sh" # ── Version detection ──────────────────────────────────────── detect_version "${1:-}" TAR_NAME="LedGrab-v${VERSION_CLEAN}-linux-x64.tar.gz" echo "=== Building LedGrab v${VERSION_CLEAN} (Linux) ===" echo " Output: build/$TAR_NAME" echo "" # ── Clean ──────────────────────────────────────────────────── echo "[1/7] Cleaning..." clean_dist # ── Create virtualenv ──────────────────────────────────────── echo "[2/7] Creating virtualenv..." python3 -m venv "$VENV_DIR" source "$VENV_DIR/bin/activate" pip install --upgrade pip --quiet # ── Install dependencies ───────────────────────────────────── echo "[3/7] Installing dependencies..." pip install --quiet "${SERVER_DIR}[notifications]" 2>&1 | { grep -i 'error\|failed' || true } # Resolve site-packages path (glob expand) SITE_PACKAGES=$(echo "$VENV_DIR"/lib/python*/site-packages) # Clean up with shared function cleanup_site_packages "$SITE_PACKAGES" "so" "so" # ── Build frontend ─────────────────────────────────────────── echo "[4/7] Building frontend..." build_frontend # ── Copy application files ─────────────────────────────────── echo "[5/7] Copying application files..." copy_app_files # ── Create launcher ────────────────────────────────────────── echo "[6/7] Creating launcher..." cat > "$DIST_DIR/run.sh" << 'LAUNCHER' #!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" export PYTHONPATH="$SCRIPT_DIR/app/src" export WLED_CONFIG_PATH="$SCRIPT_DIR/app/config/default_config.yaml" mkdir -p "$SCRIPT_DIR/data" "$SCRIPT_DIR/logs" source "$SCRIPT_DIR/venv/bin/activate" exec python -m wled_controller.main LAUNCHER sed -i "s/VERSION_PLACEHOLDER/${VERSION_CLEAN}/" "$DIST_DIR/run.sh" chmod +x "$DIST_DIR/run.sh" # ── Create autostart scripts ───────────────────────────────── cat > "$DIST_DIR/install-service.sh" << 'SERVICE_INSTALL' #!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SERVICE_NAME="ledgrab" SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" RUN_SCRIPT="$SCRIPT_DIR/run.sh" CURRENT_USER="$(whoami)" if [ "$EUID" -ne 0 ] && [ "$CURRENT_USER" != "root" ]; then echo "This script requires root privileges. Re-running with sudo..." exec sudo "$0" "$@" fi # Resolve the actual user (not root) when run via sudo ACTUAL_USER="${SUDO_USER:-$CURRENT_USER}" ACTUAL_HOME=$(eval echo "~$ACTUAL_USER") echo "Installing LedGrab systemd service..." cat > "$SERVICE_FILE" << EOF [Unit] Description=LedGrab ambient lighting server After=network.target [Service] Type=simple User=$ACTUAL_USER WorkingDirectory=$SCRIPT_DIR ExecStart=$RUN_SCRIPT Restart=on-failure RestartSec=5 Environment=HOME=$ACTUAL_HOME [Install] WantedBy=multi-user.target EOF systemctl daemon-reload systemctl enable "$SERVICE_NAME" systemctl start "$SERVICE_NAME" echo "" echo " [OK] LedGrab service installed and started." echo "" echo " Commands:" echo " sudo systemctl status $SERVICE_NAME # Check status" echo " sudo systemctl stop $SERVICE_NAME # Stop" echo " sudo systemctl restart $SERVICE_NAME # Restart" echo " sudo journalctl -u $SERVICE_NAME -f # View logs" echo "" echo " To remove: run ./uninstall-service.sh" SERVICE_INSTALL chmod +x "$DIST_DIR/install-service.sh" cat > "$DIST_DIR/uninstall-service.sh" << 'SERVICE_UNINSTALL' #!/usr/bin/env bash set -euo pipefail SERVICE_NAME="ledgrab" SERVICE_FILE="/etc/systemd/system/${SERVICE_NAME}.service" if [ "$EUID" -ne 0 ] && [ "$(whoami)" != "root" ]; then echo "This script requires root privileges. Re-running with sudo..." exec sudo "$0" "$@" fi if [ ! -f "$SERVICE_FILE" ]; then echo "LedGrab service is not installed." exit 0 fi echo "Removing LedGrab systemd service..." systemctl stop "$SERVICE_NAME" 2>/dev/null || true systemctl disable "$SERVICE_NAME" 2>/dev/null || true rm -f "$SERVICE_FILE" systemctl daemon-reload echo "" echo " [OK] LedGrab service removed." SERVICE_UNINSTALL chmod +x "$DIST_DIR/uninstall-service.sh" # ── Create tarball ─────────────────────────────────────────── echo "[7/7] Creating $TAR_NAME..." deactivate 2>/dev/null || true TAR_PATH="$BUILD_DIR/$TAR_NAME" (cd "$BUILD_DIR" && tar -czf "$TAR_NAME" "$DIST_NAME") TAR_SIZE=$(du -h "$TAR_PATH" | cut -f1) echo "" echo "=== Build complete ===" echo " Archive: $TAR_PATH" echo " Size: $TAR_SIZE" echo ""