feat(platform): 9.5-grade hardening — E2E, coverage gates, observabil… #186
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: CI | |
| on: | |
| push: | |
| branches: [master, main] | |
| tags: | |
| - "v*" | |
| pull_request: | |
| branches: [master, main] | |
| permissions: | |
| contents: write | |
| jobs: | |
| backend-tests: | |
| name: Backend Tests | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: backend | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| cache: pip | |
| cache-dependency-path: backend/requirements-test.txt | |
| - run: pip install -r requirements-test.txt | |
| - name: Python lint (ruff) | |
| run: | | |
| pip install "ruff>=0.4" | |
| ruff check app | |
| - name: Run unit tests with coverage | |
| run: python -m pytest tests/unit/ -v --tb=short --cov --cov-report=term --cov-report=xml:coverage.xml | |
| # Run the WHOLE integration suite, not just one file (test_aws_integration.py | |
| # was previously never executed in CI). | |
| - run: python -m pytest tests/integration/ -v --tb=short | |
| - run: python -m pytest tests/e2e/ -v --tb=short --run-e2e | |
| - name: Upload backend coverage | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| files: backend/coverage.xml | |
| flags: backend | |
| fail_ci_if_error: false | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| lint-and-test: | |
| name: Lint & Test | |
| runs-on: ubuntu-latest | |
| defaults: | |
| run: | |
| working-directory: frontend | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - run: npm ci | |
| - run: npm run lint | |
| - run: npx tsc --noEmit | |
| - name: Run unit tests with coverage | |
| run: npm test -- --run --reporter=verbose --coverage | |
| - name: Upload frontend coverage | |
| uses: codecov/codecov-action@v5 | |
| with: | |
| files: frontend/coverage/lcov.info | |
| flags: frontend | |
| fail_ci_if_error: false | |
| token: ${{ secrets.CODECOV_TOKEN }} | |
| electron-tests: | |
| name: Electron Tests | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Install dependencies | |
| run: npm ci | |
| # vitest runs the electron tests under Node, but postinstall | |
| # (electron-builder install-app-deps) rebuilds better-sqlite3 for the | |
| # Electron ABI. The pretest hook on test:scheduler rebuilds it for the | |
| # Node ABI so the DB-backed tests load. | |
| - name: Run electron test suite | |
| run: npm run test:scheduler | |
| e2e-tests: | |
| name: Full-stack E2E | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-python@v5 | |
| with: | |
| python-version: '3.12' | |
| cache: pip | |
| cache-dependency-path: backend/requirements.txt | |
| - run: pip install -r backend/requirements.txt | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - run: npm ci | |
| working-directory: frontend | |
| - name: Install Playwright browsers | |
| run: npx playwright install --with-deps chromium | |
| working-directory: frontend | |
| - name: Run full-stack E2E suite | |
| run: npm run test:e2e | |
| working-directory: frontend | |
| - name: Upload E2E artifacts on failure | |
| if: failure() | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: playwright-report | |
| path: frontend/playwright-report | |
| retention-days: 7 | |
| build: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| needs: [backend-tests, lint-and-test] | |
| defaults: | |
| run: | |
| working-directory: frontend | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - run: npm ci | |
| - run: npm run build | |
| release: | |
| name: Release Windows Installer | |
| runs-on: windows-latest | |
| # All test suites + build must pass before we cut a release. electron-tests | |
| # gates here because the desktop app IS the shipped Windows/macOS artifact. | |
| needs: [backend-tests, lint-and-test, electron-tests, e2e-tests, build] | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Install root dependencies | |
| run: npm install | |
| - name: Install frontend dependencies | |
| run: cd frontend && npm ci | |
| - name: Build and publish | |
| run: npm run publish | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| release-mac: | |
| name: Release macOS DMG | |
| runs-on: macos-latest | |
| # Serialized after the Windows release job so both publish into ONE draft | |
| # release: 'release' creates the draft + uploads the .exe, then 'release-mac' | |
| # finds that draft and uploads the .dmg. Avoids the split-draft race. | |
| needs: [backend-tests, lint-and-test, electron-tests, build, release] | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - uses: actions/setup-node@v4 | |
| with: | |
| node-version: 20 | |
| - name: Install root dependencies | |
| run: npm install | |
| - name: Install frontend dependencies | |
| run: cd frontend && npm ci | |
| - name: Build and publish | |
| run: npm run publish:mac | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} |