CapyDB Docs
GuidesIntegrations

GitHub Action

A disposable preview database for every pull request - idempotent create, masked outputs, TTL backstop.

What it does

capy-base/capydb-preview-action@v1 creates a CapyDB preview database for a pull request, waits for it to be ready, and exports the connection strings into the job environment. It talks to the API with curl + jq (preinstalled on GitHub runners) — nothing to install, nothing to cache.

Usage

.github/workflows/preview-database.yml
name: preview-database

on:
  pull_request:
    types: [opened, synchronize, reopened, closed]

jobs:
  preview:
    runs-on: ubuntu-latest
    steps:
      - name: Create preview database
        if: github.event.action != 'closed'
        id: capydb
        uses: capy-base/capydb-preview-action@v1
        with:
          api-key: ${{ secrets.CAPYDB_API_KEY }}
          project-id: ${{ vars.CAPYDB_PROJECT_ID }}

      - name: Run migrations + tests against the preview
        if: github.event.action != 'closed'
        run: |
          pnpm db:migrate
          pnpm test
        # DATABASE_URL / DATABASE_URL_UNPOOLED are already exported by the
        # action (write-env defaults to true).

      - name: Delete preview database
        if: github.event.action == 'closed'
        uses: capy-base/capydb-preview-action@v1
        with:
          api-key: ${{ secrets.CAPYDB_API_KEY }}
          project-id: ${{ vars.CAPYDB_PROJECT_ID }}
          command: delete

Inputs

InputDefaultDescription
api-key— (required)CapyDB API key. Use a project-scoped key stored in repo secrets.
project-id— (required)The CapyDB project the preview belongs to.
commandcreatecreate (idempotent), reset, or delete.
namepr-<number> / branch slugPreview name; re-running with the same name reuses the database.
modecloneclone copies production data; empty starts blank.
ttl-hours72Auto-delete after this many hours (1–168).
api-urlhttps://capydb.dev/api/capydbOverride for self-hosted control planes.
wait-timeout600Seconds to wait for the preview to become ready.
write-envtrueExport DATABASE_URL / DATABASE_URL_UNPOOLED into the job env.

Outputs

OutputDescription
preview-idID of the preview database.
preview-nameResolved preview name.
database-urlPooled connection string (masked).
database-url-unpooledDirect connection string (masked).

Behavior worth knowing

  • create is idempotent: pushing more commits to the same PR reuses the existing preview and extends its TTL instead of recreating it. Use command: reset if you want a fresh clone on every push.
  • Masked outputs: connection strings are registered with ::add-mask:: so they never appear in logs.
  • TTL backstop: previews expire via their TTL even if the closed job never runs (force-pushed branch, cancelled workflow), so a missed cleanup cannot leak databases forever.
  • Key scoping: create the API key in the dashboard under Settings → API keys with a project_id, scoped to the single project the workflow uses. A leaked project-scoped key cannot touch sibling projects or the org. See Authentication.
  • Ordering: unlike the Vercel/Netlify deploy-webhook flow, the Action is synchronous — database first, then your steps. Use it when build steps need the database to exist.