#!/bin/bash # ============================================================================ # Make the running bot pick up a change, and prove that it did. # # Two kinds of change, two mechanisms: # # scripts/reload.sh [cmd] data changed (aliases, an album, a # command switched off): POST /_reload, # the table is rebuilt in place, nothing # restarts and no frame is lost. # scripts/reload.sh --code [cmd] code changed: restart the unit, wait for # /healthz to go green again. Lossless too # (signal-cli replays what arrived), but # a deploy step -- so it is the flag, not # the default. # # With [cmd], the bot then types that command at itself in the test group, # so "reloaded" means "answered", not "returned 200". E.g. # # scripts/reload.sh '!nowaosoba' # scripts/reload.sh --code '!pomoc' # ============================================================================ set -euo pipefail SCRIPT_NAME="$(basename "$0")" readonly SCRIPT_NAME SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" readonly SCRIPT_DIR readonly BOT="http://127.0.0.1:${BIND_PORT:-8137}" readonly UNIT="signal-bot" readonly TEST_GROUP="${RELOAD_GROUP:-testbot}" RESTART=0 PROBE="" usage() { echo "Usage: $SCRIPT_NAME [--code] [command-to-selftest]" echo " --code restart the unit (code changed) instead of rebuilding the table" exit 0 } validate_requirements() { if ! command -v jq >/dev/null; then echo "Error: jq is required" >&2 exit 1 fi } wait_healthy() { local attempt=0 # 150 x 0.4 s: a restart is ~1 s, but signal-cli can take a while to # accept the websocket again after its own reconnect. until [[ "$(curl -s "${BOT}/healthz" | jq -r '.status // "down"')" == "ok" ]]; do attempt=$((attempt + 1)) if [[ $attempt -ge 150 ]]; then echo "Error: ${BOT}/healthz never reported ok" >&2 curl -s "${BOT}/healthz" >&2 || true exit 1 fi sleep 0.4 done } reload_data() { local reply status reply="$(curl -s -X POST "${BOT}/_reload")" status="$(jq -r '.status // "?"' <<<"$reply")" case "$status" in reloaded) echo "reloaded: $(jq -r '.commands' <<<"$reply") commands live" ;; kept) # The old table is still answering; the new data is what is broken. echo "Error: reload refused, previous table kept: $(jq -r '.reason' <<<"$reply")" >&2 exit 1 ;; *) echo "Error: unexpected answer from ${BOT}/_reload: ${reply}" >&2 exit 1 ;; esac } restart_code() { systemctl --user restart "$UNIT" wait_healthy echo "restarted: $(curl -s "${BOT}/healthz" | jq -r '"\(.version) \(.pope)"')" } main() { validate_requirements if [[ $RESTART -eq 1 ]]; then restart_code else wait_healthy reload_data fi if [[ -n "$PROBE" ]]; then "${SCRIPT_DIR}/selftest.sh" "$TEST_GROUP" "$PROBE" fi } while [[ $# -gt 0 ]]; do case $1 in --code) RESTART=1 shift ;; -h | --help) usage ;; *) PROBE="$1" shift ;; esac done main