Files
post_bot/bin/update.sh
Choi A.K. 18f91bbd40
Some checks failed
continuous-integration/drone/push Build is failing
script update
2025-09-06 14:04:18 +09:00

146 lines
5.8 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
set -Eeuo pipefail
# === Настройки ===
SERVICE="bot" # имя сервиса из docker-compose.yml
APP_DIR="/app" # рабочая директория кода в контейнере
HOST_DB_DIR="./db" # каталог БД на хосте
HOST_DB_FILE="./db/bot.db" # файл БД на хосте
DB_URL_DEFAULT="sqlite+aiosqlite:////app/db/bot.db" # ЕДИНЫЙ URL БД в контейнере
log(){ echo -e "[update.sh] $*"; }
die(){ echo -e "[update.sh][ERROR] $*" >&2; exit 1; }
# Запускать из корня репо, даже если скрипт лежит в bin/
cd "$(dirname "${BASH_SOURCE[0]}")/.."
# --- Утилиты для alembic в "смонтированном" контейнере (чтобы файлы миграций попадали в репо) ---
alembic_run_mounted() {
# использование: alembic_run_mounted "upgrade head"
docker compose run --rm -T \
-v "$PWD":/app \
-w /app \
"${SERVICE}" sh -lc "alembic $*"
}
# --- 0) Приводим БД и .env к единому виду ---
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
sed -i "s|^DATABASE_URL=.*$|DATABASE_URL=${DB_URL_DEFAULT}|g" .env
log "DATABASE_URL в .env → ${DB_URL_DEFAULT}"
else
echo "DATABASE_URL=${DB_URL_DEFAULT}" >> .env
log "Добавил DATABASE_URL в .env → ${DB_URL_DEFAULT}"
fi
else
echo "DATABASE_URL=${DB_URL_DEFAULT}" > .env
log "Создал .env с DATABASE_URL=${DB_URL_DEFAULT}"
fi
# --- 1) git pull + сборка ---
log "git pull --rebase --autostash ..."
git pull --rebase --autostash || die "git pull не удался"
log "Пересборка образа ..."
docker compose build --no-cache || die "docker compose build не удался"
# --- 2) Безопасный upgrade: выравниваем БД до HEAD; при «потере» ревизии чиним alembic_version ---
safe_upgrade() {
log "alembic upgrade head ..."
set +e
UPG_LOG="$(alembic_run_mounted 'upgrade head' 2>&1)"
RC=$?
set -e
if [[ $RC -eq 0 ]]; then
return 0
fi
echo "$UPG_LOG"
if grep -q "Can't locate revision identified by" <<< "$UPG_LOG"; then
log "Обнаружена «потерянная» ревизия. Автопочинка: подшиваю БД к актуальному HEAD ..."
# Узнаём актуальный HEAD из каталога миграций
set +e
HEADREV="$(alembic_run_mounted 'heads -v' | awk '/^Rev:/{print $2; exit}')"
set -e
[[ -n "${HEADREV:-}" ]] || die "Не удалось определить HEAD ревизию"
# Переписываем alembic_version в файле БД (внутри контейнера сервиса)
docker compose run --rm -T \
-v "$PWD":/app \
-w /app \
"${SERVICE}" sh -lc "sqlite3 /app/db/bot.db \"UPDATE alembic_version SET version_num='${HEADREV}';\" || true"
# Повторяем апгрейд
alembic_run_mounted 'upgrade head' || die "Повторный upgrade head не удался"
else
die "alembic upgrade head не удался"
fi
}
# --- 3) Выравниваем миграции до текущего HEAD ---
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}"
alembic_run_mounted "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
" || true
log "Готово ✅"
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