#!/usr/bin/env bash set -Eeuo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # shellcheck source=common.sh source "$SCRIPT_DIR/common.sh" cd "$PROJECT_ROOT" RUN_TESTS=1 usage() { cat <<'TXT' Update an existing systemd/LXC GREE Controller installation from this source tree. Usage: sudo ./scripts/update.sh sudo ./scripts/update.sh --skip-tests The updater: 1. builds and tests the new release while the old service is still running, 2. stops the service, 3. backs up the binary, systemd unit, environment file and SQLite database, 4. installs the new binary and unit, 5. restarts and checks /api/health, 6. rolls back the binary/unit/database automatically if startup fails. TXT } while [[ $# -gt 0 ]]; do case "$1" in --skip-tests) RUN_TESTS=0; shift ;; -h|--help) usage; exit 0 ;; *) echo "Unknown argument: $1" >&2; usage; exit 2 ;; esac done require_root require_systemd [[ -x "$INSTALL_BINARY" ]] || fail "No installed binary at $INSTALL_BINARY. Run scripts/install.sh first." [[ -f "$SERVICE_FILE" ]] || fail "No installed systemd unit at $SERVICE_FILE. Run scripts/install.sh first." install_build_dependencies ensure_rust version="$(project_version)" say "Preparing update to GREE Controller ${version:-unknown}" if [[ "$RUN_TESTS" -eq 1 ]]; then say "Running Rust tests before touching the running service" cargo test --all-targets fi say "Building release binary" cargo build --release stamp="$(backup_timestamp)" backup_dir="$BACKUP_ROOT/$stamp" install -d -o root -g root -m 0700 "$backup_dir" db_path="$(database_path)" rollback() { local rc=$? trap - ERR set +e warn "Update failed; restoring previous installation from $backup_dir" systemctl stop "$SERVICE_NAME" >/dev/null 2>&1 || true if [[ -f "$backup_dir/gree-controller.binary" ]]; then install -o root -g root -m 0755 "$backup_dir/gree-controller.binary" "$INSTALL_BINARY" fi if [[ -f "$backup_dir/gree-controller.service" ]]; then install -o root -g root -m 0644 "$backup_dir/gree-controller.service" "$SERVICE_FILE" fi if [[ -f "$backup_dir/gree-controller.env" ]]; then install -o root -g root -m 0600 "$backup_dir/gree-controller.env" "$ENV_FILE" fi if [[ -f "$backup_dir/gree-controller.db" ]]; then install -o "$SERVICE_USER" -g "$SERVICE_GROUP" -m 0640 "$backup_dir/gree-controller.db" "$db_path" fi rm -f "${db_path}-wal" "${db_path}-shm" systemctl daemon-reload systemctl start "$SERVICE_NAME" >/dev/null 2>&1 || true exit "$rc" } trap rollback ERR say "Stopping service for a consistent SQLite backup" systemctl stop "$SERVICE_NAME" cp -a "$INSTALL_BINARY" "$backup_dir/gree-controller.binary" cp -a "$SERVICE_FILE" "$backup_dir/gree-controller.service" [[ -f "$ENV_FILE" ]] && cp -a "$ENV_FILE" "$backup_dir/gree-controller.env" if [[ -f "$db_path" ]]; then cp -a "$db_path" "$backup_dir/gree-controller.db" fi say "Backup created: $backup_dir" say "Installing new release binary" install -o root -g root -m 0755 target/release/gree-controller "$INSTALL_BINARY.new" mv -f "$INSTALL_BINARY.new" "$INSTALL_BINARY" install -o root -g root -m 0644 systemd/gree-controller.service "$SERVICE_FILE" systemctl daemon-reload systemctl start "$SERVICE_NAME" if ! wait_for_health 80; then journalctl -u "$SERVICE_NAME" -n 100 --no-pager || true false fi trap - ERR say "Update complete" printf 'Version: %s\n' "${version:-unknown}" printf 'Panel: %s\n' "$(panel_url)" printf 'Backup: %s\n' "$backup_dir"