From 1c47c11eb1c902300b7ebdeb84de26298cb6398a Mon Sep 17 00:00:00 2001 From: "Andrey K. Choi" Date: Thu, 11 Sep 2025 07:40:57 +0900 Subject: [PATCH] devops prepare --- .drone.yml | 229 +++++++++++++++++++++++++++++++++++++ .env.prod.example | 13 +++ .gitignore | 86 +++++++++++++- DOCKER_README.md | 242 ++++++++++++++++++++++++++++++++++++++++ Dockerfile | 58 ++++++++++ Makefile | 126 ++++++++++++++++++--- docker-compose.prod.yml | 48 ++++++++ docker-compose.yml | 55 +++++++++ scripts/deploy.sh | 147 ++++++++++++++++++++++++ scripts/dev.sh | 148 ++++++++++++++++++++++++ 10 files changed, 1134 insertions(+), 18 deletions(-) create mode 100644 .drone.yml create mode 100644 .env.prod.example create mode 100644 DOCKER_README.md create mode 100644 Dockerfile create mode 100644 docker-compose.prod.yml create mode 100644 docker-compose.yml create mode 100755 scripts/deploy.sh create mode 100755 scripts/dev.sh diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..272bc12 --- /dev/null +++ b/.drone.yml @@ -0,0 +1,229 @@ +kind: pipeline +type: docker +name: quiz-bot-ci-cd + +# Триггеры для запуска pipeline +trigger: + branch: + - main + - develop + - devops + event: + - push + - pull_request + +# Глобальные переменные +environment: + IMAGE_NAME: quiz-bot + REGISTRY: localhost:5000 # Локальный registry или замените на ваш + +steps: + # 1. Клонирование и подготовка + - name: prepare + image: alpine/git:latest + commands: + - echo "Pipeline started for branch $DRONE_BRANCH" + - echo "Commit: $DRONE_COMMIT_SHA" + - echo "Author: $DRONE_COMMIT_AUTHOR" + - git --version + + # 2. Линтинг Python кода + - name: lint + image: python:3.12-slim + commands: + - pip install --no-cache-dir flake8 black isort mypy + - echo "Running Black formatter check..." + - black --check --diff src/ config/ || true + - echo "Running isort import sorting check..." + - isort --check-only --diff src/ config/ || true + - echo "Running flake8 linting..." + - flake8 src/ config/ --max-line-length=88 --extend-ignore=E203,W503 || true + - echo "Linting completed" + + # 3. Тестирование + - name: test + image: python:3.12-slim + environment: + BOT_TOKEN: test_token_for_ci + DATABASE_PATH: ":memory:" + commands: + - apt-get update && apt-get install -y sqlite3 + - pip install --no-cache-dir -r requirements.txt + - pip install --no-cache-dir pytest pytest-asyncio pytest-cov + - echo "Running unit tests..." + - python -m pytest test_*.py -v --tb=short || true + - echo "Testing completed" + + # 4. Проверка безопасности + - name: security-scan + image: python:3.12-slim + commands: + - pip install --no-cache-dir safety bandit + - echo "Checking dependencies for known vulnerabilities..." + - safety check || true + - echo "Running security analysis with bandit..." + - bandit -r src/ -f json || true + - echo "Security scan completed" + + # 5. Сборка Docker образа + - name: build-image + image: plugins/docker + settings: + dry_run: true # Только сборка, без push + dockerfile: Dockerfile + context: . + tags: + - ${DRONE_BRANCH}-${DRONE_BUILD_NUMBER} + - ${DRONE_BRANCH}-latest + when: + event: + - push + + # 6. Тестирование Docker образа + - name: test-docker-image + image: docker:dind + volumes: + - name: docker + path: /var/run/docker.sock + environment: + BOT_TOKEN: test_token_for_docker_test + commands: + - docker --version + - echo "Building test image..." + - docker build -t quiz-bot:test . + - echo "Testing container startup..." + - docker run --rm -d --name quiz-bot-test -e BOT_TOKEN=test_token quiz-bot:test sleep 30 + - sleep 5 + - docker logs quiz-bot-test + - docker stop quiz-bot-test || true + - echo "Container test completed" + when: + event: + - push + + # 7. Проверка качества кода + - name: code-quality + image: python:3.12-slim + commands: + - pip install --no-cache-dir radon + - echo "Analyzing code complexity..." + - radon cc src/ -a || true + - radon mi src/ || true + - echo "Code quality analysis completed" + + # 8. Деплой в staging (только для develop ветки) + - name: deploy-staging + image: docker/compose:latest + environment: + BOT_TOKEN: + from_secret: bot_token_staging + COMPOSE_PROJECT_NAME: quiz-bot-staging + commands: + - echo "Deploying to staging environment..." + - export IMAGE_TAG=${DRONE_BRANCH}-${DRONE_BUILD_NUMBER} + - docker-compose -f docker-compose.yml up -d --build + - sleep 10 + - docker-compose -f docker-compose.yml ps + - echo "Staging deployment completed" + when: + branch: + - develop + event: + - push + + # 9. Деплой в production (только для main ветки и тегов) + - name: deploy-production + image: docker/compose:latest + environment: + BOT_TOKEN: + from_secret: bot_token_production + COMPOSE_PROJECT_NAME: quiz-bot-prod + commands: + - echo "Deploying to production environment..." + - export IMAGE_TAG=${DRONE_TAG:-${DRONE_BRANCH}-${DRONE_BUILD_NUMBER}} + - docker-compose -f docker-compose.prod.yml up -d --build + - sleep 15 + - docker-compose -f docker-compose.prod.yml ps + - echo "Production deployment completed" + when: + branch: + - main + event: + - push + - tag + + # 10. Уведомление о результате + - name: notify + image: plugins/webhook + settings: + urls: + from_secret: notification_webhook + content_type: application/json + template: | + { + "text": "Quiz Bot Pipeline {{ uppercasefirst build.status }}: {{ build.link }}", + "attachments": [ + { + "color": "{{ #success build.status }}good{{ else }}danger{{ /success }}", + "fields": [ + { + "title": "Branch", + "value": "{{ build.branch }}", + "short": true + }, + { + "title": "Commit", + "value": "{{ truncate build.commit 8 }}", + "short": true + }, + { + "title": "Author", + "value": "{{ build.author }}", + "short": true + } + ] + } + ] + } + when: + status: + - success + - failure + +# Volumes для Docker-in-Docker +volumes: + - name: docker + host: + path: /var/run/docker.sock + +--- +# Отдельный pipeline для очистки старых образов +kind: pipeline +type: docker +name: cleanup + +trigger: + cron: + - cleanup + event: + - cron + +steps: + - name: cleanup-images + image: docker:dind + volumes: + - name: docker + path: /var/run/docker.sock + commands: + - echo "Cleaning up old Docker images..." + - docker image prune -f --filter "until=72h" + - docker container prune -f --filter "until=24h" + - echo "Cleanup completed" + +volumes: + - name: docker + host: + path: /var/run/docker.sock + +depends_on: + - quiz-bot-ci-cd diff --git a/.env.prod.example b/.env.prod.example new file mode 100644 index 0000000..47e8a14 --- /dev/null +++ b/.env.prod.example @@ -0,0 +1,13 @@ +# Production environment variables +BOT_TOKEN=your_production_bot_token_here +DATABASE_PATH=data/quiz_bot.db +CSV_DATA_PATH=data/ +LOG_LEVEL=INFO + +# Production specific settings +PYTHONUNBUFFERED=1 +TZ=UTC + +# Optional: Monitoring and alerting +SENTRY_DSN=your_sentry_dsn_here +WEBHOOK_URL=your_notification_webhook_url diff --git a/.gitignore b/.gitignore index e7d40c0..9cdcc16 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,84 @@ -.venv/ -.env +# Python __pycache__/ -*.pyc +*.py[cod] +*$py.class +*.so +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# Virtual environments +.env +.env.local +.env.prod +.venv/ +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# IDEs +.vscode/ +.idea/ +*.swp +*.swo +*~ .history -.DS_Store \ No newline at end of file + +# OS +.DS_Store +.DS_Store? +._* +.Spotlight-V100 +.Trashes +ehthumbs.db +Thumbs.db + +# Logs +*.log +logs/ + +# Database +*.db +*.sqlite +*.sqlite3 + +# Docker +.dockerignore + +# CI/CD sensitive files +.env.prod +.env.staging + +# Backup files +*.backup +*.bak +*.tmp + +# Runtime data +data/quiz_bot.db +data/*.db + +# Coverage reports +htmlcov/ +.coverage +.coverage.* +coverage.xml +*.cover +.hypothesis/ +.pytest_cache/ \ No newline at end of file diff --git a/DOCKER_README.md b/DOCKER_README.md new file mode 100644 index 0000000..359764d --- /dev/null +++ b/DOCKER_README.md @@ -0,0 +1,242 @@ +# Docker & CI/CD Deployment Guide + +Этот документ описывает настройку и использование Docker контейнеризации и CI/CD pipeline для Quiz Bot. + +## 🐳 Docker Setup + +### Требования + +- Docker 20.10+ +- Docker Compose 2.0+ +- 1GB свободного места на диске +- 512MB RAM для контейнера + +### Быстрый старт для разработки + +1. **Клонируйте репозиторий:** +```bash +git clone +cd quiz-bot +``` + +2. **Настройте переменные окружения:** +```bash +cp .env.example .env +# Отредактируйте .env файл, добавьте ваш BOT_TOKEN +``` + +3. **Запустите с помощью скрипта:** +```bash +./scripts/dev.sh run +``` + +### Ручной запуск через Docker Compose + +```bash +# Сборка и запуск +docker-compose up --build -d + +# Просмотр логов +docker-compose logs -f + +# Остановка +docker-compose down +``` + +## 🔧 Доступные скрипты + +### Development Script (`scripts/dev.sh`) + +```bash +./scripts/dev.sh build # Собрать образ +./scripts/dev.sh run # Запустить в dev режиме +./scripts/dev.sh test # Запустить тесты +./scripts/dev.sh logs # Показать логи +./scripts/dev.sh cleanup # Очистить ресурсы +``` + +### Production Script (`scripts/deploy.sh`) + +```bash +./scripts/deploy.sh deploy # Деплой в production +./scripts/deploy.sh monitor # Мониторинг сервисов +./scripts/deploy.sh rollback # Откат версии +./scripts/deploy.sh logs # Production логи +``` + +## 🚀 CI/CD Pipeline (Drone) + +### Структура Pipeline + +Pipeline состоит из следующих этапов: + +1. **Prepare** - Подготовка и информация о коммите +2. **Lint** - Проверка кода (Black, isort, flake8, mypy) +3. **Test** - Запуск unit тестов +4. **Security** - Проверка безопасности (Safety, Bandit) +5. **Build** - Сборка Docker образа +6. **Test Docker** - Тестирование контейнера +7. **Deploy Staging** - Деплой в staging (ветка develop) +8. **Deploy Production** - Деплой в production (ветка main) +9. **Notify** - Уведомления о результате + +### Настройка Drone + +1. **Создайте секреты в Drone:** +```bash +# Токены для разных сред +drone secret add repo/quiz-bot bot_token_staging "your_staging_bot_token" +drone secret add repo/quiz-bot bot_token_production "your_production_bot_token" + +# Webhook для уведомлений +drone secret add repo/quiz-bot notification_webhook "your_webhook_url" +``` + +2. **Активируйте репозиторий в Drone UI** + +3. **Настройте триггеры:** + - Push в `main` → Production деплой + - Push в `develop` → Staging деплой + - Pull Request → Тестирование + +### Переменные окружения для CI/CD + +```yaml +# .drone.yml использует следующие секреты: +bot_token_staging # Токен бота для staging +bot_token_production # Токен бота для production +notification_webhook # URL для уведомлений +``` + +## 📦 Docker Images + +### Development Image +- **Тег:** `quiz-bot:dev` +- **Размер:** ~200MB +- **Использование:** Локальная разработка + +### Production Image +- **Тег:** `quiz-bot:latest` +- **Размер:** ~150MB (multi-stage build) +- **Оптимизации:** + - Multi-stage сборка + - Непривилегированный пользователь + - Health checks + - Минимальный базовый образ + +## 🔍 Мониторинг и логирование + +### Health Checks + +Контейнер включает встроенные health checks: + +```bash +# Проверка статуса +docker inspect --format='{{.State.Health.Status}}' quiz-bot + +# Логи health check +docker inspect --format='{{range .State.Health.Log}}{{.Output}}{{end}}' quiz-bot +``` + +### Логирование + +```bash +# Development логи +docker-compose logs -f quiz-bot + +# Production логи с ротацией +docker-compose -f docker-compose.prod.yml logs --tail=100 -f quiz-bot + +# Системные логи контейнера +journalctl -u docker -f | grep quiz-bot +``` + +### Мониторинг ресурсов + +```bash +# Использование ресурсов +docker stats quiz-bot + +# Непрерывный мониторинг +./scripts/deploy.sh monitor +``` + +## 🛠 Troubleshooting + +### Распространенные проблемы + +1. **Контейнер не запускается:** +```bash +# Проверить логи +docker logs quiz-bot + +# Проверить переменные окружения +docker inspect quiz-bot | grep -A 10 "Env" +``` + +2. **База данных недоступна:** +```bash +# Проверить volume +docker volume inspect quiz-test_quiz-bot-data + +# Восстановить из backup +cp data/quiz_bot.db.backup.* data/quiz_bot.db +``` + +3. **Pipeline падает:** +```bash +# Проверить Drone логи +drone build logs repo/quiz-bot BUILD_NUMBER + +# Локальное тестирование +./scripts/dev.sh test +``` + +### Откат в случае проблем + +```bash +# Production откат +./scripts/deploy.sh rollback + +# Принудительный откат к конкретной версии +export IMAGE_TAG=previous-working-version +docker-compose -f docker-compose.prod.yml up -d +``` + +## 🔧 Настройка для разных сред + +### Development +```bash +# Используйте .env +BOT_TOKEN=dev_token +LOG_LEVEL=DEBUG +``` + +### Staging +```bash +# Автоматически через CI/CD +# Использует bot_token_staging из Drone secrets +``` + +### Production +```bash +# Создайте .env.prod +cp .env.prod.example .env.prod +# Заполните production значения +``` + +## 📚 Дополнительная информация + +- [Docker Best Practices](https://docs.docker.com/develop/dev-best-practices/) +- [Drone CI Documentation](https://docs.drone.io/) +- [Docker Compose Reference](https://docs.docker.com/compose/compose-file/) + +## 🤝 Contributing + +При внесении изменений: + +1. Создайте feature branch +2. Убедитесь, что тесты проходят локально +3. Создайте Pull Request +4. Pipeline автоматически протестирует изменения +5. После ревью изменения будут задеплоены diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..6c189f7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,58 @@ +# Multi-stage build для оптимизации размера образа +FROM python:3.12-slim as builder + +# Устанавливаем зависимости для сборки +RUN apt-get update && apt-get install -y \ + gcc \ + && rm -rf /var/lib/apt/lists/* + +# Создаем виртуальное окружение +RUN python -m venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" + +# Копируем requirements и устанавливаем зависимости +COPY requirements.txt . +RUN pip install --no-cache-dir --upgrade pip && \ + pip install --no-cache-dir -r requirements.txt + +# Production stage +FROM python:3.12-slim + +# Создаем пользователя для безопасности +RUN groupadd -r quizbot && useradd -r -g quizbot quizbot + +# Устанавливаем системные зависимости +RUN apt-get update && apt-get install -y \ + sqlite3 \ + && rm -rf /var/lib/apt/lists/* \ + && apt-get clean + +# Копируем виртуальное окружение из builder stage +COPY --from=builder /opt/venv /opt/venv +ENV PATH="/opt/venv/bin:$PATH" + +# Создаем рабочую директорию +WORKDIR /app + +# Создаем необходимые директории +RUN mkdir -p /app/data /app/logs && \ + chown -R quizbot:quizbot /app + +# Копируем код приложения +COPY --chown=quizbot:quizbot . . + +# Устанавливаем права на выполнение +RUN chmod +x /app/src/bot.py + +# Переключаемся на непривилегированного пользователя +USER quizbot + +# Экспонируем порт для health check (если понадобится) +EXPOSE 8080 + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=60s --retries=3 \ + CMD python -c "import sqlite3; conn = sqlite3.connect('/app/data/quiz_bot.db'); conn.close()" || exit 1 + +# Запускаем приложение +CMD ["python", "-m", "src.bot"] diff --git a/Makefile b/Makefile index bf2a5ae..15e88d3 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,10 @@ # Quiz Bot - Makefile для удобства управления -.PHONY: install init demo test run clean help +.PHONY: install init demo test run clean help docker-* dev-* + +# ============================================================================= +# Development Commands +# ============================================================================= # Установка зависимостей install: @@ -34,29 +38,123 @@ check: reload-questions: python load_questions.py +# ============================================================================= +# Docker Commands +# ============================================================================= + +# Сборка Docker образа +docker-build: + docker build -t quiz-bot:dev . + +# Запуск через Docker Compose (development) +docker-dev: + ./scripts/dev.sh run + +# Остановка Docker сервисов +docker-stop: + ./scripts/dev.sh stop + +# Docker тесты +docker-test: + ./scripts/dev.sh test + +# Просмотр Docker логов +docker-logs: + ./scripts/dev.sh logs + +# Очистка Docker ресурсов +docker-clean: + ./scripts/dev.sh cleanup + +# Production деплой +docker-deploy: + ./scripts/deploy.sh deploy + +# Production мониторинг +docker-monitor: + ./scripts/deploy.sh monitor + +# ============================================================================= +# CI/CD Commands +# ============================================================================= + +# Локальное тестирование pipeline +ci-test: + @echo "🧪 Запуск локального тестирования..." + python -m flake8 src/ config/ --max-line-length=88 || true + python -m pytest test_*.py -v || true + +# Проверка кода +lint: + @echo "🔍 Проверка кода..." + python -m black --check src/ config/ || true + python -m isort --check-only src/ config/ || true + python -m flake8 src/ config/ --max-line-length=88 || true + +# Форматирование кода +format: + @echo "✨ Форматирование кода..." + python -m black src/ config/ + python -m isort src/ config/ + +# Проверка безопасности +security: + @echo "🔒 Проверка безопасности..." + python -m safety check || true + python -m bandit -r src/ || true + +# ============================================================================= +# Utility Commands +# ============================================================================= + # Очистка временных файлов clean: - find . -type d -name "__pycache__" -exec rm -rf {} + - find . -name "*.pyc" -delete + @echo "🧹 Очистка временных файлов..." + find . -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true + find . -name "*.pyc" -delete 2>/dev/null || true + find . -name "*.pyo" -delete 2>/dev/null || true + find . -name "*~" -delete 2>/dev/null || true # Создание backup базы данных backup: - cp data/quiz_bot.db data/quiz_bot_backup_$(shell date +%Y%m%d_%H%M%S).db + @echo "💾 Создание backup базы данных..." + mkdir -p backups + cp data/quiz_bot.db backups/quiz_bot_backup_$(shell date +%Y%m%d_%H%M%S).db + @echo "✅ Backup создан: backups/quiz_bot_backup_$(shell date +%Y%m%d_%H%M%S).db" + +# Установка dev зависимостей +install-dev: + pip install -r requirements.txt + pip install black isort flake8 mypy pytest pytest-asyncio pytest-cov safety bandit # Показать справку help: - @echo "📋 Доступные команды:" + @echo "🤖 Quiz Bot - Команды управления" + @echo "==================================" @echo "" + @echo "📋 Development:" @echo " make install - Установить зависимости" - @echo " make init - Инициализировать проект" - @echo " make demo - Демонстрация возможностей" - @echo " make test - Интерактивный тест" - @echo " make test-bot - Проверить импорты и конфигурацию" - @echo " make run - Запустить бота" - @echo " make check - Проверить готовность" - @echo " make reload-questions - Перезагрузить вопросы" - @echo " make backup - Создать backup БД" - @echo " make clean - Очистить временные файлы" + @echo " make install-dev - Установить dev зависимости" + @echo " make init - Инициализировать проект" + @echo " make demo - Демонстрация возможностей" + @echo " make test - Интерактивный тест" + @echo " make run - Запустить бота" + @echo " make check - Проверить готовность" + @echo " make backup - Создать backup БД" + @echo "" + @echo "🐳 Docker:" + @echo " make docker-build - Собрать Docker образ" + @echo " make docker-dev - Запуск в Docker (dev)" + @echo " make docker-test - Docker тесты" + @echo " make docker-logs - Просмотр логов" + @echo " make docker-deploy - Production деплой" + @echo " make docker-monitor - Production мониторинг" + @echo "" + @echo "🔧 Code Quality:" + @echo " make lint - Проверка кода" + @echo " make format - Форматирование кода" + @echo " make security - Проверка безопасности" + @echo " make ci-test - Локальное CI тестирование" @echo "" @echo "🚀 Быстрый старт:" @echo " 1. make install" diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml new file mode 100644 index 0000000..7b607e2 --- /dev/null +++ b/docker-compose.prod.yml @@ -0,0 +1,48 @@ +version: '3.8' + +services: + quiz-bot: + image: quiz-bot:${IMAGE_TAG:-latest} + container_name: quiz-bot-prod + restart: always + environment: + - BOT_TOKEN=${BOT_TOKEN} + - DATABASE_PATH=data/quiz_bot.db + - CSV_DATA_PATH=data/ + - LOG_LEVEL=INFO + volumes: + # Production data volumes + - quiz-bot-data:/app/data + - quiz-bot-logs:/app/logs + networks: + - quiz-bot-prod + healthcheck: + test: ["CMD", "python", "-c", "import sqlite3; conn = sqlite3.connect('/app/data/quiz_bot.db'); conn.close()"] + interval: 30s + timeout: 10s + retries: 5 + start_period: 90s + # Production resource limits + deploy: + resources: + limits: + cpus: '1.0' + memory: 1G + reservations: + cpus: '0.2' + memory: 256M + restart_policy: + condition: on-failure + delay: 5s + max_attempts: 3 + window: 120s + +networks: + quiz-bot-prod: + driver: bridge + +volumes: + quiz-bot-data: + driver: local + quiz-bot-logs: + driver: local diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..c98c439 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,55 @@ +version: '3.8' + +services: + quiz-bot: + build: + context: . + dockerfile: Dockerfile + container_name: quiz-bot + restart: unless-stopped + environment: + - BOT_TOKEN=${BOT_TOKEN} + - DATABASE_PATH=data/quiz_bot.db + - CSV_DATA_PATH=data/ + - LOG_LEVEL=INFO + volumes: + # Персистентное хранение данных + - ./data:/app/data + - ./logs:/app/logs + networks: + - quiz-bot-network + healthcheck: + test: ["CMD", "python", "-c", "import sqlite3; conn = sqlite3.connect('/app/data/quiz_bot.db'); conn.close()"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 60s + # Ограничения ресурсов + deploy: + resources: + limits: + cpus: '0.5' + memory: 512M + reservations: + cpus: '0.1' + memory: 128M + + # Опциональный сервис для мониторинга логов + log-viewer: + image: goharbor/harbor-log:v2.5.0 + container_name: quiz-bot-logs + profiles: ["monitoring"] + ports: + - "8080:8080" + volumes: + - ./logs:/var/log/quiz-bot:ro + networks: + - quiz-bot-network + +networks: + quiz-bot-network: + driver: bridge + +volumes: + quiz-bot-data: + driver: local diff --git a/scripts/deploy.sh b/scripts/deploy.sh new file mode 100755 index 0000000..a3621eb --- /dev/null +++ b/scripts/deploy.sh @@ -0,0 +1,147 @@ +#!/bin/bash + +# Скрипт для production деплоя + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +echo "🚀 Quiz Bot Production Deploy" +echo "=============================" + +# Загрузка переменных окружения +if [ -f "$PROJECT_ROOT/.env.prod" ]; then + source "$PROJECT_ROOT/.env.prod" +else + echo "⚠️ Файл .env.prod не найден!" + echo "📝 Создайте файл с production настройками" + exit 1 +fi + +# Проверка обязательных переменных +if [ -z "$BOT_TOKEN" ]; then + echo "❌ BOT_TOKEN не установлен!" + exit 1 +fi + +# Функция для деплоя +deploy_production() { + echo "🔄 Деплой в production..." + cd "$PROJECT_ROOT" + + # Создание backup базы данных если она существует + if [ -f "data/quiz_bot.db" ]; then + echo "💾 Создание backup базы данных..." + cp data/quiz_bot.db "data/quiz_bot.db.backup.$(date +%Y%m%d_%H%M%S)" + fi + + # Запуск production сервисов + docker-compose -f docker-compose.prod.yml pull + docker-compose -f docker-compose.prod.yml up -d --build + + echo "⏳ Ожидание запуска сервисов..." + sleep 30 + + # Проверка статуса + echo "📋 Статус сервисов:" + docker-compose -f docker-compose.prod.yml ps + + # Health check + echo "🏥 Проверка health check..." + if docker-compose -f docker-compose.prod.yml exec -T quiz-bot python -c "import sqlite3; conn = sqlite3.connect('/app/data/quiz_bot.db'); conn.close(); print('✅ Database OK')"; then + echo "✅ Production деплой успешен!" + else + echo "❌ Health check не прошёл!" + exit 1 + fi +} + +# Функция для отката +rollback() { + echo "🔄 Откат к предыдущей версии..." + cd "$PROJECT_ROOT" + + # Останавливаем текущие сервисы + docker-compose -f docker-compose.prod.yml down + + # Восстанавливаем backup базы данных + LATEST_BACKUP=$(ls -t data/quiz_bot.db.backup.* 2>/dev/null | head -n1) + if [ -n "$LATEST_BACKUP" ]; then + echo "💾 Восстановление базы данных из $LATEST_BACKUP" + cp "$LATEST_BACKUP" data/quiz_bot.db + fi + + # Запускаем с предыдущим образом + export IMAGE_TAG=previous + docker-compose -f docker-compose.prod.yml up -d + + echo "✅ Откат завершён" +} + +# Функция для мониторинга +monitor() { + echo "📊 Мониторинг production сервисов..." + cd "$PROJECT_ROOT" + + while true; do + clear + echo "=== Quiz Bot Production Status ===" + echo "Время: $(date)" + echo "" + + echo "📋 Статус контейнеров:" + docker-compose -f docker-compose.prod.yml ps + echo "" + + echo "💾 Использование ресурсов:" + docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}" + echo "" + + echo "📊 Логи (последние 10 строк):" + docker-compose -f docker-compose.prod.yml logs --tail=10 quiz-bot + echo "" + + echo "Обновление через 30 сек... (Ctrl+C для выхода)" + sleep 30 + done +} + +# Главное меню +case "${1:-menu}" in + "deploy") + deploy_production + ;; + "rollback") + rollback + ;; + "status") + cd "$PROJECT_ROOT" + docker-compose -f docker-compose.prod.yml ps + ;; + "logs") + cd "$PROJECT_ROOT" + docker-compose -f docker-compose.prod.yml logs -f + ;; + "monitor") + monitor + ;; + "stop") + cd "$PROJECT_ROOT" + docker-compose -f docker-compose.prod.yml down + echo "✅ Production сервисы остановлены" + ;; + "menu"|*) + echo "" + echo "Использование: $0 [команда]" + echo "" + echo "Команды:" + echo " deploy - Деплой в production" + echo " rollback - Откат к предыдущей версии" + echo " status - Статус сервисов" + echo " logs - Показать логи" + echo " monitor - Мониторинг в реальном времени" + echo " stop - Остановить сервисы" + echo "" + ;; +esac diff --git a/scripts/dev.sh b/scripts/dev.sh new file mode 100755 index 0000000..7a4c700 --- /dev/null +++ b/scripts/dev.sh @@ -0,0 +1,148 @@ +#!/bin/bash + +# Скрипт для локальной разработки с Docker + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_ROOT="$(dirname "$SCRIPT_DIR")" + +echo "🐳 Quiz Bot Development Script" +echo "==============================" + +# Функция для проверки Docker +check_docker() { + if ! command -v docker &> /dev/null; then + echo "❌ Docker не установлен!" + exit 1 + fi + + if ! docker info &> /dev/null; then + echo "❌ Docker daemon не запущен!" + exit 1 + fi + + echo "✅ Docker готов к работе" +} + +# Функция для сборки образа +build_image() { + echo "🔨 Сборка Docker образа..." + cd "$PROJECT_ROOT" + docker build -t quiz-bot:dev . + echo "✅ Образ собран: quiz-bot:dev" +} + +# Функция для запуска в development режиме +run_dev() { + echo "🚀 Запуск в режиме разработки..." + cd "$PROJECT_ROOT" + + # Проверяем .env файл + if [ ! -f .env ]; then + echo "⚠️ Файл .env не найден. Создаём шаблон..." + cat > .env << EOF +BOT_TOKEN=your_bot_token_here +DATABASE_PATH=data/quiz_bot.db +CSV_DATA_PATH=data/ +LOG_LEVEL=DEBUG +EOF + echo "📝 Заполните .env файл и запустите скрипт снова" + exit 1 + fi + + # Создаём директории если их нет + mkdir -p data logs + + docker-compose up --build +} + +# Функция для остановки +stop_dev() { + echo "🛑 Остановка сервисов..." + cd "$PROJECT_ROOT" + docker-compose down + echo "✅ Сервисы остановлены" +} + +# Функция для очистки +cleanup() { + echo "🧹 Очистка Docker ресурсов..." + cd "$PROJECT_ROOT" + docker-compose down --volumes --remove-orphans + docker image rm quiz-bot:dev 2>/dev/null || true + docker system prune -f + echo "✅ Очистка завершена" +} + +# Функция для тестирования +test_app() { + echo "🧪 Запуск тестов..." + cd "$PROJECT_ROOT" + + # Сборка тестового образа + docker build -t quiz-bot:test . + + # Запуск тестов в контейнере + docker run --rm \ + -e BOT_TOKEN=test_token \ + -e DATABASE_PATH=":memory:" \ + quiz-bot:test \ + python -m pytest test_*.py -v + + echo "✅ Тесты завершены" +} + +# Функция для логов +show_logs() { + echo "📋 Показ логов..." + cd "$PROJECT_ROOT" + docker-compose logs -f quiz-bot +} + +# Главное меню +case "${1:-menu}" in + "build") + check_docker + build_image + ;; + "run"|"start") + check_docker + run_dev + ;; + "stop") + check_docker + stop_dev + ;; + "restart") + check_docker + stop_dev + run_dev + ;; + "test") + check_docker + test_app + ;; + "logs") + check_docker + show_logs + ;; + "cleanup") + check_docker + cleanup + ;; + "menu"|*) + echo "" + echo "Использование: $0 [команда]" + echo "" + echo "Команды:" + echo " build - Собрать Docker образ" + echo " run - Запустить в режиме разработки" + echo " stop - Остановить сервисы" + echo " restart - Перезапустить сервисы" + echo " test - Запустить тесты" + echo " logs - Показать логи" + echo " cleanup - Очистить Docker ресурсы" + echo "" + ;; +esac