~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/knotless

git that lives in your Atmosphere account

7
92 lines · 4.3 KB Raw History
#!/usr/bin/env bash
# Builds knotless on the runner host from this checkout and (re)starts its
# knotless-run there.
#
#   deploy/runner-host/deploy.sh <ssh destination>
#   KNOTLESS_RUNNER_HOST=root@host deploy/runner-host/deploy.sh
#
# or with that in deploy/local.env. Run setup.sh on the host once first.
#
# From deploy/local.env, or the environment:
#
# - optional: KNOTLESS_RUNNER_REPOS, repositories it watches besides
#   those whose records name its account, which it finds (--discover), as
#   `alice.example.com/tally bob.example.com/notes`;
# - KNOTLESS_RUNNER_IDENTIFIER and KNOTLESS_RUNNER_PASSWORD, its account
#   and an app password for it, needed once: they are kept on the host in
#   /etc/knotless/run.env;
# - optional: KNOTLESS_RUNNER_DOMAIN and KNOTLESS_RUNNER_DID, the name
#   Caddy answers the runner's bot login at (`runner.knotless.dev`, an
#   A/AAAA record to this host) and the runner's account, the bot that may
#   log in there: both turn on the `bots` profile, for private
#   repositories (README.md, Private repositories);
# - optional: KNOTLESS_RUNNER_ARGS, more of its command line (`--queue`);
#   KNOTLESS_RUNNER_JOBS (4), _CPUS (2), _MEMORY (3, GiB), _TIMEOUT
#   (3600 s), _ALLOWANCE (2000) and _PRIVATE_ALLOWANCE (500), as
#   docker-compose.yml passes them; KNOTLESS_LOG (info).
#
# The image is built on the host, from this checkout's HEAD as `git
# archive` gives it (so commit first): a build driven over SSH by a local
# docker client times out resolving base images, and Docker Desktop's
# builder ignores DOCKER_HOST and builds locally.

set -euo pipefail
cd "$(dirname "$0")/../.."
[ -f deploy/local.env ] && { set -a; . deploy/local.env; set +a; }
DEST="${1:-${KNOTLESS_RUNNER_HOST:-}}"
[ -n "$DEST" ] || { sed -n '5,6p' "$0" >&2; exit 2; }
REPOS="${KNOTLESS_RUNNER_REPOS:-}"
SSH="ssh -o StrictHostKeyChecking=accept-new $DEST"
COMMIT="$(git rev-parse HEAD 2>/dev/null || echo local)"

if [ -n "${KNOTLESS_RUNNER_IMAGE_FROM:-}" ]; then
  # A box too small to build knotless takes the image another host built.
  echo "==> copying knotless:current from $KNOTLESS_RUNNER_IMAGE_FROM to $DEST"
  ssh -o StrictHostKeyChecking=accept-new "$KNOTLESS_RUNNER_IMAGE_FROM" 'docker save knotless:current | gzip -1' |
    $SSH 'gunzip | docker load -q'
else
  echo "==> building knotless at ${COMMIT:0:12} on $DEST"
  git archive --format=tar HEAD |
    $SSH "docker build -q --build-arg KNOTLESS_COMMIT=$COMMIT -t knotless:current -"
fi

if [ -n "${KNOTLESS_RUNNER_IDENTIFIER:-}" ] && [ -n "${KNOTLESS_RUNNER_PASSWORD:-}" ]; then
  printf 'KNOTLESS_IDENTIFIER=%s\nKNOTLESS_PASSWORD=%s\n' "$KNOTLESS_RUNNER_IDENTIFIER" "$KNOTLESS_RUNNER_PASSWORD" |
    $SSH 'umask 077; cat > /etc/knotless/run.env'
fi
$SSH '[ -f /etc/knotless/run.env ]' || {
  echo "the runner needs KNOTLESS_RUNNER_IDENTIFIER and KNOTLESS_RUNNER_PASSWORD once" >&2
  exit 2
}

{
  echo "KNOTLESS_RUN_REPOS=$REPOS"
  [ -z "${KNOTLESS_RUNNER_ARGS:-}" ] || echo "KNOTLESS_RUN_ARGS=$KNOTLESS_RUNNER_ARGS"
  # KNOTLESS_RUNNER_DISCOVER set empty watches only KNOTLESS_RUNNER_REPOS.
  [ -z "${KNOTLESS_RUNNER_DISCOVER+set}" ] || echo "KNOTLESS_RUN_DISCOVER=$KNOTLESS_RUNNER_DISCOVER"
  for v in JOBS OWNER_JOBS CPUS MEMORY TIMEOUT ALLOWANCE PRIVATE_ALLOWANCE; do
    from="KNOTLESS_RUNNER_$v"
    [ -z "${!from:-}" ] || echo "KNOTLESS_RUN_$v=${!from}"
  done
  [ -z "${KNOTLESS_LOG:-}" ] || echo "KNOTLESS_LOG=$KNOTLESS_LOG"
  if [ -n "${KNOTLESS_RUNNER_DOMAIN:-}" ]; then
    echo "COMPOSE_PROFILES=bots"
    echo "KNOTLESS_RUNNER_DOMAIN=$KNOTLESS_RUNNER_DOMAIN"
    echo "KNOTLESS_BOT_DIDS=${KNOTLESS_RUNNER_DID:?KNOTLESS_RUNNER_DOMAIN takes KNOTLESS_RUNNER_DID, the bot that logs in there}"
  fi
} | $SSH 'umask 077; cat > /etc/knotless/.env'
scp -q -o StrictHostKeyChecking=accept-new deploy/runner-host/docker-compose.yml \
  deploy/runner-host/Caddyfile "$DEST:/etc/knotless/"

echo "==> starting"
$SSH '
  set -e
  cd /etc/knotless
  mkdir -p /var/lib/knotless-run/bots/sessions /var/lib/knotless-serve /var/lib/caddy
  # bots runs as uid 1000, the node user the image runs as, as the main
  # host'"'"'s serve does; run, as root, reads and refreshes there too.
  chown 1000:1000 /var/lib/knotless-serve /var/lib/knotless-run/bots /var/lib/knotless-run/bots/sessions
  docker compose config --quiet
  docker compose up -d --remove-orphans
  docker compose ps
'