name: Deploy Mnemo Cards on: workflow_dispatch: push: branches: - master paths: - 'mnemo_cards_web_v2/**' - 'mnemo_cards_backend/**' - 'mnemo_cards_common/**' - 'mnemo_cards_common_backend/**' jobs: deploy-backend: name: Deploy Backend runs-on: ubuntu-latest steps: - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: '20' - name: Checkout code uses: actions/checkout@v3 - name: Install Dependencies run: | apt-get update && apt-get install -y rsync openssh-client - name: Setup SSH run: | mkdir -p ~/.ssh echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts - name: Sync Source Code run: | # Sync common packages rsync -avz --delete --exclude '.*' --exclude 'build' --exclude 'doc' \ mnemo_cards_common \ mnemo_cards_common_backend \ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:~/ # Sync backend project rsync -avz --delete --exclude '.*' --exclude 'build' --exclude 'server.exe' --exclude 'isar' \ mnemo_cards_backend \ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:~/ - name: Obtain Certificates run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e echo "🔐 Checking Let's Encrypt certificates..." # Проверяем наличие multi-domain сертификата if [ -d "/etc/letsencrypt/live/mnemo-cards.online" ] && [ -f "/etc/letsencrypt/live/mnemo-cards.online/fullchain.pem" ]; then echo "✅ Let's Encrypt multi-domain сертификаты уже существуют" # Проверяем что nginx работает if ! sudo systemctl is-active --quiet nginx; then echo "🚨 nginx не работает! Запускаем..." sudo systemctl start nginx sleep 2 if ! sudo systemctl is-active --quiet nginx; then echo "❌ Критическая ошибка: не удалось запустить nginx!" exit 1 fi fi else echo "⚠️ Сертификаты не найдены. Пытаемся получить через webroot (nginx продолжает работать)..." # Убеждаемся, что nginx запущен if ! sudo systemctl is-active --quiet nginx; then echo "🚀 Запускаем nginx для webroot режима..." sudo systemctl start nginx sleep 2 if ! sudo systemctl is-active --quiet nginx; then echo "❌ Критическая ошибка: не удалось запустить nginx для получения сертификатов!" exit 1 fi fi # Создаем директорию для webroot challenge sudo mkdir -p /var/www/html/.well-known/acme-challenge sudo chown -R www-data:www-data /var/www/html # Убеждаемся, что nginx может обслуживать ACME challenge # Проверяем, есть ли конфигурация для /.well-known if ! grep -q "\.well-known" /etc/nginx/sites-enabled/* 2>/dev/null; then echo "📝 Добавляем поддержку ACME challenge в nginx..." # Создаем временную конфигурацию для ACME challenge sudo printf 'server {\n listen 80;\n server_name _;\n location /.well-known/acme-challenge/ {\n root /var/www/html;\n try_files $uri =404;\n }\n location / {\n return 404;\n }\n}\n' > /etc/nginx/sites-available/acme-challenge sudo ln -sf /etc/nginx/sites-available/acme-challenge /etc/nginx/sites-enabled/acme-challenge sudo nginx -t && sudo systemctl reload nginx fi # Получаем multi-domain сертификат через webroot echo "🔐 Получаем Let's Encrypt multi-domain сертификат через webroot..." if sudo certbot certonly --webroot \ -w /var/www/html \ -d mnemo-cards.online \ -d api.mnemo-cards.online \ -d code.mnemo-cards.online \ -d vscode.mnemo-cards.online \ --cert-name mnemo-cards.online \ --non-interactive --agree-tos --email admin@mnemo-cards.online; then echo "✅ Let's Encrypt multi-domain сертификат успешно получен через webroot!" else echo "⚠️ Не удалось получить сертификат через webroot. Продолжаем без HTTPS..." fi fi ENDSSH - name: Get Dependencies run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e cd ~/mnemo_cards_backend echo "📦 Getting dependencies..." dart pub get ENDSSH - name: Compile Server run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e cd ~/mnemo_cards_backend echo "🔨 Compiling server..." dart compile exe --verbose lib/main.dart -o server_build.exe ENDSSH - name: Stop Service run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e echo "🛑 Stopping backend service..." sudo systemctl stop mnemo_cards_server || true echo "✅ Backend service stopped" echo "🔍 Checking nginx status after stopping backend..." if sudo systemctl is-active --quiet nginx; then echo "✅ nginx still running" else echo "🚨 nginx also stopped! This is the problem!" echo "🚀 Starting nginx..." sudo systemctl start nginx sleep 2 if sudo systemctl is-active --quiet nginx; then echo "✅ nginx restarted" else echo "❌ Failed to restart nginx!" exit 1 fi fi ENDSSH - name: Update Service Configuration run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e cd ~/mnemo_cards_backend echo "⚙️ Updating service configuration..." sudo chmod 777 mnemo_cards_server.service sudo cp mnemo_cards_server.service /etc/systemd/system/ ENDSSH - name: Update Executable run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e cd ~/mnemo_cards_backend echo "🔄 Replacing executable..." sudo cp server_build.exe server.exe rm server_build.exe ENDSSH - name: Configure Certificates run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e # Check certificates and configure mode # Используем multi-domain сертификат mnemo-cards.online (если есть) if [ -d "/etc/letsencrypt/live/mnemo-cards.online" ] && [ -f "/etc/letsencrypt/live/mnemo-cards.online/fullchain.pem" ]; then echo "✅ Let's Encrypt multi-domain сертификат найден. Настраиваем HTTPS режим..." sudo sed -i 's|ExecStart=/root/mnemo_cards_backend/server.exe.*|ExecStart=/root/mnemo_cards_backend/server.exe --certs /etc/letsencrypt/live/mnemo-cards.online -a 0.0.0.0 -p 8081|' /etc/systemd/system/mnemo_cards_server.service elif [ -d "/etc/letsencrypt/live/api.mnemo-cards.online" ]; then echo "✅ Let's Encrypt сертификат для API найден. Настраиваем dual mode..." sudo sed -i 's|ExecStart=/root/mnemo_cards_backend/server.exe.*|ExecStart=/root/mnemo_cards_backend/server.exe --dual --certs /etc/letsencrypt/live/api.mnemo-cards.online -a 0.0.0.0 -p 8081|' /etc/systemd/system/mnemo_cards_server.service else echo "⚠️ No certificates found. Configuring HTTP mode..." sudo sed -i 's|ExecStart=/root/mnemo_cards_backend/server.exe.*|ExecStart=/root/mnemo_cards_backend/server.exe -a 0.0.0.0 -p 8081|' /etc/systemd/system/mnemo_cards_server.service fi ENDSSH - name: Restart Service run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e echo "🚀 Restarting service..." sudo systemctl daemon-reload sudo systemctl start mnemo_cards_server sleep 2 systemctl status mnemo_cards_server --no-pager ENDSSH - name: Ensure Nginx Running run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e echo "🔍 Проверяем статус nginx..." if sudo systemctl is-active --quiet nginx; then echo "✅ nginx уже запущен" # Перезагружаем конфигурацию на всякий случай if sudo nginx -t 2>/dev/null; then sudo systemctl reload nginx echo "✅ Конфигурация nginx перезагружена" fi else echo "⚠️ nginx не запущен, запускаем..." if sudo nginx -t 2>/dev/null; then sudo systemctl start nginx sleep 2 if sudo systemctl is-active --quiet nginx; then echo "✅ nginx успешно запущен" else echo "❌ Ошибка: не удалось запустить nginx!" sudo systemctl status nginx --no-pager || true exit 1 fi else echo "❌ Ошибка в конфигурации nginx!" sudo nginx -t || true exit 1 fi fi ENDSSH ensure-nginx-running: name: Ensure Nginx Running After Backend runs-on: ubuntu-latest needs: deploy-backend if: always() && needs.deploy-backend.result == 'success' steps: - name: Setup SSH run: | mkdir -p ~/.ssh echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts - name: Check Nginx Status run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e echo "🔍 Проверяем статус nginx после деплоя backend..." if sudo systemctl is-active --quiet nginx; then echo "✅ nginx запущен" # Тестируем доступность сайтов if curl -I --max-time 10 https://code.mnemo-cards.online/ 2>/dev/null | grep -q "200\|301\|302"; then echo "✅ code.mnemo-cards.online доступен" else echo "⚠️ code.mnemo-cards.online недоступен" fi if curl -I --max-time 10 https://vscode.mnemo-cards.online/ 2>/dev/null | grep -q "200\|301\|302"; then echo "✅ vscode.mnemo-cards.online доступен" else echo "⚠️ vscode.mnemo-cards.online недоступен" fi else echo "❌ nginx не запущен! Запускаем..." sudo systemctl start nginx sleep 2 if sudo systemctl is-active --quiet nginx; then echo "✅ nginx запущен" else echo "❌ Не удалось запустить nginx!" sudo systemctl status nginx --no-pager || true exit 1 fi fi ENDSSH deploy-web: name: Deploy Web App runs-on: ubuntu-latest container: ghcr.io/cirruslabs/flutter:3.35.5 needs: ensure-nginx-running if: always() && needs.ensure-nginx-running.result == 'success' steps: - name: Install System Dependencies run: | apt-get update && apt-get install -y rsync openssh-client jq git curl wget gnupg2 software-properties-common ca-certificates - name: Setup Node.js run: | # Install Node.js manually in container curl -fsSL https://deb.nodesource.com/setup_20.x | bash - apt-get install -y nodejs echo "Node.js version: $(node --version)" echo "NPM version: $(npm --version)" - name: Setup SSH run: | mkdir -p ~/.ssh echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa chmod 600 ~/.ssh/id_rsa ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts - name: Checkout code uses: actions/checkout@v3 with: fetch-depth: 0 lfs: false - name: Configure Git run: | git config --global http.postBuffer 52428800 git config --global http.maxRequestBuffer 100M git config --global core.compression 0 - name: Check Nginx Before Web Deploy run: | echo "🔍 Проверяем статус nginx перед деплоем web..." ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e if sudo systemctl is-active --quiet nginx; then echo "✅ nginx работает перед web деплоем" # Тестируем доступность if curl -I --max-time 5 https://mnemo-cards.online/ 2>/dev/null | grep -q "200\|301\|302"; then echo "✅ mnemo-cards.online доступен" else echo "⚠️ mnemo-cards.online недоступен" fi if curl -I --max-time 5 https://code.mnemo-cards.online/ 2>/dev/null | grep -q "200\|301\|302"; then echo "✅ code.mnemo-cards.online доступен" else echo "⚠️ code.mnemo-cards.online недоступен" fi else echo "❌ nginx не работает перед web деплоем!" exit 1 fi ENDSSH - name: Build Web App working-directory: mnemo_cards_web_v2 run: | which flutter || echo "Flutter not found in PATH" flutter --version || echo "Flutter command failed" flutter pub get flutter build web --release \ --dart-define=API_BASE_URL=https://api.mnemo-cards.online \ --dart2js-optimization=O4 - name: Deploy Web App run: | echo "📦 Копируем веб-приложение..." rsync -avz --delete mnemo_cards_web_v2/build/web/ \ ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/var/www/mnemo_cards/ echo "✅ Веб-приложение скопировано" - name: Fix Permissions and Verify run: | ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e echo "🔧 Исправляем права доступа..." chown -R www-data:www-data /var/www/mnemo_cards chmod -R 755 /var/www/mnemo_cards echo "✅ Права исправлены" echo "🔍 Проверяем nginx после деплоя web..." if sudo systemctl is-active --quiet nginx; then echo "✅ nginx работает" # Перезагружаем nginx для применения новых файлов echo "🔄 Перезагружаем nginx..." if sudo nginx -t 2>/dev/null; then sudo systemctl reload nginx echo "✅ nginx перезагружен" sleep 2 # Тестируем доступность if curl -I --max-time 10 https://mnemo-cards.online/ 2>/dev/null | grep -q "200\|301\|302"; then echo "✅ mnemo-cards.online доступен" else echo "⚠️ mnemo-cards.online недоступен" fi if curl -I --max-time 10 https://code.mnemo-cards.online/ 2>/dev/null | grep -q "200\|301\|302"; then echo "✅ code.mnemo-cards.online доступен" else echo "⚠️ code.mnemo-cards.online недоступен" fi else echo "❌ Ошибка в конфигурации nginx!" sudo nginx -t || true exit 1 fi else echo "❌ nginx не работает! Запускаем..." sudo systemctl start nginx sleep 2 if sudo systemctl is-active --quiet nginx; then echo "✅ nginx запущен" else echo "❌ Не удалось запустить nginx!" sudo systemctl status nginx --no-pager || true exit 1 fi fi ENDSSH final-verification: name: Final Verification runs-on: ubuntu-latest needs: [deploy-backend, deploy-web] if: always() steps: - name: Wait and Verify All Services run: | echo "⏳ Ждем завершения всех операций..." sleep 10 echo "🔍 Финальная проверка доступности всех сайтов..." ssh -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH' set -e echo "📊 Статус всех сервисов:" # Проверяем nginx if sudo systemctl is-active --quiet nginx; then echo "✅ nginx: работает" else echo "❌ nginx: НЕ работает!" sudo systemctl status nginx --no-pager || true fi # Проверяем backend if sudo systemctl is-active --quiet mnemo_cards_server; then echo "✅ backend: работает" else echo "❌ backend: НЕ работает!" sudo systemctl status mnemo_cards_server --no-pager || true fi echo "" echo "🌐 Тестируем доступность сайтов:" # Тестируем все сайты sites=("https://mnemo-cards.online/" "https://api.mnemo-cards.online/" "https://code.mnemo-cards.online/" "https://vscode.mnemo-cards.online/") for site in "${sites[@]}"; do if curl -I --max-time 10 "$site" 2>/dev/null | grep -q "200\|301\|302"; then echo "✅ $site доступен" else echo "❌ $site НЕДОСТУПЕН!" curl -I --max-time 5 "$site" || true fi done echo "" echo "🎉 Проверка завершена!" ENDSSH