Files
gree-controller/scripts/update.sh
T
2026-08-23 23:20:00 +02:00

112 lines
3.5 KiB
Bash
Executable File

#!/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
build_web_assets_if_available
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"