mnemo_cards/.forgejo/workflows/deploy.yaml
2025-11-27 17:11:38 +03:00

422 lines
18 KiB
YAML
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.

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: |
echo "🔍 Debugging SSH connection..."
echo "Target host: ${{ secrets.SSH_HOST }}"
ping -c 3 ${{ secrets.SSH_HOST }} || echo "⚠️ Ping failed"
nslookup ${{ secrets.SSH_HOST }} || echo "⚠️ DNS lookup failed"
nc -zv ${{ secrets.SSH_HOST }} 22 || echo "⚠️ Port 22 not reachable"
mkdir -p ~/.ssh
echo "${{ secrets.SSH_KEY }}" > ~/.ssh/id_rsa
chmod 600 ~/.ssh/id_rsa
ssh-keyscan -H ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || echo "⚠️ SSH keyscan failed"
- 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 }}:~/
# Sync deploy tools
rsync -avz --delete tools/deploy \
${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:~/mnemo_cards/tools/
- name: Ensure SSL Certificates
run: |
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
set -e
echo "🔐 Ensuring SSL certificates are available..."
if [ -d "/etc/letsencrypt/live/mnemo-cards.online" ] && [ -f "/etc/letsencrypt/live/mnemo-cards.online/fullchain.pem" ]; then
echo "✅ SSL certificates are present and valid"
else
echo "⚠️ SSL certificates missing - they should be renewed automatically by cron"
echo "Manual certificate renewal can be done with:"
echo "sudo certbot renew"
fi
ENDSSH
- name: Get Dependencies
run: |
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -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 ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -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 ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -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 ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -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 ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -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 ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -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 ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -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: Generate and Deploy Nginx Configs
run: |
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
set -e
echo "🔧 Generating nginx configurations..."
cd ~/mnemo_cards/tools/deploy
./generate-nginx-configs.sh
echo "🧹 Cleaning up old configuration files..."
# Remove old files without .conf extension that might cause conflicts
rm -f /etc/nginx/sites-available/forgejo
rm -f /etc/nginx/sites-available/vscode
rm -f /etc/nginx/sites-available/vscode.mnemo-cards.online
rm -f /etc/nginx/sites-available/mnemo_cards
rm -f /etc/nginx/sites-available/mnemo_cards_main
rm -f /etc/nginx/sites-enabled/vscode.mnemo-cards.online.conf
rm -f /etc/nginx/sites-enabled/code.mnemo-cards.online.conf
rm -f /etc/nginx/sites-enabled/mnemo-cards.online.conf
echo "📋 Deploying new configurations..."
cp generated_configs/*.conf /etc/nginx/sites-available/
echo "🔗 Creating symbolic links..."
ln -sf /etc/nginx/sites-available/mnemo-cards.online.conf /etc/nginx/sites-enabled/
ln -sf /etc/nginx/sites-available/code.mnemo-cards.online.conf /etc/nginx/sites-enabled/
ln -sf /etc/nginx/sites-available/vscode.mnemo-cards.online.conf /etc/nginx/sites-enabled/
echo "📊 Testing nginx configuration..."
if /usr/sbin/nginx -t; then
echo "✅ Configuration is valid"
echo "🔄 Reloading nginx..."
systemctl reload nginx
echo "✅ nginx reloaded successfully"
else
echo "❌ Configuration test failed!"
/usr/sbin/nginx -t || true
exit 1
fi
echo "🔍 Running final checks..."
# Check nginx service status
if systemctl is-active --quiet nginx; then
echo "✅ nginx service is running"
else
echo "❌ nginx service is not running!"
systemctl status nginx --no-pager || true
exit 1
fi
# Test site accessibility
echo "🌐 Testing site accessibility..."
if curl -I --max-time 5 https://mnemo-cards.online/ 2>/dev/null | grep -q "200\|301\|302"; then
echo "✅ mnemo-cards.online is accessible"
else
echo "⚠️ mnemo-cards.online not responding"
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 is accessible"
else
echo "⚠️ code.mnemo-cards.online not responding"
fi
if curl -I --max-time 5 https://vscode.mnemo-cards.online/ 2>/dev/null | grep -q "200\|301\|302"; then
echo "✅ vscode.mnemo-cards.online is accessible"
else
echo "⚠️ vscode.mnemo-cards.online not responding"
fi
echo "✅ Nginx configuration deployment completed successfully!"
ENDSSH
deploy-web:
name: Deploy Web App
runs-on: ubuntu-latest
container:
image: ghcr.io/cirruslabs/flutter:3.35.5
options: --memory=1024m --memory-swap=4096m
needs: deploy-backend
if: always() && needs.deploy-backend.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)"
# Set Node.js memory limits for dart2js compilation (512MB to fit in 1.5GB container)
echo "NODE_OPTIONS=--max-old-space-size=512" >> $GITHUB_ENV || echo "NODE_OPTIONS=--max-old-space-size=512" >> ~/.bashrc || true
- 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: Build Web App
working-directory: mnemo_cards_web_v2
env:
# Limit Dart VM memory usage (1GB for Dart, 512MB for Node.js)
DART_VM_OPTIONS: "--old-gen-heap-size=1024 --max-old-space-size=1024"
# Limit Node.js memory for dart2js compilation
NODE_OPTIONS: "--max-old-space-size=512"
# Limit parallel compilation to reduce memory pressure
FLUTTER_BUILD_PARALLEL: "1"
# Disable analytics to save memory
FLUTTER_ANALYTICS_DISABLED: "true"
# Reduce GC pressure
DART_FLAGS: "--disable-dart-dev"
run: |
echo "🔍 Проверяем Flutter..."
which flutter || echo "Flutter not found in PATH"
flutter --version || echo "Flutter command failed"
echo "📊 Текущее состояние памяти:"
free -h || true
echo "🧹 Очищаем кэш и временные файлы для экономии памяти..."
flutter clean || true
# Clear additional caches
rm -rf ~/.pub-cache/hosted/pub.dev/.cache || true
rm -rf ~/.dartServer || true
rm -rf ~/.flutter-devtools || true
rm -rf /tmp/dart* || true
rm -rf /tmp/flutter* || true
# Drop caches to free memory (if available)
echo 3 > /proc/sys/vm/drop_caches 2>/dev/null || true
# Sync memory to disk to free up RAM
sync || true
echo "📦 Получаем зависимости..."
timeout 300 flutter pub get || (echo "❌ Flutter pub get failed" && exit 1)
# Free memory after pub get
sync || true
echo "🔨 Собираем веб-приложение (оптимизировано для 1.5GB памяти)..."
# Use O1 optimization (lowest memory usage, still production-ready)
# Build with minimal parallelization to avoid OOM
# Additional flags to reduce memory footprint
timeout 1800 flutter build web --release \
--dart-define=API_BASE_URL=https://api.mnemo-cards.online \
--dart2js-optimization=O1 \
--no-tree-shake-icons || (echo "❌ Flutter build failed" && exit 1)
echo "✅ Сборка завершена"
echo "📊 Финальное состояние памяти:"
free -h || true
- name: Deploy Web App
run: |
echo "📦 Копируем веб-приложение..."
timeout 120 rsync -avz --delete mnemo_cards_web_v2/build/web/ \
${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/var/www/mnemo_cards/ || (echo "❌ Rsync failed" && exit 1)
echo "✅ Веб-приложение скопировано"
- name: Fix Permissions and Reload Nginx
run: |
ssh -o ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -o StrictHostKeyChecking=no ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
set -e
echo "🔧 Setting correct permissions for web files..."
chown -R www-data:www-data /var/www/mnemo_cards
chmod -R 755 /var/www/mnemo_cards
echo "✅ Permissions fixed"
echo "🔄 Reloading nginx to serve new web app..."
if sudo nginx -t 2>/dev/null; then
sudo systemctl reload nginx
echo "✅ nginx reloaded successfully"
sleep 2
# Quick verification
if curl -I --max-time 5 https://mnemo-cards.online/ 2>/dev/null | grep -q "200\|301\|302"; then
echo "✅ mnemo-cards.online is serving correctly"
else
echo "⚠️ mnemo-cards.online verification failed"
fi
else
echo "❌ nginx configuration test failed!"
sudo nginx -t || true
exit 1
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 ServerAliveInterval=60 -o ServerAliveCountMax=3 -o ConnectTimeout=30 -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