name: Test Suite on: pull_request: branches: [main, develop] push: branches: [main, develop] workflow_dispatch: # Cancel in-progress runs for same PR/branch concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true env: NODE_VERSION: '20' PNPM_VERSION: '9.15.0' jobs: # ==================== # 1. TEST BACKENDS # ==================== test-backends: name: Test Backend - ${{ matrix.project }} runs-on: ubuntu-latest timeout-minutes: 10 strategy: fail-fast: false matrix: project: - maerchenzauber - manadeck - chat - nutriphi - picture steps: - name: Checkout code uses: actions/checkout@v4 with: fetch-depth: 0 - name: Setup pnpm uses: pnpm/action-setup@v2 with: version: ${{ env.PNPM_VERSION }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Build shared packages run: pnpm run build:packages - name: Type check run: pnpm --filter @${{ matrix.project }}/backend type-check continue-on-error: true - name: Run tests with coverage run: pnpm --filter @${{ matrix.project }}/backend test:cov env: NODE_ENV: test - name: Check coverage thresholds run: | echo "Checking coverage meets 80% threshold..." # Jest/Vitest will fail if thresholds aren't met # ==================== # 2. TEST MOBILE APPS # ==================== test-mobile: name: Test Mobile - ${{ matrix.project }} runs-on: ubuntu-latest timeout-minutes: 15 strategy: fail-fast: false matrix: project: - maerchenzauber - memoro - picture - chat - manacore - manadeck - nutriphi steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup pnpm uses: pnpm/action-setup@v2 with: version: ${{ env.PNPM_VERSION }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Build shared packages run: pnpm run build:packages - name: Type check run: pnpm --filter @${{ matrix.project }}/mobile type-check continue-on-error: true - name: Run tests with coverage run: pnpm --filter @${{ matrix.project }}/mobile test -- --coverage --watchAll=false --ci env: NODE_ENV: test # ==================== # 3. TEST WEB APPS # ==================== test-web: name: Test Web - ${{ matrix.project }} runs-on: ubuntu-latest timeout-minutes: 15 strategy: fail-fast: false matrix: project: - maerchenzauber - manacore - memoro - picture - uload - chat - manadeck - nutriphi - news steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup pnpm uses: pnpm/action-setup@v2 with: version: ${{ env.PNPM_VERSION }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Build shared packages run: pnpm run build:packages - name: Type check run: pnpm --filter @${{ matrix.project }}/web check continue-on-error: true - name: Run unit tests with coverage run: pnpm --filter @${{ matrix.project }}/web test:unit -- --coverage --run env: NODE_ENV: test # ==================== # 4. E2E TESTS (WEB) # ==================== test-e2e-web: name: E2E Web - ${{ matrix.project }} runs-on: ubuntu-latest timeout-minutes: 20 strategy: fail-fast: false matrix: project: - uload # Add other projects with E2E tests steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup pnpm uses: pnpm/action-setup@v2 with: version: ${{ env.PNPM_VERSION }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Build shared packages run: pnpm run build:packages - name: Install Playwright browsers run: pnpm --filter @${{ matrix.project }}/web exec playwright install --with-deps chromium - name: Build application run: pnpm --filter @${{ matrix.project }}/web build - name: Run E2E tests run: pnpm --filter @${{ matrix.project }}/web test:e2e env: CI: true - name: Upload Playwright report if: always() uses: actions/upload-artifact@v4 with: name: playwright-report-${{ matrix.project }} path: ./apps/${{ matrix.project }}/apps/web/playwright-report/ retention-days: 7 # ==================== # 5. TEST SHARED PACKAGES # ==================== test-shared-packages: name: Test Shared Packages runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup pnpm uses: pnpm/action-setup@v2 with: version: ${{ env.PNPM_VERSION }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Build shared packages run: pnpm run build:packages - name: Type check shared packages run: pnpm --filter './packages/*' type-check continue-on-error: true - name: Run tests with coverage run: pnpm --filter './packages/*' test -- --coverage --run continue-on-error: true env: NODE_ENV: test # ==================== # 6. LINT & FORMAT CHECK # ==================== lint-and-format: name: Lint & Format runs-on: ubuntu-latest timeout-minutes: 10 steps: - name: Checkout code uses: actions/checkout@v4 - name: Setup pnpm uses: pnpm/action-setup@v2 with: version: ${{ env.PNPM_VERSION }} - name: Setup Node.js uses: actions/setup-node@v4 with: node-version: ${{ env.NODE_VERSION }} cache: 'pnpm' - name: Install dependencies run: pnpm install --frozen-lockfile - name: Build shared packages run: pnpm run build:packages - name: Check formatting run: pnpm run format:check - name: Run linters run: pnpm run lint continue-on-error: true # ==================== # 7. COVERAGE REPORT # ==================== coverage-report: name: Generate Coverage Report needs: - test-backends - test-mobile - test-web - test-shared-packages runs-on: ubuntu-latest if: always() steps: - name: Checkout code uses: actions/checkout@v4 - name: Download all coverage reports uses: actions/download-artifact@v4 continue-on-error: true - name: Generate coverage summary run: | echo "## 📊 Test Coverage Summary" >> $GITHUB_STEP_SUMMARY echo "" >> $GITHUB_STEP_SUMMARY echo "### Jobs Status" >> $GITHUB_STEP_SUMMARY echo "- Backend Tests: ${{ needs.test-backends.result }}" >> $GITHUB_STEP_SUMMARY echo "- Mobile Tests: ${{ needs.test-mobile.result }}" >> $GITHUB_STEP_SUMMARY echo "- Web Tests: ${{ needs.test-web.result }}" >> $GITHUB_STEP_SUMMARY echo "- Shared Packages Tests: ${{ needs.test-shared-packages.result }}" >> $GITHUB_STEP_SUMMARY # ==================== # 8. TEST STATUS CHECK # ==================== test-status: name: All Tests Status needs: - test-backends - test-mobile - test-web - test-shared-packages - lint-and-format runs-on: ubuntu-latest if: always() steps: - name: Check test results run: | if [ "${{ needs.test-backends.result }}" != "success" ] || \ [ "${{ needs.test-mobile.result }}" != "success" ] || \ [ "${{ needs.test-web.result }}" != "success" ] || \ [ "${{ needs.test-shared-packages.result }}" != "success" ]; then echo "❌ Some tests failed" exit 1 fi echo "✅ All tests passed" - name: Post PR comment if: github.event_name == 'pull_request' uses: actions/github-script@v7 with: script: | const status = '${{ needs.test-status.result }}' === 'success' ? '✅' : '❌'; const body = `## ${status} Test Suite Results **Status**: ${status === '✅' ? 'All tests passed!' : 'Some tests failed'} ### Test Coverage - Backend: ${{ needs.test-backends.result }} - Mobile: ${{ needs.test-mobile.result }} - Web: ${{ needs.test-web.result }} - Shared Packages: ${{ needs.test-shared-packages.result }} - Lint & Format: ${{ needs.lint-and-format.result }} View detailed results in the [Actions tab](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}) `; github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body });