Keel

Docs / Deployment / CI checks

CI checks

The pipeline lives in .github/workflows/ci.yml. It runs two jobs, test and e2e, both against a real Postgres, so a fork gets the same guarantees Keel is built with. Here's what runs and what a buyer needs to make it pass.

What triggers it

The workflow runs on every push to main and on every pull request. Both jobs run in parallel on ubuntu-latest.

Shared setup

Both jobs spin up a postgres:17 service container (user/password/db all keel, on port 5432) with a pg_isready healthcheck, so steps don't start until the database is actually up. The connection details are set once at the workflow level:

  • DATABASE_URL, postgresql://keel:keel@localhost:5432/keel, pointing at that service.
  • BETTER_AUTH_SECRET, a throwaway placeholder value (fine, CI never handles real sessions).
  • BETTER_AUTH_URL, http://localhost:3000.

A placeholder connection string won't do here: the lib/**/*.test.ts specs added alongside the money-path race fixes exercise real DB constraints, unique indexes, CHECK constraints, and transactions, that only a live Postgres enforces.

The test job

After actions/checkout and Node 22 setup with npm cache, it runs:

  • npm ci, clean install from the lockfile.
  • npm run typecheck, tsc --noEmit.
  • npm run lint, ESLint.
  • npm run db:migrate, applies migrations to the service Postgres so the schema exists before tests query it.
  • npm run test, the Vitest suite (vitest run).

The e2e job

Same checkout, Node, and Postgres setup, then:

  • npm ci
  • npm run db:migrate
  • npx playwright install --with-deps chromium, installs the browser.
  • npm run test:e2e, the Playwright suite.
  • On failure only, it uploads the playwright-report/ directory as an artifact (14-day retention) so you can inspect what broke.

If you fork this

The pipeline needs no repository secrets to pass. Every value it depends on (DATABASE_URL, the auth vars) is hardcoded in the workflow and points at the ephemeral Postgres service, and Postgres comes from GitHub's own service containers. Clone, push, and both jobs run green without touching Actions settings.

Node here, Bun locally

CI uses npm ci and npm run, while local dev and the README use Bun. The scripts are identical, only the runner differs, so a green CI run and your local bun run test are checking the same thing.

Edit this page on GitHub →Last updated Jul 22, 2026