fix: disable TLS for internal PostgreSQL connection #208
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Web E2E Tests | |
| on: | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - 'web/**' | |
| - 'backend/**' | |
| - '.github/workflows/test-web.yml' | |
| push: | |
| branches: [main] | |
| paths: | |
| - 'web/**' | |
| - 'backend/**' | |
| - '.github/workflows/test-web.yml' | |
| concurrency: | |
| group: web-tests-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| test-web: | |
| name: Web E2E Tests (300+ tests) | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 60 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| submodules: recursive | |
| - name: Start Docker Compose Stack | |
| run: | | |
| cd backend | |
| docker compose up -d | |
| # Wait for all services to be healthy (60 second timeout) | |
| echo "Waiting for services to be healthy..." | |
| for i in {1..60}; do | |
| HEALTHY=$(docker compose ps | grep -c "healthy" || true) | |
| if [ "$HEALTHY" -ge 4 ]; then | |
| echo "β All services are healthy" | |
| break | |
| fi | |
| echo "Waiting... ($i/60)" | |
| sleep 1 | |
| done | |
| # List running services | |
| echo "" | |
| echo "Running services:" | |
| docker compose ps | |
| - name: Setup Bun | |
| uses: oven-sh/setup-bun@v2 | |
| with: | |
| bun-version: latest | |
| - name: Install web dependencies | |
| run: | | |
| cd web | |
| bun install --frozen-lockfile | |
| - name: Install Playwright browsers | |
| run: | | |
| cd web | |
| bunx playwright install --with-deps chromium | |
| - name: Run E2E tests | |
| run: | | |
| cd web | |
| bunx playwright test | |
| env: | |
| BACKEND_URL: http://localhost:8787 | |
| - name: Stop Docker Compose Stack | |
| if: always() | |
| run: | | |
| cd backend | |
| docker compose down -v | |
| - name: Parse test results | |
| if: always() | |
| id: parse-results | |
| run: | | |
| if [ -f web/test-results/results.json ]; then | |
| PASSED=$(jq '.stats.expected // 0' web/test-results/results.json) | |
| FAILED=$(jq '.stats.unexpected // 0' web/test-results/results.json) | |
| SKIPPED=$(jq '.stats.skipped // 0' web/test-results/results.json) | |
| DURATION=$(jq '.stats.duration // 0' web/test-results/results.json) | |
| DURATION_SEC=$((DURATION / 1000)) | |
| echo "passed=$PASSED" >> $GITHUB_OUTPUT | |
| echo "failed=$FAILED" >> $GITHUB_OUTPUT | |
| echo "skipped=$SKIPPED" >> $GITHUB_OUTPUT | |
| echo "duration=$DURATION_SEC" >> $GITHUB_OUTPUT | |
| # Calculate total and pass rate | |
| TOTAL=$((PASSED + FAILED + SKIPPED)) | |
| if [ $TOTAL -gt 0 ]; then | |
| PASS_RATE=$((PASSED * 100 / TOTAL)) | |
| echo "total=$TOTAL" >> $GITHUB_OUTPUT | |
| echo "pass_rate=$PASS_RATE" >> $GITHUB_OUTPUT | |
| fi | |
| else | |
| echo "β No test results file found" | |
| fi | |
| - name: Upload test report | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: playwright-report | |
| path: web/playwright-report/ | |
| retention-days: 14 | |
| - name: Upload test results (JSON) | |
| if: always() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-results-json | |
| path: web/test-results/ | |
| retention-days: 14 | |
| - name: Upload test videos | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-videos | |
| path: web/test-results/**/*.webm | |
| retention-days: 7 | |
| - name: Upload test traces | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: test-traces | |
| path: web/test-results/**/*.zip | |
| retention-days: 7 | |
| - name: Comment PR with detailed results | |
| if: always() && github.event_name == 'pull_request' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| const fs = require('fs'); | |
| const testResultsPath = 'web/test-results/results.json'; | |
| let comment = '## π§ͺ Web E2E Test Results\n\n'; | |
| if (fs.existsSync(testResultsPath)) { | |
| try { | |
| const results = JSON.parse(fs.readFileSync(testResultsPath, 'utf8')); | |
| const { stats } = results; | |
| const passed = stats.expected || 0; | |
| const failed = stats.unexpected || 0; | |
| const skipped = stats.skipped || 0; | |
| const total = passed + failed + skipped; | |
| const duration = ((stats.duration || 0) / 1000).toFixed(2); | |
| const passRate = total > 0 ? Math.round((passed / total) * 100) : 0; | |
| comment += '### Summary\n'; | |
| comment += `| Metric | Value |\n`; | |
| comment += `|--------|-------|\n`; | |
| comment += `| β **Passed** | **${passed}** |\n`; | |
| comment += `| β **Failed** | **${failed}** |\n`; | |
| comment += `| βοΈ **Skipped** | **${skipped}** |\n`; | |
| comment += `| π **Total** | **${total}** |\n`; | |
| comment += `| π― **Pass Rate** | **${passRate}%** |\n`; | |
| comment += `| β±οΈ **Duration** | **${duration}s** |\n\n`; | |
| // Test coverage by category | |
| if (results.suites && results.suites.length > 0) { | |
| comment += '### Test Coverage\n'; | |
| const categories = {}; | |
| results.suites.forEach(suite => { | |
| const parts = suite.title.split(' - '); | |
| const category = parts[0] || 'Other'; | |
| if (!categories[category]) { | |
| categories[category] = { passed: 0, failed: 0 }; | |
| } | |
| suite.tests?.forEach(test => { | |
| if (test.status === 'passed') categories[category].passed++; | |
| else if (test.status === 'failed') categories[category].failed++; | |
| }); | |
| }); | |
| Object.entries(categories).forEach(([name, stats]) => { | |
| const status = stats.failed === 0 ? 'β ' : 'β'; | |
| comment += `- ${status} **${name}**: ${stats.passed}/${stats.passed + stats.failed}\n`; | |
| }); | |
| comment += '\n'; | |
| } | |
| if (failed > 0) { | |
| comment += '### Failed Tests\n'; | |
| let failCount = 0; | |
| results.suites?.forEach(suite => { | |
| suite.tests?.forEach(test => { | |
| if (test.status === 'failed' && failCount < 10) { | |
| comment += `- β ${test.title}\n`; | |
| failCount++; | |
| } | |
| }); | |
| }); | |
| if (failCount >= 10) { | |
| comment += `- ... and ${failed - 10} more\n`; | |
| } | |
| comment += '\n'; | |
| } | |
| comment += `**[View full report β](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})**\n`; | |
| } catch (e) { | |
| console.error('Error parsing results:', e); | |
| comment += 'β οΈ Error parsing test results\n'; | |
| comment += `**[View full report β](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})**\n`; | |
| } | |
| } else { | |
| comment += 'β οΈ No test results file found\n'; | |
| comment += `**[View full report β](https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }})**\n`; | |
| } | |
| github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body: comment | |
| }).catch((e) => { | |
| console.error('Error posting comment:', e); | |
| }); | |
| - name: Report test status | |
| if: always() | |
| run: | | |
| echo "## Test Execution Summary" >> $GITHUB_STEP_SUMMARY | |
| echo "" >> $GITHUB_STEP_SUMMARY | |
| echo "| Metric | Value |" >> $GITHUB_STEP_SUMMARY | |
| echo "|--------|-------|" >> $GITHUB_STEP_SUMMARY | |
| echo "| Passed | ${{ steps.parse-results.outputs.passed || '?' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Failed | ${{ steps.parse-results.outputs.failed || '?' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Skipped | ${{ steps.parse-results.outputs.skipped || '?' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Total | ${{ steps.parse-results.outputs.total || '?' }} |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Pass Rate | ${{ steps.parse-results.outputs.pass_rate || '?' }}% |" >> $GITHUB_STEP_SUMMARY | |
| echo "| Duration | ${{ steps.parse-results.outputs.duration || '?' }}s |" >> $GITHUB_STEP_SUMMARY | |
| - name: Fail if tests failed | |
| if: failure() && steps.parse-results.outputs.failed > 0 | |
| run: | | |
| echo "β Tests failed!" | |
| exit 1 | |
| - name: 'notify vercel' | |
| uses: 'vercel/repository-dispatch/actions/status@v1' | |
| with: | |
| name: Vercel - sidechain - tests-web |