AkurAI Build
Menu

Public repository / 3dc2e04327a45398df4d480fc24b78ea0f25fc75

AkurAI-Build / deploy/service-deploy.sh

Latest change 3dc2e04327a45398df4d480fc24b78ea0f25fc75 - deploy: replace stale Docker service-deploy with systemd forge swap (scheduled restart, rollback) by Ólafur Búi Ólafsson

#!/bin/sh
# Replace the live AkurAI-Build forge binary (system unit akurai-build).
#
# Live layout (see `systemctl cat akurai-build`):
#   binary  $HOME/.local/lib/akurai-build/akurai   (unit runs as the host user)
#   health  http://127.0.0.1:3210/api/health
#
# Steps: back up akurai -> akurai.prev, install target/release/akurai, restart,
# poll health up to 20s, restore akurai.prev and restart on failure.
#
# Self-restart: when run from the forge's own CI job (pass --scheduled, as
# .akurai.yml does), restarting the unit would kill this job mid-flight. In that
# case the swap/restart/health/rollback runs as a transient systemd unit
# started 5s later via `sudo systemd-run --on-active=5`; this script exits 0
# after scheduling, and the result is in `journalctl -u akurai-build-swap`.
# Requires passwordless sudo for systemctl/systemd-run/install. Note the forge
# unit sets NoNewPrivileges=true, which blocks sudo from inside CI jobs; until
# that is relaxed run this from a host shell: `sh deploy/service-deploy.sh`.
set -eu

host_home="${AKURAI_HOST_HOME:-$HOME}"
dest_dir="${AKURAI_BUILD_LIB:-$host_home/.local/lib/akurai-build}"
dest="$dest_dir/akurai"
unit=akurai-build
health=http://127.0.0.1:3210/api/health

swap() {
  src="$1"
  test -x "$src"
  test -x "$dest"
  sudo install -m 755 "$dest" "$dest.prev"
  sudo install -m 755 "$src" "$dest.new"
  sudo mv -f "$dest.new" "$dest"
  sudo systemctl restart "$unit"
  i=0
  while [ "$i" -lt 20 ]; do
    if curl -fsS -o /dev/null "$health"; then
      echo "akurai-build healthy"
      return 0
    fi
    i=$((i + 1))
    sleep 1
  done
  echo "akurai-build unhealthy after 20s; rolling back" >&2
  sudo install -m 755 "$dest.prev" "$dest"
  sudo systemctl restart "$unit"
  return 1
}

if [ "${1:-}" = "--swap" ]; then
  swap "${2:?--swap requires a staged binary}"
  exit $?
fi

test -x target/release/akurai

if [ "${1:-}" = "--scheduled" ]; then
  # Stage binary and script outside the job workspace so they survive cleanup.
  stage="$dest_dir/akurai.staged"
  sudo install -m 755 target/release/akurai "$stage"
  sudo install -m 755 deploy/service-deploy.sh "$dest_dir/service-deploy.sh"
  sudo systemd-run --unit akurai-build-swap --collect --on-active=5 \
    --uid="$(id -u)" --setenv=HOME="$host_home" \
    /bin/sh "$dest_dir/service-deploy.sh" --swap "$stage"
  echo "forge swap scheduled in 5s; check: journalctl -u akurai-build-swap"
  exit 0
fi

swap target/release/akurai