SPB Git forge
38commits 1branches 0releases
338.7 MBsize
maindefault branch
3 h agolast push
HTML 53.9% TypeScript 44.5% JavaScript 0.6% SQL 0.5%
4.1 KB · 104 lines shellscript
Raw Blame History
1#!/usr/bin/env bash2# Shared helpers for deploy/bin/*.sh — sourced, not executed.3# Targets: data = BHS128 (public via BHS64 gateway, stores on 10.68.0.1) · crawl = BHS64b (workers, 10.68.0.2)4set -euo pipefail56REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"7REMOTE_DIR="${DCI_REMOTE_DIR:-/srv/dci/app}"8BACKUP_DIR="${DCI_BACKUP_DIR:-/srv/dci/backups}"9OFFSITE_DIR="${DCI_OFFSITE_DIR:-/srv/dci-backups}"10DATA_WG_IP="${DATA_WG_IP:-10.67.0.60}"11DATA_PRIVATE_IP="${DATA_PRIVATE_IP:-10.68.0.1}"12CRAWL_PRIVATE_IP="${CRAWL_PRIVATE_IP:-10.68.0.2}"13PUBLIC_URL="${DCI_PUBLIC_URL:-https://www.datacenterindex.io}"14SSH_OPTS=(-o BatchMode=yes -o ConnectTimeout=15 -o ServerAliveInterval=30)1516c_bold=$'\033[1m'; c_dim=$'\033[2m'; c_red=$'\033[31m'; c_grn=$'\033[32m'; c_ylw=$'\033[33m'; c_rst=$'\033[0m'17log()  { printf '%s▸ %s%s\n' "$c_bold" "$*" "$c_rst"; }18ok()   { printf '%s✓ %s%s\n' "$c_grn" "$*" "$c_rst"; }19warn() { printf '%s! %s%s\n' "$c_ylw" "$*" "$c_rst" >&2; }20die()  { printf '%s✗ %s%s\n' "$c_red" "$*" "$c_rst" >&2; exit 1; }2122# target → ssh alias23host_for() {24  case "$1" in25    data)  echo "${DCI_DATA_HOST:-BHS128}" ;;26    crawl) echo "${DCI_CRAWL_HOST:-BHS64b}" ;;27    *) die "unknown target '$1' (data|crawl)" ;;28  esac29}30check_target() { case "${1:-}" in data|crawl) ;; *) die "usage: $(basename "$0") data|crawl" ;; esac; }3132# service → target (for logs.sh / status.sh convenience)33target_for_service() {34  case "$1" in35    worker|worker-b) echo crawl ;;36    *) echo data ;;37  esac38}3940remote() { # remote <target> <cmd...>41  local t="$1"; shift42  ssh "${SSH_OPTS[@]}" "$(host_for "$t")" "$@"43}4445# The compose command as executed ON the remote host (docker or sudo docker, whichever works).46compose_prefix() { # compose_prefix <target>47  local t="$1"48  echo "cd $REMOTE_DIR && TSX_VERSION=$(tsx_version) \$(docker info >/dev/null 2>&1 && echo docker || echo 'sudo docker') compose -f deploy/compose.$t.yml --env-file deploy/.env.$t"49}50compose() { # compose <target> <compose args...>51  local t="$1"; shift52  remote "$t" "$(compose_prefix "$t") $*"53}5455tsx_version() {56  sed -nE 's/^  tsx@([0-9]+\.[0-9]+\.[0-9]+):.*/\1/p' "$REPO_ROOT/pnpm-lock.yaml" | head -1 | grep . || echo 4.23.1357}5859require_env_file() { # require_env_file <target>60  local f="$REPO_ROOT/deploy/.env.$1"61  if [[ ! -f "$f" ]]; then62    if remote "$1" "test -f $REMOTE_DIR/deploy/.env.$1"; then63      warn "no local $f — keeping the existing remote copy"64      return 065    fi66    die "missing $f (copy deploy/.env.$1.example and fill the secrets)"67  fi68  if grep -qE '^(POSTGRES_PASSWORD|REDIS_PASSWORD|S3_SECRET_KEY)=$' "$f"; then69    die "$f still has empty secrets"70  fi71}7273ensure_remote_layout() { # ensure_remote_layout <target>74  local t="$1"75  # clickhouse (uid 101 in its container) writes BACKUP files into $BACKUP_DIR/clickhouse → sticky world-writable76  remote "$t" "sudo mkdir -p $REMOTE_DIR $BACKUP_DIR/pg $BACKUP_DIR/config $BACKUP_DIR/minio $BACKUP_DIR/clickhouse /srv/dci/out \77    && sudo chown -R \$USER:\$USER /srv/dci && sudo chmod 1777 $BACKUP_DIR/clickhouse /srv/dci/out \78    && (docker info >/dev/null 2>&1 || sudo usermod -aG docker \$USER)"79}8081sync_repo() { # sync_repo <target>82  local t="$1" host; host="$(host_for "$t")"83  log "rsync repo → $host:$REMOTE_DIR"84  rsync -az --delete \85    --exclude-from="$REPO_ROOT/deploy/rsync-exclude.txt" \86    -e "ssh ${SSH_OPTS[*]}" \87    "$REPO_ROOT/" "$host:$REMOTE_DIR/"88  if [[ -f "$REPO_ROOT/deploy/.env.$t" ]]; then89    scp -q "${SSH_OPTS[@]}" "$REPO_ROOT/deploy/.env.$t" "$host:$REMOTE_DIR/deploy/.env.$t" && remote "$t" "chmod 600 $REMOTE_DIR/deploy/.env.$t"90  fi91  remote "$t" "chmod +x $REMOTE_DIR/deploy/bin/*.sh $REMOTE_DIR/deploy/bin/remote/*.sh $REMOTE_DIR/deploy/docker/entrypoint.sh $REMOTE_DIR/deploy/minio/init.sh"92  ok "synced"93}9495wait_http() { # wait_http <target> <url> [attempts] [sleep]96  local t="$1" url="$2" n="${3:-60}" s="${4:-5}" i97  for ((i = 1; i <= n; i++)); do98    if remote "$t" "curl -fsS -m 5 -o /dev/null $url"; then ok "healthy: $url"; return 0; fi99    printf '%s  waiting for %s (%d/%d)%s\n' "$c_dim" "$url" "$i" "$n" "$c_rst"100    sleep "$s"101  done102  return 1103}104