Release vNext: Cover import, various ui improvements, password reset #134
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: Tests | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [develop, main] | |
| workflow_dispatch: | |
| env: | |
| PYTHON_VERSION: "3.14" | |
| NODE_VERSION: "24" | |
| FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" | |
| jobs: | |
| backend: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: backend | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install dependencies | |
| run: uv sync --frozen | |
| - name: Run tests | |
| run: uv run pytest --junitxml=report.xml --cov=app --cov-report=term-missing | |
| - name: Upload report | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: test-report-backend | |
| path: backend/report.xml | |
| cli: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: cli | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install uv | |
| uses: astral-sh/setup-uv@v8.1.0 | |
| with: | |
| python-version: ${{ env.PYTHON_VERSION }} | |
| - name: Install dependencies | |
| run: uv sync --frozen | |
| - name: Run tests | |
| run: uv run pytest --junitxml=report.xml | |
| - name: Upload report | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: test-report-cli | |
| path: cli/report.xml | |
| frontend: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: frontend | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v6 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run tests | |
| run: npx vitest run --reporter=junit --reporter=default --outputFile=report.xml | |
| - name: Upload report | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: test-report-frontend | |
| path: frontend/report.xml | |
| e2e: | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: frontend | |
| steps: | |
| - uses: actions/checkout@v6 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v4 | |
| - name: Prepare E2E directories | |
| run: | | |
| docker run --rm -v ${{ github.workspace }}/data-e2e:/data alpine sh -c 'rm -rf /data/*' 2>/dev/null || true | |
| mkdir -p playwright-report test-results | |
| - name: Build backend image | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: ./backend | |
| tags: librislog-e2e-backend | |
| load: true | |
| build-args: | | |
| APP_VERSION=v0.0.0-dev | |
| GIT_SHA=unknown | |
| - name: Build frontend image | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: ./frontend | |
| tags: librislog-e2e-frontend | |
| load: true | |
| build-args: | | |
| APP_VERSION=v0.0.0-dev | |
| GIT_SHA=unknown | |
| PUBLIC_DEFAULT_LOCALE=en | |
| - name: Build test-runner image | |
| uses: docker/build-push-action@v7 | |
| with: | |
| context: ./frontend | |
| file: frontend/Dockerfile.e2e | |
| tags: librislog-e2e-test-runner | |
| load: true | |
| - name: Run E2E tests | |
| run: docker compose -f ../docker-compose.e2e.yml up --abort-on-container-exit --attach test-runner --no-log-prefix | |
| - name: Upload Playwright report | |
| if: always() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: playwright-report | |
| path: frontend/playwright-report/ | |
| - name: Upload test results | |
| if: failure() | |
| uses: actions/upload-artifact@v7 | |
| with: | |
| name: test-results | |
| path: frontend/test-results/ | |
| include-hidden-files: true | |
| report: | |
| needs: [backend, cli, frontend, e2e] | |
| if: always() | |
| runs-on: ubuntu-latest | |
| permissions: | |
| checks: write | |
| pull-requests: write | |
| issues: write | |
| steps: | |
| - uses: actions/download-artifact@v8 | |
| with: | |
| path: artifacts | |
| pattern: "*report*" | |
| - name: Initialize git for test reporter | |
| run: | | |
| git init | |
| git config user.email "ci@github.com" | |
| git config user.name "CI" | |
| git add -A | |
| git commit --allow-empty -m "ci" | |
| - name: Publish backend results | |
| id: backend | |
| uses: dorny/test-reporter@v3 | |
| continue-on-error: true | |
| with: | |
| name: Backend Tests (pytest) | |
| path: artifacts/test-report-backend/report.xml | |
| reporter: java-junit | |
| fail-on-error: "false" | |
| - name: Publish CLI results | |
| id: cli | |
| uses: dorny/test-reporter@v3 | |
| continue-on-error: true | |
| with: | |
| name: CLI Tests (pytest) | |
| path: artifacts/test-report-cli/report.xml | |
| reporter: java-junit | |
| fail-on-error: "false" | |
| - name: Publish frontend results | |
| id: frontend | |
| uses: dorny/test-reporter@v3 | |
| continue-on-error: true | |
| with: | |
| name: Frontend Tests (vitest) | |
| path: artifacts/test-report-frontend/report.xml | |
| reporter: java-junit | |
| fail-on-error: "false" | |
| - name: Publish E2E results | |
| id: e2e | |
| uses: dorny/test-reporter@v3 | |
| continue-on-error: true | |
| with: | |
| name: E2E Tests (Playwright) | |
| path: artifacts/playwright-report/report.xml | |
| reporter: java-junit | |
| fail-on-error: "false" | |
| - name: Post PR comment | |
| if: github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository | |
| continue-on-error: true | |
| uses: actions/github-script@v9 | |
| env: | |
| backend_passed: ${{ steps.backend.outputs.passed }} | |
| backend_failed: ${{ steps.backend.outputs.failed }} | |
| backend_skipped: ${{ steps.backend.outputs.skipped }} | |
| backend_conclusion: ${{ steps.backend.outputs.conclusion }} | |
| cli_passed: ${{ steps.cli.outputs.passed }} | |
| cli_failed: ${{ steps.cli.outputs.failed }} | |
| cli_skipped: ${{ steps.cli.outputs.skipped }} | |
| cli_conclusion: ${{ steps.cli.outputs.conclusion }} | |
| frontend_passed: ${{ steps.frontend.outputs.passed }} | |
| frontend_failed: ${{ steps.frontend.outputs.failed }} | |
| frontend_skipped: ${{ steps.frontend.outputs.skipped }} | |
| frontend_conclusion: ${{ steps.frontend.outputs.conclusion }} | |
| e2e_passed: ${{ steps.e2e.outputs.passed }} | |
| e2e_failed: ${{ steps.e2e.outputs.failed }} | |
| e2e_skipped: ${{ steps.e2e.outputs.skipped }} | |
| e2e_conclusion: ${{ steps.e2e.outputs.conclusion }} | |
| with: | |
| script: | | |
| function suite(label, prefix) { | |
| const passed = parseInt(process.env[`${prefix}_passed`] || '0'); | |
| const failed = parseInt(process.env[`${prefix}_failed`] || '0'); | |
| const skipped = parseInt(process.env[`${prefix}_skipped`] || '0'); | |
| const conclusion = process.env[`${prefix}_conclusion`] || 'skipped'; | |
| const total = passed + failed + skipped; | |
| const emoji = conclusion === 'success' ? '✅' : conclusion === 'failure' ? '❌' : '⏭️'; | |
| return { passed, failed, skipped, total, line: `${emoji} **${label}** — ${passed} passed, ${failed} failed, ${skipped} skipped (${total} total)` }; | |
| } | |
| const results = [ | |
| suite('Backend (pytest)', 'backend'), | |
| suite('CLI (pytest)', 'cli'), | |
| suite('Frontend (vitest)', 'frontend'), | |
| suite('E2E (Playwright)', 'e2e'), | |
| ]; | |
| const sha = context.sha; | |
| const shaLink = `[\`${sha.slice(0, 7)}\`](${context.serverUrl}/${context.repo.owner}/${context.repo.repo}/commit/${sha})`; | |
| const totalPassed = results.reduce((s, r) => s + r.passed, 0); | |
| const totalFailed = results.reduce((s, r) => s + r.failed, 0); | |
| const totalSkipped = results.reduce((s, r) => s + r.skipped, 0); | |
| const total = totalPassed + totalFailed + totalSkipped; | |
| const summary = totalFailed === 0 && totalSkipped === 0 | |
| ? `**Summary:** ✅ All ${total} tests passed` | |
| : `**Summary:** ${totalPassed} ✅ passed` + (totalFailed > 0 ? `, ${totalFailed} ❌ failed` : '') + (totalSkipped > 0 ? `, ${totalSkipped} ⏭️ skipped` : '') + ` (${total} total)`; | |
| const body = `## 🧪 Test Results — ${shaLink}\n\n` | |
| + results.map(r => r.line).join('\n') | |
| + `\n\n${summary}`; | |
| await github.rest.issues.createComment({ | |
| issue_number: context.issue.number, | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| body, | |
| }); |