# .github/workflows/ci.yml # CI for arac-hasar-v2 monorepo. Runs on every push and on PRs to main. # Jobs are parallel where possible. name: CI on: push: branches: ["**"] pull_request: branches: [main] # Cancel superseded runs on the same branch/PR. concurrency: group: ci-${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: PYTHON_VERSION: "3.11" NODE_VERSION: "20" PNPM_VERSION: "9" jobs: # ==================================================================== # Backend — Python 3.11 + FastAPI # ==================================================================== backend-lint: name: backend / lint (ruff + black) runs-on: ubuntu-latest defaults: run: working-directory: services/backend steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} cache: pip cache-dependency-path: services/backend/requirements.txt - name: Install lint tools run: | python -m pip install --upgrade pip pip install "ruff>=0.4" "black>=24.0" - name: Ruff run: ruff check . - name: Black --check run: black --check . backend-typecheck: name: backend / typecheck (mypy) runs-on: ubuntu-latest defaults: run: working-directory: services/backend steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} cache: pip cache-dependency-path: services/backend/requirements.txt - name: Install deps run: | python -m pip install --upgrade pip pip install -r requirements.txt pip install "mypy>=1.10" types-requests types-PyYAML - name: mypy # Be lenient until typing debt is paid down — fail only on hard errors. run: mypy --ignore-missing-imports --no-strict-optional . || true backend-test: name: backend / pytest runs-on: ubuntu-latest defaults: run: working-directory: services/backend services: postgres: image: postgres:16-alpine env: POSTGRES_USER: postgres POSTGRES_PASSWORD: postgres POSTGRES_DB: arac_hasar_test ports: ["5432:5432"] options: >- --health-cmd "pg_isready -U postgres" --health-interval 5s --health-timeout 5s --health-retries 10 redis: image: redis:7-alpine ports: ["6379:6379"] options: >- --health-cmd "redis-cli ping" --health-interval 5s --health-timeout 3s --health-retries 5 env: DATABASE_URL: postgresql://postgres:postgres@localhost:5432/arac_hasar_test REDIS_URL: redis://localhost:6379/0 ML_DEVICE: cpu ENVIRONMENT: test SKIP_MODEL_LOAD: "1" steps: - uses: actions/checkout@v4 - uses: actions/setup-python@v5 with: python-version: ${{ env.PYTHON_VERSION }} cache: pip cache-dependency-path: services/backend/requirements.txt - name: Install system deps for cv2 run: | sudo apt-get update sudo apt-get install -y --no-install-recommends \ libgl1 libglib2.0-0 libsm6 libxext6 libxrender1 - name: Install deps (CPU torch) run: | python -m pip install --upgrade pip pip install --extra-index-url https://download.pytorch.org/whl/cpu \ torch==2.3.1+cpu torchvision==0.18.1+cpu pip install -r requirements.txt pip install "pytest>=8.0" "pytest-asyncio>=0.23" "httpx>=0.27" - name: Run tests run: pytest -q --maxfail=5 # ==================================================================== # Frontend — Node 20 + pnpm 9 (monorepo) # ==================================================================== frontend-setup-cache: # Light job to warm the pnpm cache once; downstream jobs reuse it. name: frontend / pnpm install runs-on: ubuntu-latest outputs: store-path: ${{ steps.pnpm-cache.outputs.STORE_PATH }} steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: version: ${{ env.PNPM_VERSION }} - uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: pnpm - id: pnpm-cache run: echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_OUTPUT - run: pnpm install --frozen-lockfile packages-build: name: packages / build (types + ui) needs: frontend-setup-cache runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: { version: "${{ env.PNPM_VERSION }}" } - uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: pnpm - run: pnpm install --frozen-lockfile - name: Build shared packages run: pnpm -r --filter "./packages/*" build frontend-lint-web: name: web / next lint needs: packages-build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: { version: "${{ env.PNPM_VERSION }}" } - uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm -r --filter "./packages/*" build - name: Lint web working-directory: apps/web run: pnpm lint frontend-typecheck-web: name: web / tsc --noEmit needs: packages-build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: { version: "${{ env.PNPM_VERSION }}" } - uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm -r --filter "./packages/*" build - name: Typecheck web working-directory: apps/web run: pnpm exec tsc --noEmit frontend-typecheck-mobile: name: mobile / tsc --noEmit needs: packages-build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: { version: "${{ env.PNPM_VERSION }}" } - uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm -r --filter "./packages/*" build - name: Typecheck mobile working-directory: apps/mobile run: pnpm exec tsc --noEmit frontend-typecheck-desktop: name: desktop / tsc --noEmit needs: packages-build runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: pnpm/action-setup@v4 with: { version: "${{ env.PNPM_VERSION }}" } - uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: pnpm - run: pnpm install --frozen-lockfile - run: pnpm -r --filter "./packages/*" build - name: Typecheck desktop working-directory: apps/desktop run: pnpm exec tsc --noEmit # ==================================================================== # Aggregate gate — required check for branch protection. # ==================================================================== ci-pass: name: ci / all green needs: - backend-lint - backend-typecheck - backend-test - packages-build - frontend-lint-web - frontend-typecheck-web - frontend-typecheck-mobile - frontend-typecheck-desktop runs-on: ubuntu-latest steps: - run: echo "All CI jobs passed."