CI/CD Database Seeding
- Use
SEEDFAST_API_KEYenvironment variable for non-interactive CI/CD authentication - The
--scopeflag accepts natural language descriptions of what to seed --output jsonenables machine-readable output for pipeline validation- Always run database migrations before seeding
- Create separate API keys per environment (dev, staging, production)
Most teams rely on one of these approaches β and each has drawbacks:
Static SQL dumps β contain real or semi-anonymized production data, drift from live schemas, require constant maintenance.
Custom seeding scripts β become unmaintainable code that breaks with every schema change.
Shared test databases β create race conditions and test pollution between concurrent runs.
There's also a deeper issue with any approach based on production data: even anonymized or masked records start from something real. That creates compliance exposure β there's always something that needs protecting, auditing, or GDPR-scoping.
Seedfast generates data from scratch on every run. Your production records are never involved:
- No production data β data is synthesized from your schema on every pipeline run, nothing to anonymize or protect
- Schema-adaptive β Seedfast reads your live schema; no script rewrites after migrations
- Isolated per run β each pipeline job seeds its own database; no shared state, no race conditions
Make sure you have:
- A Seedfast account (sign up at seedfa.st)
- A PostgreSQL database accessible from your CI/CD environment
- Access to configure secrets in your CI/CD platform
API keys authenticate the Seedfast CLI in non-interactive environments where browser-based login isn't possible.
- Log in and open the Seedfast Dashboard
- Click API Keys in the left sidebar
- Click Create new key and enter a name (e.g. "GitHub Actions")
- Copy the key immediately β it won't be shown again
Your API key format: sfk_live_a1b2c3d4e5f6...
Tip: Create separate keys for each environment (dev, staging, production). This enables independent rotation and revocation.
Store your API key and database credentials as encrypted secrets in your CI/CD platform.
GitHub Actions: Go to repository β Settings β Secrets and variables β Actions β New repository secret:
SEEDFAST_API_KEY=sfk_live_...
SEEDFAST_DSN=postgres://user:pass@host:5432/db
Note: Use SEEDFAST_DSN rather than DATABASE_URL. Many CI environments already set DATABASE_URL for other tools β using SEEDFAST_DSN avoids conflicts. The CLI checks SEEDFAST_DSN first, then falls back to DATABASE_URL.
GitLab CI: Go to project β Settings β CI/CD β Variables. Mark as Masked and Protected.
CircleCI: Go to Project Settings β Environment Variables.
The simplest way to run Seedfast in CI/CD is via npx:
npx seedfast seed --scope "Your scope description" --output json
The --scope flag describes what data to seed in plain English:
# Seed by schema
--scope "HR schema: employees, departments, payroll"
# Seed by use case
--scope "Customers and orders for checkout flow testing"
# Seed with specificity
--scope "Single user with 3 pending orders"
When --scope is provided, Seedfast automatically approves the seeding plan without prompting β enabling fully automated pipelines.
name: E2E Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
services:
postgres:
image: postgres:15
env:
POSTGRES_PASSWORD: testpass
ports:
- 5432:5432
steps:
- uses: actions/checkout@v4
- run: npm ci
- run: npm run db:migrate
- name: Seed test data
run: npx seedfast seed --scope "Users and orders for E2E tests" --output json
env:
SEEDFAST_API_KEY: ${{ secrets.SEEDFAST_API_KEY }}
SEEDFAST_DSN: postgres://postgres:testpass@localhost:5432/postgres
- run: npm run test:e2e
test:
stage: test
services:
- postgres:15
variables:
POSTGRES_PASSWORD: testpass
SEEDFAST_DSN: postgres://postgres:testpass@postgres:5432/postgres
script:
- npm ci
- npm run db:migrate
- npx seedfast seed --scope "Test dataset" --output plain
- npm run test
The --output flag controls output format:
| Mode | Use case |
|---|---|
interactive | Colors and spinners (default, for local dev) |
plain | Timestamped logs (for CI log output) |
json | Machine-readable (for script validation) |
Validate results with JSON output:
RESULT=$(npx seedfast seed --scope "..." --output json)
if [ "$(echo $RESULT | jq -r '.success')" != "true" ]; then
echo "Seeding failed!"
exit 1
fi
echo "Seeded $(echo $RESULT | jq -r '.rows') rows"
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Generic error |
| 2 | Authentication failed (check API key) |
| 3 | Database connection failed (check SEEDFAST_DSN) |
| 4 | Quota exceeded |
| 5 | Operation cancelled by user |
- Never commit API keys β use CI/CD secret management
- Separate keys per environment β enable independent rotation
- Rotate regularly β generate new key, update secrets, verify, revoke old key
- Limit scope β expose the API key only to the seeding step:
# Key only in the seeding step, not globally
- name: Seed database
run: npx seedfast seed --scope "..."
env:
SEEDFAST_API_KEY: ${{ secrets.SEEDFAST_API_KEY }}
"Authentication failed" in CI but works locally: Verify the secret name matches exactly. Check for leading/trailing whitespace. Ensure the API key hasn't been revoked.
"Connection refused" to database: Wait for database health check to pass. Use the correct hostname (localhost for GitHub Actions, postgres for GitLab CI). Check that the CI runner can reach the database port.
Seeding takes too long in pipeline: Narrow the scope to only the tables your tests need. A focused scope like "users and orders for checkout tests" is faster than "all tables."
CI/CD database seeding with Seedfast takes minutes to set up. Start with one test job, refine your scope, then expand to your full test suite. Try Seedfast β sign up and start seeding in minutes.