#!/usr/bin/env bash # Usage: werkregie-deploy-receive < werkregie-dashboard-runtime-linux-x64.tar.gz # # Installs the runtime bundle on stdin as ~/opt/werkregie-dashboard and restarts the service with it. # It is the forced command of Werkator's deploy key in ~/.ssh/authorized_keys of the server's user, # so that the key can do nothing else; the human installs it once as ~/bin/werkregie-deploy-receive. # The command the client asks for, in SSH_ORIGINAL_COMMAND, is ignored. # # It unpacks the bundle beside the running one and runs its launcher, # so that a JRE that does not start on this host stops the deploy before the service does. # Then it stops the service, keeps the running runtime as werkregie-dashboard.prev, swaps and starts it, # and waits until the service answers with the new version; otherwise it puts the previous runtime back. # # The environment may override WERKREGIE_INSTALL_DIR (~/opt), WERKREGIE_CONFIG (~/.config/werkregie/dashboard.yml), # WERKREGIE_UNIT (werkregie-dashboard), WERKREGIE_LAUNCHER_SECONDS (60) and WERKREGIE_WAIT_SECONDS (120). set -euo pipefail install_dir="${WERKREGIE_INSTALL_DIR:-$HOME/opt}" config="${WERKREGIE_CONFIG:-$HOME/.config/werkregie/dashboard.yml}" unit="${WERKREGIE_UNIT:-werkregie-dashboard}" launcher_seconds="${WERKREGIE_LAUNCHER_SECONDS:-60}" wait_seconds="${WERKREGIE_WAIT_SECONDS:-120}" current="$install_dir/werkregie-dashboard" new="$current.new" prev="$current.prev" rm -rf "$new" mkdir -p "$new" tar -xzf - -C "$new" --strip-components=1 # a launcher that ignores its argument would start the dashboard instead and never end if ! version=$(timeout "$launcher_seconds" "$new/bin/werkregie-dashboard" version); then echo "the launcher of the new runtime fails, the service stays as it is" >&2 rm -rf "$new" exit 1 fi [[ "$version" =~ ^[0-9]+(\.[0-9]+)+$ ]] || { echo "not a version: $version" >&2; rm -rf "$new"; exit 1; } port=$(sed -n 's/^port:[[:space:]]*\([0-9][0-9]*\).*/\1/p' "$config" 2>/dev/null | head -1) port="${port:-4747}" answers() { local deadline=$((SECONDS + wait_seconds)) while ((SECONDS < deadline)); do curl -fsS --max-time 5 "http://127.0.0.1:$port/api/dashboard" 2>/dev/null | grep -q "\"version\":\"$1\"" && return 0 sleep 2 done return 1 } echo "installing $version" systemctl --user stop "$unit" rm -rf "$prev" [[ ! -d "$current" ]] || mv "$current" "$prev" mv "$new" "$current" systemctl --user start "$unit" if answers "$version"; then echo "werkregie-dashboard $version runs" exit 0 fi echo "werkregie-dashboard $version does not answer within $wait_seconds s, the previous runtime comes back" >&2 systemctl --user stop "$unit" if [[ -d "$prev" ]]; then rm -rf "$current" mv "$prev" "$current" fi systemctl --user start "$unit" exit 1