Skip to content

CI/CD Pipeline

Generated: 2026-01-04

NexisChat uses GitHub Actions for continuous integration and deployment. The pipeline is optimized for monorepo workflows using Turborepo change detection.

WorkflowTriggerPurpose
ci.ymlPush, PRMain CI pipeline
change-detection.ymlCalledDetect changed packages
storybook-tests.ymlPush (main)Visual regression tests
knip.ymlPRUnused code detection
todo-to-issue.ymlPush (main)Convert TODOs to issues
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
┌─────────────────┐
│ change-detection│ Determine affected packages
└────────┬────────┘
┌─────────────────┐
│ typecheck │ TypeScript validation
└────────┬────────┘
┌────┴────┐
▼ ▼
┌───────┐ ┌───────┐
│ lint │ │format │ Code quality
└───┬───┘ └───┬───┘
│ │
└────┬────┘
┌─────────────────┐
│ build │ Production builds
└────────┬────────┘
┌─────────────────┐
│ test │ Unit tests + coverage
└────────┬────────┘
┌─────────────────┐
│ coverage │ Upload to Codecov
└─────────────────┘

The pipeline uses Turborepo’s --filter to only process changed packages:

jobs:
change-detection:
runs-on: ubuntu-latest
outputs:
client: ${{ steps.filter.outputs.client }}
server: ${{ steps.filter.outputs.server }}
ui: ${{ steps.filter.outputs.ui }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v2
id: filter
with:
filters: |
client:
- 'apps/client/**'
- 'packages/ui/**'
server:
- 'apps/server/**'
ui:
- 'packages/ui/**'
- name: Setup pnpm
uses: pnpm/action-setup@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'pnpm'
- name: Turborepo Cache
uses: actions/cache@v4
with:
path: .turbo
key: turbo-${{ runner.os }}-${{ hashFiles('**/pnpm-lock.yaml') }}
restore-keys: |
turbo-${{ runner.os }}-
- name: Run Tests
run: pnpm test:coverage
- name: Upload Coverage
uses: codecov/codecov-action@v4
with:
files: ./apps/server/coverage/lcov.info,./packages/ui/coverage/lcov.info
fail_ci_if_error: false

Visual regression testing with Chromatic:

on:
push:
branches: [main]
paths:
- 'packages/ui/**'
jobs:
chromatic:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Required for Chromatic
- name: Install dependencies
run: pnpm install
- name: Build Storybook
run: pnpm --filter ui build:storybook
- name: Chromatic
uses: chromaui/action@v1
with:
projectToken: ${{ secrets.CHROMATIC_PROJECT_TOKEN }}
workingDir: packages/ui

Detect unused exports, dependencies, and files:

on:
pull_request:
branches: [main]
jobs:
knip:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pnpm install
- run: pnpm knip

The CI uses a self-hosted runner for faster builds:

jobs:
build:
runs-on: self-hosted
# Fallback to ubuntu-latest if self-hosted unavailable
  1. Install GitHub Actions runner on build machine
  2. Configure with repository access
  3. Install required tools: Node.js, pnpm, Docker
  4. Add labels: self-hosted, linux, x64
SecretUsed ByPurpose
DATABASE_URLserver, whatsapp-web-serverTest database
WORKOS_CLIENT_IDserverAuth testing
WORKOS_API_KEYserverAuth testing
CREEM_API_KEYserverPayment testing
SENTRY_DSNclient, subscriptionError tracking
CODECOV_TOKENCICoverage uploads
CHROMATIC_PROJECT_TOKENuiVisual tests
env:
CI: true
DATABASE_URL: ${{ secrets.DATABASE_URL }}
TURBO_TOKEN: ${{ secrets.TURBO_TOKEN }}
TURBO_TEAM: ${{ secrets.TURBO_TEAM }}

Vercel (Client, Subscription, Docs, Landing)

Section titled “Vercel (Client, Subscription, Docs, Landing)”

Automatic deployments via Vercel GitHub integration:

  1. Push to main → Production deploy
  2. Push to PR → Preview deploy

Configuration in vercel.json per app.

Deploy via Railway GitHub integration:

  1. Connect repository
  2. Configure build command: pnpm --filter server build
  3. Configure start command: pnpm --filter server start
  4. Set environment variables
  • Require pull request before merge
  • Require status checks:
    • typecheck
    • lint
    • build
    • test
  • Require up-to-date branches
  • Require linear history (squash merge)

Test CI pipeline locally with act:

Terminal window
# Install act
brew install act
# Run CI workflow
act push
# Run specific job
act -j build
# With secrets
act --secret-file .secrets
Terminal window
# Clear Turborepo cache
rm -rf .turbo
# Clear pnpm cache
pnpm store prune
  1. Check for race conditions
  2. Ensure test isolation
  3. Use deterministic mocks
  4. Add retry configuration:
- name: Run Tests
run: pnpm test
env:
VITEST_MAX_THREADS: 1 # Reduce parallelism
  1. Check Node.js version matches local
  2. Verify all dependencies in pnpm-lock.yaml
  3. Check for missing environment variables
  4. Review Turborepo pipeline dependencies
  • View workflow runs: Actions tab
  • Check run times: Actions → Workflow → Run
  • Download artifacts: Actions → Run → Artifacts
  • Coverage trends
  • PR coverage diff
  • File-level coverage
  • Visual diff review
  • Component snapshots
  • Build history