How to run Tango in CI/CD
Tango applications are easiest to operate in CI/CD when pipeline jobs follow the same boundaries as the framework:
- configuration comes from
tango.config.ts - schema state is managed through migrations
- integration tests run against the same database family you deploy
The sections below give a practical baseline for GitHub Actions and GitLab pipelines, then cover database environments and migration strategy.
Pipeline shape
A strong default pipeline has three concerns:
- static verification (
typecheck, lint, unit tests) - integration verification against a real database with migrations applied
- deployment steps that run migrations once before serving the new build
That separation keeps fast feedback in early jobs while still proving schema compatibility before release.
GitHub Actions baseline
This workflow runs static checks, then integration tests on both SQLite and PostgreSQL.
name: ci
on:
pull_request:
push:
branches: [main]
jobs:
verify:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm typecheck
- run: pnpm test
integration:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
dialect: [sqlite, postgres]
services:
postgres:
image: postgres:16
env:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: tango_test
ports:
- 5432:5432
options: >-
--health-cmd "pg_isready -U postgres -d tango_test"
--health-interval 10s
--health-timeout 5s
--health-retries 10
env:
NODE_ENV: test
TANGO_DB_ADAPTER: ${{ matrix.dialect }}
TANGO_SQLITE_FILENAME: ':memory:'
TANGO_DATABASE_URL: postgres://postgres:postgres@localhost:5432/tango_test
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
version: 9
- uses: actions/setup-node@v4
with:
node-version: 22
cache: pnpm
- run: pnpm install --frozen-lockfile
- run: pnpm exec tango migrate --config ./tango.config.ts --env test
- run: pnpm test:integrationGitLab pipeline baseline
This .gitlab-ci.yml uses a similar structure with verify and integration stages.
stages:
- verify
- integration
default:
image: node:22
before_script:
- corepack enable
- corepack prepare pnpm@9 --activate
- pnpm install --frozen-lockfile
verify:
stage: verify
script:
- pnpm typecheck
- pnpm test
integration:postgres:
stage: integration
services:
- name: postgres:16
alias: postgres
variables:
NODE_ENV: test
TANGO_DB_ADAPTER: postgres
TANGO_DATABASE_URL: postgres://postgres:postgres@postgres:5432/tango_test
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: tango_test
script:
- pnpm exec tango migrate --config ./tango.config.ts --env test
- pnpm test:integration
integration:sqlite:
stage: integration
variables:
NODE_ENV: test
TANGO_DB_ADAPTER: sqlite
TANGO_SQLITE_FILENAME: ':memory:'
script:
- pnpm exec tango migrate --config ./tango.config.ts --env test
- pnpm test:integrationDatabase environments
tango.config.ts should define stable defaults for development, test, and production, then CI/CD can override specific values per job.
A common pattern is:
- local development: SQLite file for fast iteration
- CI integration: PostgreSQL for production-parity verification
- production: PostgreSQL with deployment-provided connection values
Environment overrides supported by @danceroutine/tango-config let pipeline jobs switch behavior without changing application code:
TANGO_DB_ADAPTERTANGO_DATABASE_URLorDATABASE_URLTANGO_SQLITE_FILENAMETANGO_DB_HOST,TANGO_DB_PORT,TANGO_DB_NAME,TANGO_DB_USER,TANGO_DB_PASSWORDTANGO_MIGRATIONS_DIRTANGO_MIGRATIONS_ONLINE
Migrations in CI
Integration jobs should run migrations against an empty or disposable test database before tests execute:
pnpm exec tango migrate --config ./tango.config.ts --env test
pnpm test:integrationThis catches migration-order problems and schema drift in the same pipeline run that validates behavior.
Useful companion checks in CI:
pnpm exec tango status --config ./tango.config.ts --env testafter migrate for applied/pending visibilitypnpm exec tango plan --config ./tango.config.ts --env testwhen you want SQL output as build logs or artifacts
Migrations in CD
Deployment should treat migrations as a release step, not a background startup side effect.
A practical release sequence is:
- build and publish the application artifact
- run
tango migrateonce for the target environment - verify migration status
- shift traffic to the new application version
Typical commands:
pnpm exec tango migrate --config ./tango.config.ts --env production
pnpm exec tango status --config ./tango.config.ts --env productionRunning migrations in a single deployment job prevents race conditions when multiple application instances start at the same time.
Multi-database deployments
When applications use multiple databases, keep migration execution explicit per database target.
A safe pattern is:
- one config profile or override set per database
- one migration command per database in a controlled order
- integration tests that cover every supported database family
That keeps migration policy visible in the pipeline instead of spreading it across application startup paths.