CI/CD Integration
SqlProof works in any CI environment that can reach a PostgreSQL database. Choose the mode that fits your pipeline.
Mode 1: Testcontainers (Docker-in-CI)
Requires Docker available in the runner. GitHub Actions’ ubuntu-latest includes Docker.
name: Testson: [push, pull_request]
jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: npm - run: npm ci - run: npm run test:integration env: TESTCONTAINERS_RYUK_DISABLED: 'true'No additional secrets required — SqlProof pulls postgres:16 automatically. Set TESTCONTAINERS_RYUK_DISABLED=true to avoid permission issues in restricted CI environments.
In your test file:
const proof = await SqlProof.connect({ schemaFile: './schema.sql',});Mode 2: Connection String (Staging / CI Postgres)
Use a GitHub Actions service container for a real, ephemeral Postgres — no Docker socket tricks needed.
name: Testson: [push, pull_request]
jobs: test: runs-on: ubuntu-latest services: postgres: image: postgres:16 env: POSTGRES_PASSWORD: ci POSTGRES_DB: testdb options: >- --health-cmd pg_isready --health-interval 5s --health-timeout 5s --health-retries 5 ports: - 5432:5432 steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: npm - run: npm ci - run: npm run test:integration env: DATABASE_URL: postgresql://postgres:ci@localhost:5432/testdbIn your test file:
const proof = await SqlProof.connect({ connectionString: process.env.DATABASE_URL!, schemaFile: './schema.sql', // applies DDL to the CI DB — no Docker needed // or: schema: 'public' // introspect an existing live schema});Mode 3: Neon Branching
Each CI run gets its own instant Neon branch (~1 second). No Docker, no service containers.
- Create a Neon project and note the project ID.
- Generate a project-scoped API key in Neon Console → Settings → API Keys.
- Add
NEON_API_KEYandNEON_PROJECT_IDas repository secrets.
name: Testson: [push, pull_request]
jobs: test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: actions/setup-node@v4 with: node-version: 20 cache: npm - run: npm ci - run: npm run test:integration env: NEON_API_KEY: ${{ secrets.NEON_API_KEY }} NEON_PROJECT_ID: ${{ secrets.NEON_PROJECT_ID }}In your test file:
const proof = await SqlProof.connect({ neon: { apiKey: process.env.NEON_API_KEY!, projectId: process.env.NEON_PROJECT_ID!, parentBranch: 'main', // optional — branch from your schema-ready branch }, schema: 'public',});// Branch is created on connect(), deleted on disconnect()The branch is deleted in disconnect() even if the test fails — cleanup is guaranteed.
Vitest Configuration
All modes require pool: 'forks' in Vitest config (required by testcontainers and for process isolation):
import { defineConfig } from 'vitest/config';
export default defineConfig({ test: { pool: 'forks', testTimeout: 120_000, // allow time for container startup or branch creation },});