From 38b59ba48da55b3fa1554e39f96b899abef519ae Mon Sep 17 00:00:00 2001 From: sepehr Date: Fri, 15 May 2026 14:53:15 +0200 Subject: [PATCH] fix: rewrite deploy workflow to use SSH-based deployment Use ubuntu-24.04 runner with SSH to 192.168.1.151 (same pattern as memento project). Self-hosted runner is not needed on the server. Co-Authored-By: Claude Opus 4.7 --- .gitea/workflows/deploy.yml | 161 +++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 78 deletions(-) diff --git a/.gitea/workflows/deploy.yml b/.gitea/workflows/deploy.yml index 22262b4..9fafde0 100644 --- a/.gitea/workflows/deploy.yml +++ b/.gitea/workflows/deploy.yml @@ -1,104 +1,109 @@ -name: Deploy to Homelab +name: Deploy to Production on: push: branches: - production-deployment + workflow_dispatch: jobs: deploy: - name: Deploy Wordly to 192.168.1.151 - runs-on: self-hosted + name: Build and Deploy + runs-on: ubuntu-24.04 steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: production-deployment - - - name: Copy environment file + - name: Setup SSH run: | - if [ ! -f .env ]; then - echo "WARNING: .env file not found. Creating from template." - echo "You must manually set secrets in .env on the server." - cp .env.production .env - fi + mkdir -p ~/.ssh + echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H 192.168.1.151 >> ~/.ssh/known_hosts - - name: Build and start services + - name: Deploy via SSH run: | - docker compose build --no-cache backend frontend - docker compose up -d + ssh root@192.168.1.151 << 'ENDSSH' + set -e + cd /opt/wordly - - name: Wait for services to be healthy + echo "=== Git pull ===" + git config --global --add safe.directory /opt/wordly + git fetch origin production-deployment + git reset --hard origin/production-deployment + + echo "=== Building images ===" + docker compose build backend frontend + + echo "=== Starting services ===" + docker compose up -d --remove-orphans + + echo "=== Waiting for postgres ===" + for i in $(seq 1 30); do + if docker compose exec -T postgres pg_isready -U translate >/dev/null 2>&1; then + echo "Postgres ready after $((i * 2))s" + break + fi + if [ "$i" -eq 30 ]; then + echo "ERROR: Postgres not ready after 60s" + docker compose logs postgres --tail=30 + exit 1 + fi + sleep 2 + done + + echo "=== Waiting for backend healthy ===" + for i in $(seq 1 20); do + if curl -sf http://localhost:8001/health >/dev/null 2>&1; then + echo "Backend healthy after $((i * 5))s" + break + fi + if [ "$i" -eq 20 ]; then + echo "ERROR: Backend not healthy after 100s" + docker compose logs backend --tail=50 + exit 1 + fi + sleep 5 + done + + echo "=== Deploy summary ===" + docker compose ps + echo "Health: $(curl -sf http://localhost:8001/health 2>/dev/null || echo 'FAILED')" + ENDSSH + + - name: Wait for frontend run: | - echo "Waiting for services to start..." - sleep 15 - - # Check each service - SERVICES="wordly-postgres wordly-redis wordly-backend wordly-frontend" - FAILED=0 - - for svc in $SERVICES; do - STATUS=$(docker inspect --format='{{.State.Status}}' $svc 2>/dev/null || echo "not found") - if [ "$STATUS" = "running" ]; then - echo " $svc: RUNNING" - else - echo " $svc: $STATUS (may still be starting)" - FAILED=$((FAILED + 1)) + echo "Waiting for frontend..." + for i in $(seq 1 20); do + CODE=$(curl -s -o /dev/null -w "%{http_code}" --max-time 5 http://192.168.1.151:3000/ || echo "000") + if [ "$CODE" != "000" ] && [ "$CODE" -lt 500 ]; then + echo "Frontend OK (HTTP $CODE) after $((i * 5))s" + exit 0 fi - done - - # Wait more for slow services - sleep 20 - - # Final health check on backend - for i in $(seq 1 10); do - if curl -sf http://localhost:8001/health > /dev/null 2>&1; then - echo "Backend health check: OK" - break - fi - echo "Waiting for backend... attempt $i/10" + echo " [$((i * 5))s] HTTP $CODE" sleep 5 done + echo "Timeout!" + exit 1 - if ! curl -sf http://localhost:8000/health > /dev/null 2>&1; then - echo "ERROR: Backend health check failed after 50 seconds" - docker compose logs --tail=30 backend - exit 1 - fi + - name: Cleanup + if: always() + run: ssh root@192.168.1.151 "docker image prune -f" || true - - name: Cleanup old images - run: | - docker image prune -f --filter "until=48h" 2>/dev/null || true - - - name: Deploy summary - run: | - echo "=========================================" - echo " Wordly Deployment Complete" - echo "=========================================" - docker compose ps - echo "" - echo "Health: $(curl -sf http://localhost:8001/health 2>/dev/null || echo 'FAILED')" - echo "=========================================" - - # Optional: deploy monitoring stack deploy-monitoring: - name: Deploy Monitoring (if configured) - runs-on: self-hosted + name: Deploy Monitoring + runs-on: ubuntu-24.04 needs: deploy - if: hashFiles('docker-compose.monitoring.yml') != '' steps: - - name: Checkout code - uses: actions/checkout@v4 - with: - ref: production-deployment - - - name: Start monitoring services + - name: Setup SSH run: | - docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -d prometheus grafana node-exporter cadvisor - continue-on-error: true + mkdir -p ~/.ssh + echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/id_rsa + chmod 600 ~/.ssh/id_rsa + ssh-keyscan -H 192.168.1.151 >> ~/.ssh/known_hosts - - name: Monitoring status + - name: Start monitoring run: | - echo "Monitoring services:" - docker compose -f docker-compose.yml -f docker-compose.monitoring.yml ps + ssh root@192.168.1.151 << 'ENDSSH' + cd /opt/wordly + docker compose -f docker-compose.yml -f docker-compose.monitoring.yml up -d prometheus grafana node-exporter cadvisor + docker compose -f docker-compose.yml -f docker-compose.monitoring.yml ps + ENDSSH continue-on-error: true