add AGENTS.md #20
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: .NET API Tests, Docker Build & Deploy | |
| on: | |
| push: | |
| branches: [ Prod ] | |
| pull_request: | |
| branches: [ Prod ] | |
| permissions: | |
| contents: read | |
| checks: write | |
| pull-requests: write | |
| packages: write | |
| env: | |
| IMAGE_NAME: ghcr.io/${{ github.repository_owner }}/tablemaster-api | |
| jobs: | |
| build-and-test: | |
| runs-on: ubuntu-latest | |
| strategy: | |
| matrix: | |
| dotnet-version: ['10.0.x'] | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Setup .NET ${{ matrix.dotnet-version }} | |
| uses: actions/setup-dotnet@v4 | |
| with: | |
| dotnet-version: ${{ matrix.dotnet-version }} | |
| include-prerelease: true | |
| - name: Restore dependencies | |
| run: | | |
| dotnet restore TableMasterApi/TableMasterApi.csproj | |
| dotnet restore TableMasterApi.Tests/TableMasterApi.Tests.csproj | |
| - name: Build | |
| run: | | |
| dotnet build TableMasterApi/TableMasterApi.csproj --no-restore --configuration Release | |
| dotnet build TableMasterApi.Tests/TableMasterApi.Tests.csproj --no-restore --configuration Release | |
| - name: Run Unit Tests | |
| run: > | |
| dotnet test TableMasterApi.Tests/TableMasterApi.Tests.csproj | |
| --no-build | |
| --configuration Release | |
| --verbosity normal | |
| --logger "trx;LogFileName=test-results.trx" | |
| - name: Upload Test Results | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results | |
| path: '**/test-results.trx' | |
| - name: Test Report | |
| if: always() | |
| uses: dorny/test-reporter@v1 | |
| with: | |
| name: .NET Test Results | |
| path: '**/test-results.trx' | |
| reporter: 'dotnet-trx' | |
| docker-build-and-push: | |
| name: Build and push Docker image | |
| runs-on: ubuntu-latest | |
| needs: build-and-test | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/Prod' | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Normalize image name | |
| run: | | |
| IMAGE_NAME_LOWER=$(echo "${IMAGE_NAME}" | tr '[:upper:]' '[:lower:]') | |
| echo "IMAGE_NAME_LOWER=$IMAGE_NAME_LOWER" >> $GITHUB_ENV | |
| - name: Login to GHCR | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build and push API image | |
| uses: docker/build-push-action@v6 | |
| with: | |
| context: . | |
| file: ./TableMasterApi/Dockerfile | |
| push: true | |
| tags: | | |
| ${{ env.IMAGE_NAME_LOWER }}:prod | |
| ${{ env.IMAGE_NAME_LOWER }}:${{ github.sha }} | |
| deploy: | |
| name: Deploy to Oracle VPS | |
| runs-on: ubuntu-latest | |
| needs: docker-build-and-push | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/Prod' | |
| steps: | |
| - name: Prepare SSH key | |
| run: | | |
| mkdir -p ~/.ssh | |
| echo "${{ secrets.ORACLE_SSH_KEY_B64 }}" | base64 -d > ~/.ssh/oracle_key | |
| chmod 600 ~/.ssh/oracle_key | |
| ssh-keyscan -H ${{ secrets.ORACLE_HOST }} >> ~/.ssh/known_hosts | |
| - name: Deploy with Docker Compose | |
| run: | | |
| ssh -i ~/.ssh/oracle_key ${{ secrets.ORACLE_USER }}@${{ secrets.ORACLE_HOST }} << 'EOF' | |
| set -e | |
| cd /opt/tablemaster/prod/TableMasterApi | |
| git fetch origin Prod | |
| git reset --hard origin/Prod | |
| test -f .env | |
| test -f tablemaster-firebase.json | |
| echo "${{ secrets.GHCR_READ_TOKEN }}" | docker login ghcr.io -u "${{ secrets.GHCR_USERNAME }}" --password-stdin | |
| docker compose pull | |
| docker compose up -d | |
| docker image prune -f | |
| docker compose ps | |
| echo "Health check..." | |
| healthy=0 | |
| for i in $(seq 1 30); do | |
| if curl -fsS http://localhost:8080/health; then | |
| echo "" | |
| echo "API is healthy" | |
| healthy=1 | |
| break | |
| fi | |
| echo "API not ready yet... attempt $i/30" | |
| docker compose ps | |
| sleep 5 | |
| done | |
| if [ "$healthy" -ne 1 ]; then | |
| echo "API failed to become healthy" | |
| docker compose logs api --tail=200 | |
| exit 1 | |
| fi | |
| EOF |