name: PR Checks # Validation gate for pull requests. # PRs to preprod → lint + unit tests + integration tests # PRs to main → lint + unit tests only (code was integration-tested in preprod already) # # Configure these as required status checks in GitHub branch protection rules. on: pull_request: branches: [preprod, main] concurrency: group: pr-${{ github.event.pull_request.number }} cancel-in-progress: true env: NODE_VERSION: '20' jobs: # ────────────────────────────────────────── # Lint & Type-check (both apps, parallel) # ────────────────────────────────────────── quality: name: Quality (${{ matrix.app }}) runs-on: ubuntu-latest strategy: fail-fast: false matrix: app: [backend, frontend] defaults: run: working-directory: apps/${{ matrix.app }} steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: apps/${{ matrix.app }}/package-lock.json - name: Install dependencies run: npm ci --legacy-peer-deps - name: Lint run: npm run lint - name: Type-check (frontend only) if: matrix.app == 'frontend' run: npm run type-check # ────────────────────────────────────────── # Unit Tests (both apps, parallel) # ────────────────────────────────────────── unit-tests: name: Unit Tests (${{ matrix.app }}) runs-on: ubuntu-latest needs: quality strategy: fail-fast: false matrix: app: [backend, frontend] defaults: run: working-directory: apps/${{ matrix.app }} steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: apps/${{ matrix.app }}/package-lock.json - name: Install dependencies run: npm ci --legacy-peer-deps - name: Run unit tests run: npm test -- --passWithNoTests --coverage # ────────────────────────────────────────── # Integration Tests — PRs to preprod only # ────────────────────────────────────────── integration-tests: name: Integration Tests runs-on: ubuntu-latest needs: unit-tests if: github.base_ref == 'preprod' defaults: run: working-directory: apps/backend services: postgres: image: postgres:15-alpine env: POSTGRES_USER: xpeditis_test POSTGRES_PASSWORD: xpeditis_test_password POSTGRES_DB: xpeditis_test options: >- --health-cmd pg_isready --health-interval 5s --health-timeout 5s --health-retries 10 ports: - 5432:5432 redis: image: redis:7-alpine options: >- --health-cmd "redis-cli ping" --health-interval 5s --health-timeout 5s --health-retries 10 ports: - 6379:6379 steps: - uses: actions/checkout@v4 - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'npm' cache-dependency-path: apps/backend/package-lock.json - name: Install dependencies run: npm ci --legacy-peer-deps - name: Run integration tests env: NODE_ENV: test DATABASE_HOST: localhost DATABASE_PORT: 5432 DATABASE_USER: xpeditis_test DATABASE_PASSWORD: xpeditis_test_password DATABASE_NAME: xpeditis_test DATABASE_SYNCHRONIZE: false REDIS_HOST: localhost REDIS_PORT: 6379 REDIS_PASSWORD: '' JWT_SECRET: test-secret-key-for-ci-only SMTP_HOST: localhost SMTP_PORT: 1025 SMTP_FROM: test@xpeditis.com run: npm run test:integration -- --passWithNoTests # ────────────────────────────────────────── # PR Summary # ────────────────────────────────────────── pr-summary: name: PR Summary runs-on: ubuntu-latest needs: [quality, unit-tests] if: always() steps: - name: Write job summary run: | echo "## PR Check Results" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "| Check | Status |" >> $GITHUB_STEP_SUMMARY echo "|-------|--------|" >> $GITHUB_STEP_SUMMARY echo "| Quality (lint + type-check) | ${{ needs.quality.result }} |" >> $GITHUB_STEP_SUMMARY echo "| Unit Tests | ${{ needs.unit-tests.result }} |" >> $GITHUB_STEP_SUMMARY echo "| Target Branch | \`${{ github.base_ref }}\` |" >> $GITHUB_STEP_SUMMARY echo "| Author | ${{ github.actor }} |" >> $GITHUB_STEP_SUMMARY