Merge pull request #5 from bnbong/feature/multiplayer #1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Deploy Backend | |
| on: | |
| workflow_dispatch: | |
| push: | |
| branches: [main] | |
| paths: | |
| - "backend/**" | |
| - "src/fall_in/core/**" | |
| - "src/fall_in/ai/**" | |
| - "src/fall_in/net/**" | |
| - "src/fall_in/multiplayer/models.py" | |
| # Only one deployment at a time. | |
| concurrency: | |
| group: deploy-backend | |
| cancel-in-progress: true | |
| jobs: | |
| test: | |
| name: Pre-deploy Test | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| shell: bash | |
| working-directory: backend | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Python 3.12 | |
| uses: actions/setup-python@v6 | |
| with: | |
| python-version: "3.12" | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v7 | |
| - name: Install dependencies | |
| run: uv sync --extra dev | |
| - name: Lint | |
| run: uv run ruff check app/ tests/ | |
| - name: Test | |
| run: uv run pytest -x -q | |
| deploy: | |
| name: Deploy to OCI | |
| needs: test | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up SSH | |
| run: | | |
| mkdir -p ~/.ssh | |
| echo "${{ secrets.OCI_SSH_KEY }}" > ~/.ssh/id_ed25519 | |
| chmod 600 ~/.ssh/id_ed25519 | |
| ssh-keyscan -H "${{ secrets.OCI_HOST }}" >> ~/.ssh/known_hosts | |
| - name: Sync source to server | |
| run: | | |
| rsync -azP --delete \ | |
| --include='backend/***' \ | |
| --include='src/fall_in/core/***' \ | |
| --include='src/fall_in/ai/***' \ | |
| --include='src/fall_in/net/***' \ | |
| --include='src/fall_in/multiplayer/models.py' \ | |
| --include='src/fall_in/__init__.py' \ | |
| --include='src/fall_in/multiplayer/__init__.py' \ | |
| --include='src/' \ | |
| --include='src/fall_in/' \ | |
| --include='src/fall_in/multiplayer/' \ | |
| --include='pyproject.toml' \ | |
| --include='uv.lock' \ | |
| --include='data/***' \ | |
| --exclude='*' \ | |
| ./ "${{ secrets.OCI_USER }}@${{ secrets.OCI_HOST }}:~/fall-in/" | |
| - name: Build & restart on server | |
| run: | | |
| ssh "${{ secrets.OCI_USER }}@${{ secrets.OCI_HOST }}" << 'DEPLOY_SCRIPT' | |
| set -e | |
| cd ~/fall-in | |
| # Build Docker image (ARM-native on Ampere A1). | |
| docker build -t fall-in-backend -f backend/Dockerfile . | |
| # Stop existing container (if any) and start fresh. | |
| docker stop fall-in-backend 2>/dev/null || true | |
| docker rm fall-in-backend 2>/dev/null || true | |
| docker run -d \ | |
| --name fall-in-backend \ | |
| --restart unless-stopped \ | |
| --env-file ~/fall-in/backend/.env \ | |
| --network host \ | |
| fall-in-backend | |
| # Wait for health check. | |
| echo "Waiting for health check..." | |
| for i in $(seq 1 15); do | |
| if curl -sf http://localhost:8000/healthz > /dev/null 2>&1; then | |
| echo "Health check passed." | |
| exit 0 | |
| fi | |
| sleep 2 | |
| done | |
| echo "Health check failed after 30s" | |
| docker logs fall-in-backend --tail 30 | |
| exit 1 | |
| DEPLOY_SCRIPT | |
| - name: Clean up old Docker images | |
| if: success() | |
| run: | | |
| ssh "${{ secrets.OCI_USER }}@${{ secrets.OCI_HOST }}" \ | |
| 'docker image prune -f' |