# ───────────────────────────────────────────────────────────────────────────── # Backend CI — Python formatting checks via Ruff and lock file check # Runs on pushes and PRs to main/dev when backend files change # ───────────────────────────────────────────────────────────────────────────── name: Python CI permissions: contents: read on: push: branches: [main, dev] paths: ['backend/**', 'pyproject.toml', 'uv.lock', '.github/workflows/backend.yaml'] pull_request: branches: [main, dev] paths: ['backend/**', 'pyproject.toml', 'uv.lock', '.github/workflows/backend.yaml'] concurrency: group: backend-${{ github.ref }} cancel-in-progress: true jobs: # ── Ruff format check across supported Python versions ─────────────────── format-check: name: Ruff Format (${{ matrix.python-version }}) runs-on: ubuntu-latest timeout-minutes: 10 strategy: fail-fast: false matrix: python-version: ['3.11', '3.12'] steps: - uses: actions/checkout@v5.1.0 - uses: actions/setup-python@v6.3.0 with: python-version: ${{ matrix.python-version }} - name: Install formatter run: pip install "ruff>=0.15.5" - name: Verify formatting run: ruff format --check . --exclude .venv --exclude venv - name: Detect logic errors run: ruff check --select=F --ignore=F401,F403,F405,F541,F811,F841 --output-format=github . # ── Dockerfile lock files match the requirements files ─────────────────── lock-check: name: Requirements locks up to date runs-on: ubuntu-latest timeout-minutes: 10 steps: - uses: actions/checkout@v5.1.0 - uses: actions/setup-python@v6.3.0 with: python-version: '3.12' - name: Install uv run: pip install uv==0.12.10 - name: Regenerate locks run: backend/update-locks.sh - name: Verify locks are up to date run: test -z "$(git status --porcelain -- backend)"