144 lines
4.2 KiB
Bash
Executable File
144 lines
4.2 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -Eeuo pipefail
|
|
|
|
# Incremental deployment for an existing Dockerized AlphaX server.
|
|
#
|
|
# Required:
|
|
# DEPLOY_HOST="user@server"
|
|
# REMOTE_DIR="/path/to/existing/alphax-docker"
|
|
#
|
|
# Optional:
|
|
# DEPLOY_BRANCH="main"
|
|
# DEPLOY_MESSAGE="deploy: update alphax"
|
|
# DEPLOY_REMOTE="origin"
|
|
# DEPLOY_SERVICES="alphax-web alphax-scheduler alphax-price-streamer"
|
|
# DEPLOY_RUN_MIGRATIONS=1
|
|
# DEPLOY_HEALTHCHECK_URL="http://127.0.0.1:8191/api/stats"
|
|
# DEPLOY_SKIP_COMMIT=1
|
|
# DEPLOY_SKIP_PUSH=1
|
|
# DEPLOY_SKIP_BUILD=1
|
|
|
|
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
DEPLOY_HOST="${DEPLOY_HOST:-}"
|
|
REMOTE_DIR="${REMOTE_DIR:-}"
|
|
DEPLOY_BRANCH="${DEPLOY_BRANCH:-main}"
|
|
DEPLOY_REMOTE="${DEPLOY_REMOTE:-origin}"
|
|
DEPLOY_MESSAGE="${DEPLOY_MESSAGE:-}"
|
|
DEPLOY_SERVICES="${DEPLOY_SERVICES:-alphax-web alphax-scheduler alphax-price-streamer}"
|
|
DEPLOY_RUN_MIGRATIONS="${DEPLOY_RUN_MIGRATIONS:-1}"
|
|
DEPLOY_HEALTHCHECK_URL="${DEPLOY_HEALTHCHECK_URL:-http://127.0.0.1:8191/api/stats}"
|
|
DEPLOY_SKIP_COMMIT="${DEPLOY_SKIP_COMMIT:-0}"
|
|
DEPLOY_SKIP_PUSH="${DEPLOY_SKIP_PUSH:-0}"
|
|
DEPLOY_SKIP_BUILD="${DEPLOY_SKIP_BUILD:-0}"
|
|
|
|
die() {
|
|
echo "[deploy] ERROR: $*" >&2
|
|
exit 1
|
|
}
|
|
|
|
info() {
|
|
echo "[deploy] $*"
|
|
}
|
|
|
|
require_cmd() {
|
|
command -v "$1" >/dev/null 2>&1 || die "missing required command: $1"
|
|
}
|
|
|
|
quote_remote() {
|
|
printf "%q" "$1"
|
|
}
|
|
|
|
if [[ -z "$DEPLOY_HOST" || -z "$REMOTE_DIR" ]]; then
|
|
cat >&2 <<'USAGE'
|
|
Usage:
|
|
DEPLOY_HOST="user@server" REMOTE_DIR="/path/to/alphax-docker" DEPLOY_MESSAGE="deploy: xxx" bash scripts/deploy_server.sh
|
|
|
|
What it does on the existing server directory:
|
|
git fetch + git pull --ff-only
|
|
docker compose build
|
|
docker compose up -d postgres alphax-web alphax-scheduler alphax-price-streamer
|
|
|
|
Useful options:
|
|
DEPLOY_BRANCH=main
|
|
DEPLOY_SERVICES="alphax-web alphax-scheduler alphax-price-streamer"
|
|
DEPLOY_RUN_MIGRATIONS=1
|
|
DEPLOY_SKIP_COMMIT=1
|
|
DEPLOY_SKIP_PUSH=1
|
|
USAGE
|
|
exit 2
|
|
fi
|
|
|
|
require_cmd git
|
|
require_cmd ssh
|
|
|
|
cd "$ROOT_DIR"
|
|
|
|
current_branch="$(git branch --show-current)"
|
|
if [[ "$current_branch" != "$DEPLOY_BRANCH" ]]; then
|
|
die "current branch is '$current_branch', expected '$DEPLOY_BRANCH'. Set DEPLOY_BRANCH or switch branch first."
|
|
fi
|
|
|
|
if [[ -n "$(git status --porcelain)" ]]; then
|
|
if [[ "$DEPLOY_SKIP_COMMIT" == "1" ]]; then
|
|
die "working tree has changes, but DEPLOY_SKIP_COMMIT=1. Commit or stash first."
|
|
fi
|
|
if [[ -z "$DEPLOY_MESSAGE" ]]; then
|
|
die "working tree has changes. Provide DEPLOY_MESSAGE='deploy: ...' to commit them."
|
|
fi
|
|
info "staging local changes"
|
|
git add -A
|
|
info "creating local commit"
|
|
git commit -m "$DEPLOY_MESSAGE"
|
|
else
|
|
info "working tree clean; no local commit needed"
|
|
fi
|
|
|
|
if [[ "$DEPLOY_SKIP_PUSH" != "1" ]]; then
|
|
info "pushing $DEPLOY_REMOTE/$DEPLOY_BRANCH"
|
|
git push "$DEPLOY_REMOTE" "$DEPLOY_BRANCH"
|
|
else
|
|
info "skip git push"
|
|
fi
|
|
|
|
remote_dir_q="$(quote_remote "$REMOTE_DIR")"
|
|
branch_q="$(quote_remote "$DEPLOY_BRANCH")"
|
|
remote_q="$(quote_remote "$DEPLOY_REMOTE")"
|
|
services_q="$DEPLOY_SERVICES"
|
|
health_q="$(quote_remote "$DEPLOY_HEALTHCHECK_URL")"
|
|
|
|
remote_cmd="
|
|
set -Eeuo pipefail
|
|
cd $remote_dir_q
|
|
test -d .git || { echo '[deploy:remote] ERROR: REMOTE_DIR is not an existing git checkout'; exit 1; }
|
|
test -f docker-compose.yml || { echo '[deploy:remote] ERROR: docker-compose.yml not found in REMOTE_DIR'; exit 1; }
|
|
echo '[deploy:remote] fetching code'
|
|
git fetch $remote_q $branch_q
|
|
echo '[deploy:remote] checking out and pulling branch'
|
|
git checkout $branch_q
|
|
git pull --ff-only $remote_q $branch_q
|
|
echo '[deploy:remote] docker compose config check'
|
|
docker compose config >/dev/null
|
|
if [[ '$DEPLOY_SKIP_BUILD' != '1' ]]; then
|
|
echo '[deploy:remote] docker compose build'
|
|
docker compose build $services_q
|
|
else
|
|
echo '[deploy:remote] skip docker build'
|
|
fi
|
|
if [[ '$DEPLOY_RUN_MIGRATIONS' == '1' ]]; then
|
|
echo '[deploy:remote] running PostgreSQL migrations'
|
|
docker compose run --rm alphax-web python scripts/postgres/run_migrations.py
|
|
fi
|
|
echo '[deploy:remote] docker compose up'
|
|
docker compose up -d postgres $services_q
|
|
echo '[deploy:remote] service status'
|
|
docker compose ps
|
|
if [[ -n $health_q ]]; then
|
|
echo '[deploy:remote] healthcheck'
|
|
curl -fsS $health_q >/dev/null
|
|
fi
|
|
"
|
|
|
|
info "deploying on $DEPLOY_HOST:$REMOTE_DIR"
|
|
ssh "$DEPLOY_HOST" "$remote_cmd"
|
|
info "deployment complete"
|