Feature: GitHub Actions CI/CD Pipeline
Date: 2026-02-12 Status: Completed
1. Context & Motivation
Morphee has zero CI/CD automation — all 1,839 tests and builds are run manually. This creates risk of regressions, makes collaboration harder, and means no automated desktop app distribution.
Goals:
- Automated testing on every push/PR (backend, frontend, Rust)
- Automated Tauri desktop app builds on release, with binaries as downloadable GitHub Release assets
- Frontend coverage tracking with line-level reporting (see exactly which lines aren't covered)
- 80% coverage threshold enforcement
2. Options Investigated
Option A: GitHub Actions (Chosen)
- Description: Native GitHub CI/CD, free for public repos, 2000 min/month for private
- Pros: Zero infrastructure, native GitHub integration, matrix builds for cross-platform Tauri, built-in artifact/release upload, service containers for PostgreSQL/Redis
- Cons: macOS runners are slower and more expensive (10x Linux cost)
- Estimated effort: M
Option B: Self-hosted CI (Drone, Jenkins, Gitea Actions)
- Description: Self-managed CI runners
- Pros: Full control, no minute limits, can reuse Docker Compose setup
- Cons: Infrastructure overhead, maintenance burden, no native GitHub Release integration
- Estimated effort: L–XL
Option C: External CI (CircleCI, GitLab CI)
- Description: Third-party CI services
- Pros: Powerful caching, parallelism
- Cons: Another service to manage, GitHub Release integration requires extra setup, vendor lock-in
- Estimated effort: M
Coverage Reporting Options
| Option | Pros | Cons | Chosen? |
|---|---|---|---|
| In-repo (vitest reporters + GH Actions artifacts) | No external deps, lcov for line-level, HTML for browsing | No historical dashboard | Yes |
| Codecov | Beautiful dashboard, PR annotations, badges | External service, token management, privacy concern | No |
| Coveralls | Similar to Codecov | Same concerns as Codecov | No |
3. Decision
Chosen approach: GitHub Actions with 3 workflows + enhanced vitest coverage
Reasoning:
- Native GitHub integration eliminates infrastructure overhead
tauri-apps/tauri-actionis the official way to build Tauri apps in CI- Service containers (PostgreSQL, Redis) are simpler and faster than Docker Compose in CI
- In-repo coverage reporting avoids external service dependencies (privacy-first project)
Trade-offs accepted:
- macOS runners cost 10x Linux (mitigated by only running on release, not every PR)
- Rust tests run on schedule/Rust changes only (compilation is slow)
- No historical coverage dashboard (can add later)
4. Implementation Plan
| Step | Description | Effort | Dependencies |
|---|---|---|---|
| 1 | Create CI workflow (ci.yml) — backend tests, frontend tests/build/lint | M | None |
| 2 | Create Release workflow (release.yml) — Tauri cross-platform builds with Apple signing | M | None |
| 3 | Create Rust tests workflow (rust-tests.yml) — cargo test on schedule + Rust changes | S | None |
| 4 | Update vitest.config.ts — add lcov/html reporters, 80% coverage thresholds | XS | None |
| 5 | Update project docs (status.md, ROADMAP.md) | XS | Steps 1–4 |
Step 1: CI Workflow (.github/workflows/ci.yml)
Triggers: push to main, pull_request to main
Jobs (all parallel):
-
backend-tests(~3-4 min)- Runner:
ubuntu-latest - Service containers: PostgreSQL 15, Redis 7
- Steps: checkout → apply 6 SQL migrations → Python 3.12 + pip install → pytest with coverage
- Env vars: DATABASE_URL, SUPABASE_JWT_SECRET, ENCRYPTION_KEY, etc. (dummy values for CI)
- Runner:
-
frontend-tests(~2 min)- Runner:
ubuntu-latest - Steps: checkout → Node.js 22 + npm ci →
vitest run --coverage→ upload coverage artifacts (HTML + lcov) → PR coverage comment - Uses
davelosert/vitest-coverage-report-actionfor PR annotations
- Runner:
-
frontend-build(~1 min)- Runner:
ubuntu-latest - Steps: checkout → Node.js 22 + npm ci →
npm run build(tsc + vite)
- Runner:
-
frontend-lint(~30s)- Runner:
ubuntu-latest - Steps: checkout → Node.js 22 + npm ci →
npm run lint
- Runner:
Step 2: Release Workflow (.github/workflows/release.yml)
Triggers: GitHub Release created (released event)
Strategy: Uses tauri-apps/tauri-action@v0 with a build matrix:
| Platform | Runner | Artifacts | Signing |
|---|---|---|---|
| macOS (Universal) | macos-latest | .dmg | Apple Developer ID (notarized) |
| Windows | windows-latest | .msi, .exe | Unsigned (for now) |
| Linux | ubuntu-22.04 | .AppImage, .deb | N/A |
Apple Signing — Required GitHub Secrets:
APPLE_CERTIFICATE— Base64-encoded .p12 certificateAPPLE_CERTIFICATE_PASSWORD— Password for the .p12APPLE_SIGNING_IDENTITY— e.g., "Developer ID Application: Name (TEAMID)"APPLE_ID— Apple ID email for notarizationAPPLE_PASSWORD— App-specific password for notarizationAPPLE_TEAM_ID— Team ID
All artifacts are automatically uploaded to the GitHub Release as downloadable assets.
Step 3: Rust Tests Workflow (.github/workflows/rust-tests.yml)
Triggers:
- Push/PR that changes
frontend/src-tauri/** - Weekly schedule (Sunday midnight UTC)
Job:
- Runner:
ubuntu-latest - Steps: checkout → Rust toolchain → cargo cache →
cargo test - Caches
~/.cargoandtarget/directory (saves ~5 min on subsequent runs)
Step 4: Vitest Coverage Enhancement
Changes to frontend/vitest.config.ts:
- Add
lcovreporter (generateslcov.infofor line-level tooling) - Add
htmlreporter (browsable coverage report) - Add coverage thresholds:
lines: 80, branches: 80, functions: 80, statements: 80 reportOnFailure: true— still generate reports even when thresholds fail
5. Questions & Answers
| Question | Answer |
|---|---|
| Can backend tests run without Supabase Auth? | Yes — auth is 100% mocked via dependency injection in conftest.py |
| Do backend tests need real PostgreSQL? | Yes — asyncpg connections are real. Service container works. |
| How are migrations applied? | 6 SQL files in supabase/migrations/ run in order against the service container |
| What about pgvector extension? | Migration 002 uses pgvector — need pgvector/pgvector:pg15 Docker image |
| Does fastembed model download block Rust CI? | Yes (~30MB), but cargo cache + model cache mitigates this |
| Are there secrets needed for CI tests? | No — all test env vars use dummy values (no real API keys) |
6. Open Items
- Windows code signing: Not configured. Can be added later with a certificate.
- Historical coverage tracking: Could add a coverage badge or dashboard later (Codecov, custom GitHub Pages)
- E2E tests in CI: Playwright tests need a running backend — could add as a separate job later with Docker Compose
- Dependabot: Could add dependency update automation
- Branch protection rules: Recommend requiring CI to pass before merging (manual GitHub setting)
7. References
- Tauri GitHub Action — Official Tauri CI/CD action
- GitHub Actions Service Containers
- Vitest Coverage — v8 provider, reporters, thresholds
- davelosert/vitest-coverage-report-action — PR coverage comments
- Apple Code Signing for Tauri — Tauri v2 macOS signing docs