Первоначальный коммит

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
poignatov-home
2026-02-08 17:01:36 +03:00
commit bad198ce29
217 changed files with 57075 additions and 0 deletions

View File

@@ -0,0 +1,347 @@
#!/bin/bash
# Скрипт для тестирования baseline миграции на чистой БД
# Создает тестовую БД, применяет baseline, и сравнивает схему с production
set -e
# Цвета для вывода
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Получаем переменные окружения
DB_HOST=${DB_HOST:-localhost}
DB_PORT=${DB_PORT:-5432}
DB_USER=${DB_USER:-playeng}
DB_PASSWORD=${DB_PASSWORD:-playeng}
DB_NAME=${DB_NAME:-playeng}
TEST_DB_NAME="playeng_baseline_test_$$"
MIGRATIONS_PATH="migrations"
TMP_DIR=$(mktemp -d)
echo "=== Тестирование baseline миграции на чистой БД ==="
echo ""
# Добавляем ~/go/bin в PATH если migrate не найден
if ! command -v migrate &> /dev/null; then
export PATH="$HOME/go/bin:$PATH"
fi
# Проверяем наличие необходимых инструментов
if ! command -v migrate &> /dev/null; then
echo -e "${RED}Ошибка: migrate не найден. Установите golang-migrate:${NC}"
echo " brew install golang-migrate"
echo " или"
echo " go install -tags 'postgres' github.com/golang-migrate/migrate/v4/cmd/migrate@latest"
exit 1
fi
# Определяем способ выполнения PostgreSQL команд
PG_DUMP_CMD=""
PG_PSQL_CMD=""
POSTGRES_CONTAINER=""
if command -v pg_dump &> /dev/null; then
PG_DUMP_CMD="pg_dump"
PG_PSQL_CMD="psql"
else
# Пытаемся найти PostgreSQL контейнер
if command -v docker &> /dev/null; then
POSTGRES_CONTAINER=$(docker ps --format "{{.Names}}" 2>/dev/null | grep -iE "(postgres|db)" | head -1)
if [ -n "$POSTGRES_CONTAINER" ]; then
PG_DUMP_CMD="docker exec $POSTGRES_CONTAINER pg_dump"
PG_PSQL_CMD="docker exec -i $POSTGRES_CONTAINER psql"
echo -e "${BLUE}Используется PostgreSQL из Docker контейнера: $POSTGRES_CONTAINER${NC}"
fi
fi
fi
HAS_PG_DUMP=false
if [ -n "$PG_DUMP_CMD" ]; then
HAS_PG_DUMP=true
else
echo -e "${YELLOW}Предупреждение: pg_dump не найден. Сравнение схем будет пропущено.${NC}"
echo " Для полного тестирования установите PostgreSQL client tools"
fi
# Проверяем наличие директории миграций
if [ ! -d "$MIGRATIONS_PATH" ]; then
echo -e "${RED}Ошибка: Директория миграций не найдена: $MIGRATIONS_PATH${NC}"
exit 1
fi
# Проверяем наличие baseline миграции
if [ ! -f "$MIGRATIONS_PATH/000001_baseline.up.sql" ]; then
echo -e "${RED}Ошибка: Baseline миграция не найдена: $MIGRATIONS_PATH/000001_baseline.up.sql${NC}"
exit 1
fi
echo "Параметры подключения:"
echo " Host: $DB_HOST"
echo " Port: $DB_PORT"
echo " User: $DB_USER"
echo " Test DB: $TEST_DB_NAME"
echo ""
# Проверяем подключение к БД
echo "1. Проверка подключения к БД..."
if [ -n "$POSTGRES_CONTAINER" ]; then
# Используем Docker
echo "SELECT 1;" | $PG_PSQL_CMD -U $DB_USER -d postgres > /dev/null 2>&1
elif [ -n "$PG_PSQL_CMD" ]; then
# Используем локальный psql
PGPASSWORD=$DB_PASSWORD $PG_PSQL_CMD \
-h $DB_HOST \
-p $DB_PORT \
-U $DB_USER \
-d postgres \
-c "SELECT 1;" > /dev/null 2>&1
else
# Пытаемся через стандартный psql
PGPASSWORD=$DB_PASSWORD psql \
-h $DB_HOST \
-p $DB_PORT \
-U $DB_USER \
-d postgres \
-c "SELECT 1;" > /dev/null 2>&1
fi
if [ $? -ne 0 ]; then
echo -e "${RED}Ошибка: Не удалось подключиться к БД${NC}"
exit 1
fi
echo -e "${GREEN}✓ Подключение успешно${NC}"
echo ""
# Создаем тестовую БД
echo "2. Создание тестовой БД..."
if [ -n "$POSTGRES_CONTAINER" ]; then
echo "CREATE DATABASE $TEST_DB_NAME;" | $PG_PSQL_CMD -U $DB_USER -d postgres > /dev/null 2>&1
elif [ -n "$PG_PSQL_CMD" ]; then
PGPASSWORD=$DB_PASSWORD $PG_PSQL_CMD \
-h $DB_HOST \
-p $DB_PORT \
-U $DB_USER \
-d postgres \
-c "CREATE DATABASE $TEST_DB_NAME;" > /dev/null 2>&1
else
PGPASSWORD=$DB_PASSWORD psql \
-h $DB_HOST \
-p $DB_PORT \
-U $DB_USER \
-d postgres \
-c "CREATE DATABASE $TEST_DB_NAME;" > /dev/null 2>&1
fi
if [ $? -ne 0 ]; then
echo -e "${RED}Ошибка: Не удалось создать тестовую БД${NC}"
exit 1
fi
echo -e "${GREEN}✓ Тестовая БД создана: $TEST_DB_NAME${NC}"
echo ""
# Ждем немного, чтобы БД точно создалась
sleep 1
# Проверяем, что БД создана
echo "3. Проверка существования тестовой БД..."
if [ -n "$POSTGRES_CONTAINER" ]; then
if echo "SELECT 1 FROM pg_database WHERE datname='$TEST_DB_NAME';" | $PG_PSQL_CMD -U $DB_USER -d postgres -t | grep -q 1; then
echo -e "${GREEN}✓ БД подтверждена${NC}"
else
echo -e "${RED}Ошибка: БД не найдена после создания${NC}"
exit 1
fi
fi
echo ""
# Применяем baseline миграцию
echo "4. Применение baseline миграции..."
cd "$(dirname "$0")" || exit 1
if [ -n "$POSTGRES_CONTAINER" ]; then
# Для Docker контейнеров используем psql напрямую, так как migrate может иметь проблемы с подключением
echo -e "${BLUE}Применение миграции через psql (Docker)...${NC}"
if [ -f "$MIGRATIONS_PATH/000001_baseline.up.sql" ]; then
if cat "$MIGRATIONS_PATH/000001_baseline.up.sql" | $PG_PSQL_CMD -U $DB_USER -d $TEST_DB_NAME > /dev/null 2>&1; then
echo -e "${GREEN}✓ Миграция применена через psql${NC}"
# Создаем таблицу schema_migrations вручную для migrate
echo "CREATE TABLE IF NOT EXISTS schema_migrations (version bigint NOT NULL PRIMARY KEY, dirty boolean NOT NULL);" | $PG_PSQL_CMD -U $DB_USER -d $TEST_DB_NAME > /dev/null 2>&1
echo "INSERT INTO schema_migrations (version, dirty) VALUES (1, false) ON CONFLICT (version) DO UPDATE SET dirty = false;" | $PG_PSQL_CMD -U $DB_USER -d $TEST_DB_NAME > /dev/null 2>&1
MIGRATE_SUCCESS=false # Устанавливаем в false, чтобы использовать psql для проверки версии
else
echo -e "${RED}Ошибка: Не удалось применить миграцию через psql${NC}"
exit 1
fi
else
echo -e "${RED}Ошибка: Файл миграции не найден${NC}"
exit 1
fi
DATABASE_URL="postgres://$DB_USER:$DB_PASSWORD@localhost:$DB_PORT/$TEST_DB_NAME?sslmode=disable"
else
DATABASE_URL="postgres://$DB_USER:$DB_PASSWORD@$DB_HOST:$DB_PORT/$TEST_DB_NAME?sslmode=disable"
if ! migrate -path "$MIGRATIONS_PATH" -database "$DATABASE_URL" up; then
echo -e "${RED}Ошибка: Не удалось применить baseline миграцию${NC}"
exit 1
fi
fi
echo -e "${GREEN}✓ Baseline миграция применена${NC}"
echo ""
# Проверяем версию миграции
echo "5. Проверка версии миграции..."
if [ -n "$POSTGRES_CONTAINER" ] && [ "${MIGRATE_SUCCESS:-false}" = "false" ]; then
# Проверяем версию через psql
VERSION=$(echo "SELECT version FROM schema_migrations;" | $PG_PSQL_CMD -U $DB_USER -d $TEST_DB_NAME -t 2>/dev/null | tr -d ' ' | head -1)
if [ -n "$VERSION" ] && [ "$VERSION" != "" ]; then
echo " Версия: $VERSION"
if [ "$VERSION" = "1" ]; then
echo -e "${GREEN}✓ Версия миграции корректна${NC}"
else
echo -e "${YELLOW}⚠ Неожиданная версия миграции: $VERSION${NC}"
fi
else
echo -e "${YELLOW}Не удалось определить версию миграции${NC}"
fi
else
# Используем migrate для проверки версии
VERSION=$(migrate -path "$MIGRATIONS_PATH" -database "$DATABASE_URL" version 2>&1)
echo " Версия: $VERSION"
if echo "$VERSION" | grep -qE "^1"; then
echo -e "${GREEN}✓ Версия миграции корректна${NC}"
else
echo -e "${YELLOW}⚠ Неожиданная версия миграции${NC}"
fi
fi
echo ""
# Экспортируем схему из тестовой БД (если pg_dump доступен)
if [ "$HAS_PG_DUMP" = true ]; then
echo "6. Экспорт схемы из тестовой БД..."
if [ -n "$POSTGRES_CONTAINER" ]; then
$PG_DUMP_CMD -U $DB_USER -d $TEST_DB_NAME --schema-only --no-owner --no-privileges > "$TMP_DIR/baseline_schema.sql"
else
PGPASSWORD=$DB_PASSWORD $PG_DUMP_CMD \
-h $DB_HOST \
-p $DB_PORT \
-U $DB_USER \
-d $TEST_DB_NAME \
--schema-only \
--no-owner \
--no-privileges \
-f "$TMP_DIR/baseline_schema.sql"
fi
if [ $? -ne 0 ]; then
echo -e "${RED}Ошибка: Не удалось экспортировать схему${NC}"
exit 1
fi
echo -e "${GREEN}✓ Схема экспортирована${NC}"
echo ""
# Пытаемся экспортировать схему из production БД для сравнения
echo "7. Экспорт схемы из production БД для сравнения..."
if [ -n "$POSTGRES_CONTAINER" ]; then
if $PG_DUMP_CMD -U $DB_USER -d $DB_NAME --schema-only --no-owner --no-privileges > "$TMP_DIR/production_schema.sql" 2>/dev/null; then
PROD_EXPORT_SUCCESS=true
else
PROD_EXPORT_SUCCESS=false
fi
else
if PGPASSWORD=$DB_PASSWORD $PG_DUMP_CMD \
-h $DB_HOST \
-p $DB_PORT \
-U $DB_USER \
-d $DB_NAME \
--schema-only \
--no-owner \
--no-privileges \
-f "$TMP_DIR/production_schema.sql" 2>/dev/null; then
PROD_EXPORT_SUCCESS=true
else
PROD_EXPORT_SUCCESS=false
fi
fi
if [ "$PROD_EXPORT_SUCCESS" = true ]; then
echo -e "${GREEN}✓ Схема production экспортирована${NC}"
echo ""
# Сравниваем схемы
echo "8. Сравнение схем..."
# Подсчитываем объекты
echo -e "${BLUE}Таблицы:${NC}"
BASELINE_TABLES=$(grep -c "CREATE TABLE" "$TMP_DIR/baseline_schema.sql" || echo "0")
PROD_TABLES=$(grep -c "CREATE TABLE" "$TMP_DIR/production_schema.sql" || echo "0")
echo " Baseline: $BASELINE_TABLES"
echo " Production: $PROD_TABLES"
if [ "$BASELINE_TABLES" -eq "$PROD_TABLES" ]; then
echo -e " ${GREEN}✓ Количество таблиц совпадает${NC}"
else
echo -e " ${YELLOW}⚠ Количество таблиц не совпадает${NC}"
fi
echo ""
echo -e "${BLUE}Индексы:${NC}"
BASELINE_INDEXES=$(grep -c "CREATE.*INDEX" "$TMP_DIR/baseline_schema.sql" || echo "0")
PROD_INDEXES=$(grep -c "CREATE.*INDEX" "$TMP_DIR/production_schema.sql" || echo "0")
echo " Baseline: $BASELINE_INDEXES"
echo " Production: $PROD_INDEXES"
if [ "$BASELINE_INDEXES" -eq "$PROD_INDEXES" ]; then
echo -e " ${GREEN}✓ Количество индексов совпадает${NC}"
else
echo -e " ${YELLOW}⚠ Количество индексов не совпадает${NC}"
fi
echo ""
echo -e "${BLUE}Materialized Views:${NC}"
BASELINE_MV=$(grep -c "CREATE MATERIALIZED VIEW" "$TMP_DIR/baseline_schema.sql" || echo "0")
PROD_MV=$(grep -c "CREATE MATERIALIZED VIEW" "$TMP_DIR/production_schema.sql" || echo "0")
echo " Baseline: $BASELINE_MV"
echo " Production: $PROD_MV"
if [ "$BASELINE_MV" -eq "$PROD_MV" ]; then
echo -e " ${GREEN}✓ Количество materialized views совпадает${NC}"
else
echo -e " ${YELLOW}⚠ Количество materialized views не совпадает${NC}"
fi
echo ""
echo "Для детального сравнения выполните:"
echo " diff $TMP_DIR/baseline_schema.sql $TMP_DIR/production_schema.sql"
echo ""
echo "Или используйте:"
echo " diff -u $TMP_DIR/baseline_schema.sql $TMP_DIR/production_schema.sql | less"
else
echo -e "${YELLOW}Не удалось экспортировать схему production БД${NC}"
echo " Продолжаем без сравнения"
echo ""
echo "Схема baseline сохранена в: $TMP_DIR/baseline_schema.sql"
fi
else
echo "6. Пропуск экспорта схемы (pg_dump недоступен)"
echo ""
echo -e "${YELLOW}Для полного тестирования установите PostgreSQL client tools:${NC}"
echo " macOS: brew install postgresql"
echo " или используйте Docker контейнер с PostgreSQL"
echo ""
fi
echo ""
echo "=== Тестирование завершено ==="
echo ""
echo -e "${GREEN}✓ Baseline миграция успешно применена к чистой БД${NC}"
echo ""