name: Run Tests & Linting on: [push, pull_request] permissions: contents: read jobs: # ── Tests ────────────────────────────────────────────────────────────── test: name: Tests runs-on: ubuntu-latest services: redis: image: redis:7 ports: - 6379:6379 options: >- --health-cmd "redis-cli ping" --health-interval 10s --health-timeout 5s --health-retries 5 rabbitmq: image: rabbitmq:3-management ports: - 5672:5672 - 15672:15672 options: >- --health-cmd "rabbitmq-diagnostics -q ping" --health-interval 10s --health-timeout 5s --health-retries 5 steps: - name: Checkout Code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install Dependencies run: | python -m pip install --upgrade pip pip install -r requirements-dev.txt - name: Run Tests # Exclude E2E tests (-m "not e2e") as they require Docker-in-Docker (testcontainers) # which isn't well-supported in GitHub Actions without additional DinD configuration. # E2E tests can be run locally with: pytest -m e2e run: pytest tests/ -v --cov=app --cov-report=xml --cov-report=term --junitxml=junit.xml -o junit_family=legacy -m "not e2e" - name: Upload coverage reports to Codecov if: ${{ !cancelled() }} uses: codecov/codecov-action@v5 with: token: ${{ secrets.CODECOV_TOKEN }} file: ./coverage.xml fail_ci_if_error: false - name: Upload test results to Codecov if: ${{ !cancelled() }} uses: codecov/test-results-action@v1 with: token: ${{ secrets.CODECOV_TOKEN }} - name: Upload test artifacts if: ${{ !cancelled() }} uses: actions/upload-artifact@v4 with: name: test-results path: | junit.xml coverage.xml # ── Lint (Ruff) ─────────────────────────────────────────────────────── lint: name: Ruff Lint & Format runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install Ruff run: pip install ruff - name: Run Ruff Check run: ruff check app/ tests/ - name: Run Ruff Format run: ruff format --check app/ tests/ # ── Mypy ─────────────────────────────────────────────────────────────── mypy: name: Mypy runs-on: ubuntu-latest steps: - name: Checkout Code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: "3.11" - name: Install Dependencies run: | python -m pip install --upgrade pip pip install -r requirements-dev.txt - name: Run Mypy run: mypy app/