CI/CD Pipeline
Kuviq uses GitHub Actions for continuous integration and deployment.
Current Metrics (March 2026):
- 402 test suites
- 6,805 passing tests, 0 skipped
- Full CI run: ~5 minutes
- Automatic deployment on push to main/master
Pipeline Overview
Push to main/master
↓
┌─────────────────────────────────────┐
│ Parallel Jobs: │
│ - lint (ESLint) │
│ - typecheck (TypeScript) │
│ - test-unit │
│ - test-integration │
│ - test-api (MSW) │
│ - test-e2e (Playwright) │
└─────────────────────────────────────┘
↓
build (after lint + typecheck)
↓
lighthouse (performance audit)
↓
ci-success (all checks passed)
↓
deploy (only on main/master push)
↓
Version bump + Firebase deploy
Jobs
Lint
Runs ESLint to check code quality and formatting.
Type Check
Runs TypeScript compiler (tsc --noEmit) to verify types.
Test Jobs
- test-unit: Vitest unit tests
- test-integration: Vitest integration tests
- test-api: MSW-based API mocking tests
- test-e2e: Playwright browser tests
Build
Builds the production application to verify it compiles successfully.
Lighthouse
Runs Lighthouse CI to audit:
- Performance (budget-enforced LCP/FCP thresholds)
- Accessibility (target: 95%)
- Best Practices (target: 95%)
- SEO (target: 95%)
Quality Gates
The CI pipeline enforces strict quality gates:
- Bundle size budgets — fails if JS bundle exceeds configured limits
- Core Web Vitals — LCP and FCP thresholds enforced
- Zero lint errors — ESLint must pass with 0 warnings
- Zero type errors — TypeScript strict mode, no errors
- All tests passing — no skipped tests allowed in CI
Deploy
Only runs on pushes to main or master branch:
- Updates version using
npm run version:date - Builds the application
- Deploys to Firebase Hosting
- Pushes version commit back to repository
Local Hooks
Pre-commit Hook
Checks test files follow project standards (using renderWithTheme).
Pre-push Hook
Runs before every git push:
- TypeScript type check
- ESLint
- Unit tests
This catches issues locally before using CI minutes.
GitHub Secrets Required
| Secret | Description |
|---|---|
FIREBASE_SERVICE_ACCOUNT | Firebase service account JSON for deployment |
Setting up Firebase Service Account
- Go to Firebase Console → Project Settings → Service Accounts
- Click "Generate new private key"
- Download the JSON file
- Add to GitHub: Settings → Secrets → Actions → New repository secret
- Name:
FIREBASE_SERVICE_ACCOUNT - Value: Paste entire JSON contents
Workflow File
The CI configuration is in .github/workflows/ci.yml.
Skipping CI
To skip CI for a commit (e.g., documentation-only changes):
git commit -m "docs: update readme [skip ci]"
Scheduled Cloud Functions
Trial Processing
The following Cloud Functions run on a daily schedule to manage trial lifecycle:
| Function | Schedule | Description |
|---|---|---|
processTrialExpirations | Daily | Checks all trial orgs and transitions expired trials to subscriptionStatus = 'expired' |
processAutoExtensions | Daily (within expiration processing) | Evaluates pending extension requests against activity thresholds for auto-approval; proactively creates extensions for qualifying orgs with 1 day remaining |
sendTrialExpirationEmails | Daily | Sends 3-day warning, 1-day warning, and expired emails to organization owners; deduplicates via trialEmails subcollection |
sendTrialOnboardingEmails | Daily | Sends Day 1/3/7/10 onboarding emails with activity-based personalization |
All email functions:
- Support English, Finnish, and Swedish via
resolveLanguage() - Use Brevo (Sendinblue) for transactional email delivery
- Track sent emails in
organizations/{orgId}/trialEmailssubcollection to prevent duplicates - Continue processing remaining organizations if an individual send fails
Observability
Kuviq uses Sentry for error tracking and performance monitoring across the entire stack.
Frontend
ContextErrorBoundarywraps all context providers and reports errors to Sentry- Automatic error capture with user and organization context
- Performance tracing for page loads and key interactions
Cloud Functions
- All Cloud Functions are wrapped with Sentry error handlers
- Captures unhandled exceptions with function name and trigger context
- Performance monitoring for function execution time
Monitoring
- View pipeline status: GitHub repo → Actions tab
- Lighthouse reports: Available as artifacts on failed runs
- Playwright reports: Available as artifacts on failed runs
- Sentry dashboard: Real-time error tracking and performance