119 lines
3.7 KiB
Bash
Executable File
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}}'
|