seed every supabase preview branch.
Supabase preview branches ship with an empty database. Run satus once after the branch is created and every PR review gets a fully seeded environment. The 10,000-row safety guard is harmless here: preview branches start at zero.
# pull the postgres url from the supabase CLI$ export DATABASE_URL=$(supabase --experimental branches get $BRANCH --output json | jq -r .POSTGRES_URL)$ export OPENAI_API_KEY=$OPENAI_API_KEY# seed it. one transaction. all-or-nothing.$ satus generate --profile ecommerce --rows 50✓ inserted 250 rows across 5 tables
Each run generates fresh data—the model varies values by design. If a review depends on stable fixtures, keep the branch alive instead of re-seeding it, or snapshot the seeded state with pg_dump.
one job. one step. one secret per env.
The most common shape. Plan in PR jobs (no writes, free), generate on merge to main or against ephemeral DBs.
# .github/workflows/seed.yml$ name: seed$ on: { pull_request: {}, push: { branches: [main] } }$ jobs:$ seed:$ runs-on: ubuntu-latest$ env:$ DATABASE_URL: ${{ secrets.DATABASE_URL }}$ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}$ steps:$ - uses: actions/checkout@v4$ - uses: actions/setup-node@v4$ with: { node-version: 20 }$ - run: npm i -g @passkeybridge/satus$ - run: satus generate --profile saas --dry-run --json$ if: github.event_name == 'pull_request'$ - run: satus generate --profile saas$ if: github.ref == 'refs/heads/main'
satus generate --dry-run --json introspects but never writes and never calls the model—no LLM key needed, no spend. It exits non-zero when the relational validator finds errors, so it works as a PR gate for schema-breaking changes.
fresh data between every test suite.
Cypress, Playwright, and Vitest E2E suites need a known-good database state. The pattern: seed once with --truncate, snapshot the result with pg_dump, and restore that fixture between suites— restores are fast and byte-identical, which generation is not.
# scripts/reset-test-db.sh$ #!/usr/bin/env bash$ set -euo pipefail# truncate the target tables and re-seed in one run$ satus generate --profile ecommerce --truncate
--truncate issues TRUNCATE ... RESTART IDENTITY on the run’s tables inside the same transaction as the inserts, so sequences reset and a failed run leaves the old data in place. Note the absent CASCADE: if a table outside the run set has a foreign key into one inside it, satus stops with an error rather than emptying a table you never asked it to seed. Bring that table into the run set or truncate it yourself. Wire this into Cypress’s before(...) hook or Playwright’s globalSetup.
seed a fresh neon branch in one shell.
Neon's copy-on-write branches make per-developer or per-PR databases cheap. Combine that with satus and every engineer gets their own seeded database for the cost of the branch metadata.
# create a branch and capture its connection string$ BRANCH=$(neon branches create --name pr-$PR --project-id $NEON_PROJECT_ID --output json)$ export DATABASE_URL=$(echo "$BRANCH" | jq -r .connection_uris[0].connection_uri)# seed$ satus generate --profile saas
Tear the branch down on PR close. Neon charges per active branch—a stale fleet of seeded branches will surprise the bill.
Have a recipe you want documented? Email support@satus.sh. We add the most-requested integrations first.