#!/usr/bin/env bash set -Eeuo pipefail SERVICE="bot" # имя сервиса в docker-compose APP_DIR="/app" # рабочая директория в контейнере HOST_DB_DIR="./db" # каталог БД на хосте HOST_DB_FILE="./db/bot.db" # файл БД на хосте DB_URL_DEFAULT="sqlite+aiosqlite:////app/db/bot.db" # единый путь БД в контейнере log(){ echo -e "[update.sh] $*"; } die(){ echo -e "[update.sh][ERROR] $*" >&2; exit 1; } cd "$(dirname "${BASH_SOURCE[0]}")/.." # --- 0) Приводим БД к ./db/bot.db и .env к единому URL --- log "Проверка каталога БД ${HOST_DB_DIR} ..." mkdir -p "${HOST_DB_DIR}" # гашим древний конфликт ./bot.db (файл/папка) if [[ -d "./bot.db" ]]; then log "Удаляю конфликтующую ПАПКУ ./bot.db" rm -rf ./bot.db fi if [[ -f "./bot.db" && ! -f "${HOST_DB_FILE}" ]]; then log "Переношу старый файл ./bot.db -> ${HOST_DB_FILE}" mv ./bot.db "${HOST_DB_FILE}" fi if [[ ! -f "${HOST_DB_FILE}" ]]; then log "Создаю пустой файл БД: ${HOST_DB_FILE}" :> "${HOST_DB_FILE}" fi # .env: гарантируем DATABASE_URL if [[ -f .env ]]; then if ! grep -q '^DATABASE_URL=' .env; then log "В .env не найден DATABASE_URL — дописываю ${DB_URL_DEFAULT}" echo "DATABASE_URL=${DB_URL_DEFAULT}" >> .env else # аккуратно заменим на нужный абсолютный путь, если другой sed -i "s|^DATABASE_URL=.*$|DATABASE_URL=${DB_URL_DEFAULT}|g" .env log "DATABASE_URL в .env → ${DB_URL_DEFAULT}" fi else log "Создаю .env с DATABASE_URL=${DB_URL_DEFAULT}" echo "DATABASE_URL=${DB_URL_DEFAULT}" > .env fi # --- 1) git pull + build --- log "git pull --rebase --autostash ..." git pull --rebase --autostash || die "git pull не удался" log "Пересборка образа ..." docker compose build --no-cache # --- 2) Функция безопасного апгрейда Alembic --- safe_upgrade() { log "alembic upgrade head ..." if docker compose run --rm -T "${SERVICE}" sh -lc "cd '${APP_DIR}' && alembic upgrade head"; then return 0 fi log "upgrade head не прошёл. Пытаюсь выровнять ревизии: alembic stamp head → upgrade head" docker compose run --rm -T "${SERVICE}" sh -lc "cd '${APP_DIR}' && alembic stamp head" || die "alembic stamp head провалился" docker compose run --rm -T "${SERVICE}" sh -lc "cd '${APP_DIR}' && alembic upgrade head" || die "alembic upgrade head провалился повторно" } # --- 3) Сначала выравниваем цепочку миграций --- safe_upgrade # --- 4) (Опционально) создаём новую ревизию с твоим комментарием --- MIG_MSG="${1-}" if [[ -z "${MIG_MSG}" ]]; then read -rp "[update.sh] Комментарий для новой миграции (Enter — пропустить): " MIG_MSG || true fi if [[ -n "${MIG_MSG}" ]]; then log "Создаю ревизию Alembic с комментарием: ${MIG_MSG}" docker compose run --rm -T "${SERVICE}" sh -lc "cd '${APP_DIR}' && alembic revision --autogenerate -m \"${MIG_MSG}\"" \ || die "alembic revision --autogenerate не удался" # применяем новую ревизию safe_upgrade else log "Создание ревизии пропущено." fi # --- 5) Запуск сервиса и пост-проверки --- log "Запускаю контейнер ..." docker compose up -d || die "docker compose up -d не удался" log "Проверка переменных и таблиц внутри контейнера ..." docker compose exec -T "${SERVICE}" sh -lc " echo 'DATABASE_URL='\"\$DATABASE_URL\"; cd '${APP_DIR}'; echo 'Alembic HEADS:'; alembic heads -v || true; echo 'Alembic CURRENT:'; alembic current -v || true; if [ -f /app/db/bot.db ]; then echo 'Таблицы SQLite (/app/db/bot.db):'; sqlite3 /app/db/bot.db '.tables' || true; else echo 'Внимание: /app/db/bot.db отсутствует!'; fi " log "Готово ✅"