set -euo pipefail OLD_VER="${1:?old version}" NEW_VER="${2:?new version}" H="$HOME/.hermes" PLUGIN="$H/plugins/srs-gate" BACKUPS="$H/plugin-backups" KEEP=5 export XDG_RUNTIME_DIR="/run/user/$(id -u)" export DBUS_SESSION_BUS_ADDRESS="unix:path=$XDG_RUNTIME_DIR/bus" export PATH="$HOME/.local/bin:$PATH" command -v hermes >/dev/null || { echo "ERROR: hermes command not found in PATH" >&2; exit 1; } [ -d "$PLUGIN" ] || { echo "ERROR: $PLUGIN does not exist" >&2; exit 1; } STAGE="$(mktemp -d "$H/.srs-gate-stage.XXXXXX")" trap 'rm -rf "$STAGE"' EXIT echo "-- unpack" tar -x -C "$STAGE" -f - for f in __init__.py plugin.yaml; do [ -f "$STAGE/$f" ] || { echo "ERROR: missing $f in upload" >&2; exit 1; } done [ "$(ls -A "$STAGE" | wc -l)" = 2 ] || { echo "ERROR: unexpected files in upload" >&2; exit 1; } echo "-- load check" PY="$H/hermes-agent/venv/bin/python" [ -x "$PY" ] || PY=python3 "$PY" -B - "$STAGE/__init__.py" <<'CHECK' import asyncio, importlib.util, sys spec = importlib.util.spec_from_file_location("srs_gate_load_check", sys.argv[1]) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) hooks = [] class Ctx: def register_hook(self, name, callback): hooks.append((name, callback)) module.register(Ctx()) assert [name for name, _ in hooks] == ["pre_gateway_dispatch"], "hook not registered" result = asyncio.run(hooks[0][1](event=None)) assert result.get("action") == "skip", "hook did not answer skip" print("plugin loads, registers and skips") CHECK echo "-- backup" TS="$(date +%Y%m%d-%H%M%S)" BACKUP="$BACKUPS/srs-gate-$OLD_VER-$TS" mkdir -p "$BACKUPS" cp -a "$PLUGIN" "$BACKUP" ls -1dt "$BACKUPS"/srs-gate-* | tail -n +$((KEEP + 1)) | xargs -r rm -rf echo "-- swap" chmod 755 "$STAGE"; chmod 644 "$STAGE"/* mv "$PLUGIN" "$H/.srs-gate-replaced" mv "$STAGE" "$PLUGIN" rm -rf "$H/.srs-gate-replaced" trap - EXIT echo "-- restart gateway" hermes -p default gateway restart echo "-- check" ok=0 for _ in $(seq 1 30); do sleep 2 if systemctl --user is-active --quiet hermes-gateway \ && curl -fsS http://127.0.0.1:3000/health 2>/dev/null | grep -q '"connected"'; then ok=1; break; fi done if [ "$ok" != 1 ]; then echo "ERROR: gateway or bridge not healthy after restart." >&2 echo "Previous plugin is in: $BACKUP" >&2 echo "Roll back: mv $PLUGIN $BACKUPS/srs-gate-bad && cp -a $BACKUP $PLUGIN && hermes -p default gateway restart" >&2 exit 1 fi echo "plugin $OLD_VER -> $NEW_VER installed; backup: $BACKUP"