Automate source deployment on main
This commit is contained in:
Executable
+123
@@ -0,0 +1,123 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -Eeuo pipefail
|
||||
|
||||
DEPLOY_DIR="${DEPLOY_DIR:-/home/gitlab-runner/deploy/call-center}"
|
||||
APP_IMAGE_NAME="${APP_IMAGE_NAME:-call-center-app}"
|
||||
APP_IMAGE_TAG="${APP_IMAGE_TAG:-${CI_COMMIT_SHORT_SHA:-latest}}"
|
||||
COMPOSE_FILE="${COMPOSE_FILE:-$DEPLOY_DIR/deployment/docker-compose.server.yml}"
|
||||
HEALTHCHECK_URL="${HEALTHCHECK_URL:-http://127.0.0.1:8080/health}"
|
||||
HEALTHCHECK_TIMEOUT_SECONDS="${HEALTHCHECK_TIMEOUT_SECONDS:-120}"
|
||||
|
||||
require_command() {
|
||||
if ! command -v "$1" >/dev/null 2>&1; then
|
||||
echo "Missing required command: $1" >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
wait_for_health() {
|
||||
python3 - "$HEALTHCHECK_URL" "$HEALTHCHECK_TIMEOUT_SECONDS" <<'PY'
|
||||
import sys
|
||||
import time
|
||||
import urllib.request
|
||||
|
||||
url = sys.argv[1]
|
||||
timeout_seconds = int(sys.argv[2])
|
||||
deadline = time.time() + timeout_seconds
|
||||
last_error = None
|
||||
|
||||
while time.time() < deadline:
|
||||
try:
|
||||
with urllib.request.urlopen(url, timeout=5) as response:
|
||||
if response.getcode() == 200:
|
||||
print(f"Healthcheck passed: {url}")
|
||||
sys.exit(0)
|
||||
last_error = f"unexpected status {response.getcode()}"
|
||||
except Exception as exc:
|
||||
last_error = str(exc)
|
||||
time.sleep(3)
|
||||
|
||||
print(f"Healthcheck failed for {url}: {last_error}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
PY
|
||||
}
|
||||
|
||||
require_command docker
|
||||
require_command rsync
|
||||
require_command python3
|
||||
|
||||
if docker compose version >/dev/null 2>&1; then
|
||||
COMPOSE_CMD=(docker compose)
|
||||
elif command -v docker-compose >/dev/null 2>&1; then
|
||||
COMPOSE_CMD=(docker-compose)
|
||||
else
|
||||
echo "Missing docker compose or docker-compose" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z "${CI_PROJECT_DIR:-}" || ! -d "${CI_PROJECT_DIR:-}" ]]; then
|
||||
echo "CI_PROJECT_DIR is not set or does not exist" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! docker info >/dev/null 2>&1; then
|
||||
echo "Docker daemon is not reachable for the runner user" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
install -d "$DEPLOY_DIR"
|
||||
cd "$DEPLOY_DIR"
|
||||
|
||||
if [[ "$CI_PROJECT_DIR" != "$DEPLOY_DIR" ]]; then
|
||||
rsync -a --delete \
|
||||
--exclude '.git/' \
|
||||
--exclude '.env.production' \
|
||||
--exclude '.env.production.*' \
|
||||
--exclude '.data/' \
|
||||
--exclude '.data_local/' \
|
||||
--exclude '.data_gate3/' \
|
||||
--exclude '.data_gate4/' \
|
||||
--exclude '.data_uat_dry_run/' \
|
||||
--exclude '.data_uat_preflight/' \
|
||||
--exclude '.venv/' \
|
||||
--exclude '.pytest_cache/' \
|
||||
--exclude '.local_stack/' \
|
||||
--exclude 'test-results/' \
|
||||
--exclude '.codex_backup/' \
|
||||
--exclude '.db_backups/' \
|
||||
--exclude '.deploy_backups/' \
|
||||
"$CI_PROJECT_DIR/" "$DEPLOY_DIR/"
|
||||
fi
|
||||
|
||||
if [[ ! -f "$DEPLOY_DIR/.env.production" ]]; then
|
||||
if [[ -n "${DEPLOY_ENV_FILE:-}" && -f "${DEPLOY_ENV_FILE}" ]]; then
|
||||
install -m 600 "$DEPLOY_ENV_FILE" "$DEPLOY_DIR/.env.production"
|
||||
else
|
||||
echo "Missing $DEPLOY_DIR/.env.production. Create it once on the server or set DEPLOY_ENV_FILE." >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
install -d "$DEPLOY_DIR/.data_local"
|
||||
|
||||
export CALL_CENTER_IMAGE="${APP_IMAGE_NAME}:${APP_IMAGE_TAG}"
|
||||
export COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-call-center}"
|
||||
|
||||
echo "Deploy directory: $DEPLOY_DIR"
|
||||
echo "Building image: $CALL_CENTER_IMAGE"
|
||||
|
||||
docker build -t "$CALL_CENTER_IMAGE" -t "${APP_IMAGE_NAME}:latest" "$DEPLOY_DIR"
|
||||
|
||||
if docker ps -a --format '{{.Names}}' | grep -Fxq 'call-center-api-gateway' \
|
||||
&& ! docker ps -a --format '{{.Names}}' | grep -Fxq 'call-center-app'; then
|
||||
echo "Removing legacy gateway container call-center-api-gateway before rename to call-center-app"
|
||||
docker rm -f call-center-api-gateway
|
||||
fi
|
||||
|
||||
"${COMPOSE_CMD[@]}" -f "$COMPOSE_FILE" config -q
|
||||
"${COMPOSE_CMD[@]}" -f "$COMPOSE_FILE" up -d --remove-orphans --force-recreate
|
||||
|
||||
wait_for_health
|
||||
|
||||
docker ps --filter "name=^call-center-app$" --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'
|
||||
Reference in New Issue
Block a user