Files
marketing-parser/scripts/deploy_gitlab.sh

119 lines
3.7 KiB
Bash
Executable File

#!/usr/bin/env bash
set -Eeuo pipefail
DEPLOY_DIR="${DEPLOY_DIR:-/home/gitlab-runner/deploy/marketing-parser}"
COMPOSE_FILE="${COMPOSE_FILE:-$DEPLOY_DIR/deployment/docker-compose.server.yml}"
PARSER_IMAGE_NAME="${PARSER_IMAGE_NAME:-marketing-parser-app}"
PARSER_IMAGE_TAG="${PARSER_IMAGE_TAG:-${CI_COMMIT_SHORT_SHA:-latest}}"
PARSER_IMAGE="${PARSER_IMAGE:-${PARSER_IMAGE_NAME}:${PARSER_IMAGE_TAG}}"
PARSER_CONTAINER_NAME="${PARSER_CONTAINER_NAME:-konturai-parser-app}"
COMPOSE_PROJECT_NAME="${COMPOSE_PROJECT_NAME:-marketing-parser}"
WAIT_TIMEOUT_SECONDS="${WAIT_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_container() {
local deadline status
deadline=$((SECONDS + WAIT_TIMEOUT_SECONDS))
while (( SECONDS < deadline )); do
status="$(docker inspect "$PARSER_CONTAINER_NAME" --format '{{.State.Status}}' 2>/dev/null || true)"
if [[ "$status" == "running" ]]; then
echo "Container is running: $PARSER_CONTAINER_NAME"
return 0
fi
if [[ "$status" == "exited" || "$status" == "dead" ]]; then
echo "Container $PARSER_CONTAINER_NAME is in state: $status" >&2
docker logs --tail 100 "$PARSER_CONTAINER_NAME" || true
exit 1
fi
sleep 3
done
echo "Timed out waiting for $PARSER_CONTAINER_NAME to start" >&2
docker logs --tail 100 "$PARSER_CONTAINER_NAME" || true
exit 1
}
require_command bash
require_command docker
require_command rsync
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"
if [[ "$CI_PROJECT_DIR" != "$DEPLOY_DIR" ]]; then
rsync -a --delete \
--exclude '.git/' \
--exclude '.m2/' \
--exclude 'target/' \
--exclude '.codex' \
--exclude '.claude/' \
--exclude '.cursor/' \
--exclude '.idea/' \
--exclude '.vscode/' \
--exclude '.DS_Store' \
--exclude '.env' \
--exclude '.env.*' \
"$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. Run scripts/bootstrap_gitlab_deploy.sh once or set DEPLOY_ENV_FILE." >&2
exit 1
fi
fi
if docker ps -a --format '{{.Names}}' | grep -Fxq "$PARSER_CONTAINER_NAME"; then
EXISTING_PROJECT="$(docker inspect "$PARSER_CONTAINER_NAME" --format '{{ index .Config.Labels "com.docker.compose.project" }}' 2>/dev/null || true)"
if [[ -n "$EXISTING_PROJECT" && "$EXISTING_PROJECT" != "$COMPOSE_PROJECT_NAME" ]]; then
echo "Removing existing container $PARSER_CONTAINER_NAME from compose project $EXISTING_PROJECT"
docker rm -f "$PARSER_CONTAINER_NAME"
fi
fi
cd "$DEPLOY_DIR"
echo "Deploy directory: $DEPLOY_DIR"
echo "Building image: $PARSER_IMAGE"
docker build -t "$PARSER_IMAGE" -t "${PARSER_IMAGE_NAME}:latest" "$DEPLOY_DIR"
export PARSER_IMAGE
export PARSER_CONTAINER_NAME
export COMPOSE_PROJECT_NAME
"${COMPOSE_CMD[@]}" -f "$COMPOSE_FILE" config -q
"${COMPOSE_CMD[@]}" -f "$COMPOSE_FILE" up -d --remove-orphans --force-recreate
wait_for_container
docker ps --filter "name=^${PARSER_CONTAINER_NAME}$" --format 'table {{.Names}}\t{{.Image}}\t{{.Status}}'