Skip to main content

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:

  1. Automated testing on every push/PR (backend, frontend, Rust)
  2. Automated Tauri desktop app builds on release, with binaries as downloadable GitHub Release assets
  3. Frontend coverage tracking with line-level reporting (see exactly which lines aren't covered)
  4. 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

OptionProsConsChosen?
In-repo (vitest reporters + GH Actions artifacts)No external deps, lcov for line-level, HTML for browsingNo historical dashboardYes
CodecovBeautiful dashboard, PR annotations, badgesExternal service, token management, privacy concernNo
CoverallsSimilar to CodecovSame concerns as CodecovNo

3. Decision

Chosen approach: GitHub Actions with 3 workflows + enhanced vitest coverage

Reasoning:

  • Native GitHub integration eliminates infrastructure overhead
  • tauri-apps/tauri-action is 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

StepDescriptionEffortDependencies
1Create CI workflow (ci.yml) — backend tests, frontend tests/build/lintMNone
2Create Release workflow (release.yml) — Tauri cross-platform builds with Apple signingMNone
3Create Rust tests workflow (rust-tests.yml) — cargo test on schedule + Rust changesSNone
4Update vitest.config.ts — add lcov/html reporters, 80% coverage thresholdsXSNone
5Update project docs (status.md, ROADMAP.md)XSSteps 1–4

Step 1: CI Workflow (.github/workflows/ci.yml)

Triggers: push to main, pull_request to main

Jobs (all parallel):

  1. 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)
  2. 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-action for PR annotations
  3. frontend-build (~1 min)

    • Runner: ubuntu-latest
    • Steps: checkout → Node.js 22 + npm ci → npm run build (tsc + vite)
  4. frontend-lint (~30s)

    • Runner: ubuntu-latest
    • Steps: checkout → Node.js 22 + npm ci → npm run lint

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:

PlatformRunnerArtifactsSigning
macOS (Universal)macos-latest.dmgApple Developer ID (notarized)
Windowswindows-latest.msi, .exeUnsigned (for now)
Linuxubuntu-22.04.AppImage, .debN/A

Apple Signing — Required GitHub Secrets:

  • APPLE_CERTIFICATE — Base64-encoded .p12 certificate
  • APPLE_CERTIFICATE_PASSWORD — Password for the .p12
  • APPLE_SIGNING_IDENTITY — e.g., "Developer ID Application: Name (TEAMID)"
  • APPLE_ID — Apple ID email for notarization
  • APPLE_PASSWORD — App-specific password for notarization
  • APPLE_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 ~/.cargo and target/ directory (saves ~5 min on subsequent runs)

Step 4: Vitest Coverage Enhancement

Changes to frontend/vitest.config.ts:

  • Add lcov reporter (generates lcov.info for line-level tooling)
  • Add html reporter (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

QuestionAnswer
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