name: Build & Deploy on: push: branches: [main] workflow_dispatch: inputs: deploy: description: 'Desplegar en el VPS despues de construir' required: true default: true type: boolean # Un solo deploy a la vez — si llega uno nuevo, cancela el anterior concurrency: group: deploy-production cancel-in-progress: true env: REGISTRY: ghcr.io BACKEND_IMAGE: ghcr.io/${{ github.repository }}/backend FRONTEND_IMAGE: ghcr.io/${{ github.repository }}/frontend jobs: build-backend: name: Build Backend runs-on: ubuntu-latest permissions: contents: read packages: write steps: - name: Checkout code uses: actions/checkout@v4 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build & push backend uses: docker/build-push-action@v5 with: context: ./back push: true cache-from: type=gha,scope=backend cache-to: type=gha,mode=max,scope=backend tags: | ${{ env.BACKEND_IMAGE }}:latest ${{ env.BACKEND_IMAGE }}:${{ github.sha }} build-frontend: name: Build Frontend runs-on: ubuntu-latest permissions: contents: read packages: write steps: - name: Checkout code uses: actions/checkout@v4 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Login to GitHub Container Registry uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - name: Build & push frontend uses: docker/build-push-action@v5 with: context: ./front push: true cache-from: type=gha,scope=frontend cache-to: type=gha,mode=max,scope=frontend build-args: | VITE_API_URL=/api tags: | ${{ env.FRONTEND_IMAGE }}:latest ${{ env.FRONTEND_IMAGE }}:${{ github.sha }} deploy: name: Deploy to VPS needs: [build-backend, build-frontend] if: ${{ github.event_name == 'push' || inputs.deploy }} runs-on: ubuntu-latest steps: - name: Deploy via SSH uses: appleboy/ssh-action@v1 with: host: ${{ secrets.VPS_HOST }} username: ${{ secrets.VPS_USER }} key: ${{ secrets.VPS_SSH_KEY }} port: ${{ secrets.VPS_PORT || 22 }} command_timeout: 30m script: | cd ${{ secrets.VPS_PROJECT_PATH }} # Sincronizar archivos del host con el repo (sin conflictos) git fetch origin main && git reset --hard origin/main # Login al registry echo ${{ secrets.CR_PAT }} | docker login ghcr.io -u ${{ github.actor }} --password-stdin # Descargar imagenes nuevas docker pull ${{ env.BACKEND_IMAGE }}:latest docker pull ${{ env.FRONTEND_IMAGE }}:latest # Reiniciar servicios docker compose --env-file .env.prod -f docker-compose.prod.yml up -d --force-recreate backend frontend nginx # Esperar que el backend este listo antes de migrar (max 60 segundos) echo "Esperando backend..." for i in $(seq 1 30); do if docker exec admision_prod_backend php artisan --version > /dev/null 2>&1; then echo "Backend listo" break fi sleep 2 done # Ejecutar migraciones si hay pendientes docker exec admision_prod_backend php artisan migrate --force # Limpiar imagenes viejas docker image prune -f