326 lines
No EOL
14 KiB
YAML
326 lines
No EOL
14 KiB
YAML
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 ${{ 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 ${{ 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 ${{ 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 ${{ 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 ${{ 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 ${{ 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 ${{ 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 ${{ 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 ${{ 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: Check Nginx Status
|
||
run: |
|
||
ssh ${{ 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()
|
||
steps:
|
||
- name: Setup Node.js
|
||
uses: actions/setup-node@v4
|
||
with:
|
||
node-version: '20'
|
||
|
||
- 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: Install Dependencies
|
||
run: |
|
||
apt-get update && apt-get install -y rsync openssh-client jq git nodejs npm
|
||
|
||
- 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: Build Web App
|
||
working-directory: mnemo_cards_web_v2
|
||
run: |
|
||
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: |
|
||
rsync -avz --delete mnemo_cards_web_v2/build/web/ \
|
||
${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }}:/var/www/mnemo_cards/
|
||
|
||
- name: Fix Permissions
|
||
run: |
|
||
ssh ${{ secrets.SSH_USER }}@${{ secrets.SSH_HOST }} \
|
||
"chown -R www-data:www-data /var/www/mnemo_cards && chmod -R 755 /var/www/mnemo_cards" |