https://github.com/sawirricardo/dbrs
small minimal database migration tool
https://github.com/sawirricardo/dbrs
database db mariadb migration mysql postgres postgresql sqlite tool
Last synced: about 2 months ago
JSON representation
small minimal database migration tool
- Host: GitHub
- URL: https://github.com/sawirricardo/dbrs
- Owner: sawirricardo
- Created: 2026-03-24T04:40:07.000Z (3 months ago)
- Default Branch: main
- Last Pushed: 2026-03-24T12:45:39.000Z (3 months ago)
- Last Synced: 2026-03-25T05:44:48.685Z (3 months ago)
- Topics: database, db, mariadb, migration, mysql, postgres, postgresql, sqlite, tool
- Language: Rust
- Homepage:
- Size: 56.6 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# dbrs
`dbrs` is a small SQL migration tool.
It creates timestamped migration files, applies pending migrations, tracks applied versions in a database table, supports rolling migrations back in reverse order, and includes destructive reset commands for development workflows.
## Features
- Timestamped SQL migration files
- Default migration path at `./db/migrations`
- `migrate` to apply pending migrations
- `status` to show applied and pending migrations
- `show` to inspect database metadata and table sizes
- `table` to inspect one table's columns and indexes
- `rollback` to revert one or more applied migrations
- `reset` to revert all tracked migrations
- `wipe` to reset the current database without dropping the database itself
- `fresh` to wipe and then re-run all migrations
- Streamed progress output for `migrate`, `rollback`, `reset`, `wipe`, and `fresh`
- Global `--quiet` / `-q` flag for summary-only output
- Global `--json` flag for NDJSON event output in CI/agents
- `.env` support, including custom env file paths
- Configurable migration directory and migration table name
- Opt-in table scaffolding for `create_*` migrations
## Installation
Stable release:
```bash
curl -fsSL https://raw.githubusercontent.com/sawirricardo/dbrs/main/install.sh | bash
```
Edge release from `main`:
```bash
DBRS_RELEASE_TAG=edge curl -fsSL https://raw.githubusercontent.com/sawirricardo/dbrs/main/install.sh | bash
```
Custom install directory:
```bash
DBRS_INSTALL_DIR=/usr/local/bin curl -fsSL https://raw.githubusercontent.com/sawirricardo/dbrs/main/install.sh | bash
```
Uninstall:
```bash
curl -fsSL https://raw.githubusercontent.com/sawirricardo/dbrs/main/uninstall.sh | bash
```
## Quick Start
Create a `.env`:
```env
DATABASE_URL=postgres://localhost/my_app
DBRS_MIGRATIONS_DIR=./db/migrations
DBRS_MIGRATION_TABLE=dbrs_migrations
```
Create a migration:
```bash
dbrs new create_users
```
Apply migrations:
```bash
dbrs migrate
```
Check migration status:
```bash
dbrs status
```
Inspect the database:
```bash
dbrs show
```
Inspect a table:
```bash
dbrs table users
```
Roll back the latest migration:
```bash
dbrs rollback --yes
```
Reset all tracked migrations:
```bash
dbrs reset --yes
```
Reset the database and re-run all migrations:
```bash
dbrs fresh --yes
```
## Migration Files
By default, `dbrs new my_migration` creates:
```text
./db/migrations/YYYY_MM_DD_HHMMSS-my-migration.sql
```
Default file template:
```sql
-- dbrs:up
-- write your forward migration here
-- dbrs:down
-- write the rollback for this migration here
```
Rules:
- `-- dbrs:up` is required
- `-- dbrs:down` is optional
- `rollback` and `reset` fail if they hit a migration with no `down` section
- migrations are applied in filename order
Example:
```sql
-- dbrs:up
CREATE TABLE users (
id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
email TEXT NOT NULL UNIQUE
);
-- dbrs:down
DROP TABLE users;
```
## Commands
Global options:
- `--env-file ` or `DBRS_ENV_FILE`
- `--quiet` or `-q` to suppress streamed progress output and show only summaries/errors
- `--json` for newline-delimited JSON event output on stdout for CI/agents
- `--wait` to poll until the database accepts connections before running a DB-backed command
- `--wait-timeout ` and `--wait-interval ` to control readiness polling
- `--quiet` and `--json` are mutually exclusive
Progress output:
- `migrate`, `rollback`, `reset`, `wipe`, and `fresh` print live progress by default
- use `--quiet` for summary-only output
- use `--json` for machine-readable NDJSON events
- use `--wait` when your database may still be starting up
Create a migration:
```bash
dbrs new
```
Options:
- `--dir ` or `DBRS_MIGRATIONS_DIR`
- `--env-file ` or `DBRS_ENV_FILE`
- `--table`
- `--backend postgres|mysql|sqlite`
Apply pending migrations:
```bash
dbrs migrate --database-url
```
Wait for the database first if needed:
```bash
dbrs --wait --wait-timeout 60 migrate --database-url
```
Options:
- `--dir ` or `DBRS_MIGRATIONS_DIR`
- `--env-file ` or `DBRS_ENV_FILE`
- `--database-url ` or `DATABASE_URL`
- `--quiet` or `-q`
- `--json`
Example output:
```text
Running 2 pending migration(s)...
[1/2] Running 2026_03_24_120000 (create-users)...
[1/2] Done 2026_03_24_120000 (create-users) in 0.03s
[2/2] Running 2026_03_24_120100 (add-email-index)...
[2/2] Done 2026_03_24_120100 (add-email-index) in 0.01s
Applied 2 migration(s).
Total migrate time: 0.05s
```
Example JSON output:
```text
{"event":"start","command":"migrate","pending":2}
{"event":"migration_started","command":"migrate","index":1,"total":2,"version":"2026_03_24_120000","name":"create-users"}
{"event":"migration_finished","command":"migrate","index":1,"total":2,"version":"2026_03_24_120000","name":"create-users","duration_seconds":0.030000}
{"event":"summary","command":"migrate","applied":2,"duration_seconds":0.050000}
```
Show status:
```bash
dbrs status --database-url
```
Options:
- `--json`
Output states:
- `APPLIED`
- `PENDING`
- `APPLIED_MODIFIED`
- `MISSING_FILE`
Example JSON output:
```text
{"event":"migration","command":"status","state":"APPLIED","version":"2026_03_24_120000","name":"create-users"}
{"event":"summary","command":"status","count":1}
```
Show database info:
```bash
dbrs show --database-url
```
Options:
- `--database-url ` or `DATABASE_URL`
- `--limit ` for the number of tables to print, default `20`
- `--json`
Example JSON output:
```text
{"event":"database_info","command":"show","backend":"postgres","database":"my_app","current_schema":"public","database_size_bytes":123456,"open_connections":2,"schemas":["public"]}
{"event":"table_size","command":"show","name":"public.users","size_bytes":8192}
{"event":"summary","command":"show","count":1}
```
Inspect one table:
```bash
dbrs table users --database-url
```
Options:
- `--json`
Example JSON output:
```text
{"event":"table_info","command":"table","backend":"postgres","database":"my_app","table":"public.users","estimated_rows":42,"size_bytes":8192}
{"event":"column","command":"table","table":"public.users","name":"id","data_type":"bigint","nullable":false,"default":null}
{"event":"index","command":"table","table":"public.users","name":"users_pkey","unique":true,"columns":["id"]}
{"event":"summary","command":"table","columns":1,"indexes":1}
```
The table name can be either:
- `table`
- `schema.table`
Roll back one or more migrations:
```bash
dbrs rollback --database-url --steps 3 --yes
```
Options:
- `--quiet` or `-q`
- `--json`
Roll back until a specific migration version remains applied:
```bash
dbrs rollback --database-url --to 2026_03_24_12_30_00.123456 --yes
```
Reset all tracked migrations:
```bash
dbrs reset --database-url --yes
```
Options:
- `--quiet` or `-q`
- `--json`
Wipe the current database contents:
```bash
dbrs wipe --database-url --yes
```
Options:
- `--quiet` or `-q`
- `--json`
Fresh database from migrations:
```bash
dbrs fresh --database-url --yes
```
Options:
- `--quiet` or `-q`
- `--json`
## Environment
Supported environment variables:
- `DATABASE_URL`
- `DBRS_ENV_FILE`
- `DBRS_MIGRATIONS_DIR`
- `DBRS_MIGRATION_TABLE`
Env loading order:
1. `--env-file`
2. `DBRS_ENV_FILE`
3. default `.env`
Migration directory behavior:
- default: `./db/migrations`
- override with `--dir`
- or set `DBRS_MIGRATIONS_DIR`
Migration table behavior:
- default: `dbrs_migrations`
- override with `DBRS_MIGRATION_TABLE=migrations`
- allowed names are simple identifiers only: letters, numbers, and underscores
## Table Scaffolding
`dbrs new` supports opt-in table scaffolding:
```bash
dbrs new create_users --table
```
If the migration name looks like a table creation, `dbrs new create_users` prints a hint suggesting `--table`.
Examples:
```bash
dbrs new create_users --table
dbrs new create_users_table --table --backend postgres
dbrs new create_orders --table --backend mysql
```
Scaffolded tables include:
- `id`
- `created_at`
- `updated_at`
Backend behavior:
- Postgres uses `GENERATED BY DEFAULT AS IDENTITY`
- MySQL uses `AUTO_INCREMENT`
- SQLite uses `INTEGER PRIMARY KEY AUTOINCREMENT`
## Supported Databases
- PostgreSQL
- MySQL / MariaDB
- SQLite
## Safety
These commands require explicit confirmation with `--yes`:
- `rollback`
- `reset`
- `wipe`
- `fresh`
`migrate` does not require confirmation.
## Local Development
Build:
```bash
cargo build
```
Run tests:
```bash
cargo test
```
Run repeatable Postgres/MySQL smoke tests:
```bash
scripts/smoke-test.sh \
--postgres-url postgres://postgres@localhost:5432/testing \
--mysql-url mysql://root:root@localhost:3306/testing
```
If your databases may still be starting up, wait for readiness first:
```bash
scripts/smoke-test.sh \
--postgres-url postgres://postgres@localhost:5432/testing \
--mysql-url mysql://root:root@localhost:3306/testing \
--wait
```
Destructive coverage for disposable databases only:
```bash
scripts/smoke-test.sh \
--postgres-url postgres://postgres@localhost:5432/dbrs_smoke \
--mysql-url mysql://root:root@localhost:3306/dbrs_smoke \
--allow-destructive
```
The smoke script verifies `migrate`, `status`, `show`, `table`, JSON output, `rollback`, and `reset`.
With `--allow-destructive`, it also verifies `fresh` and `wipe`.
The script-level `--wait` is useful when orchestrating fresh databases; `dbrs` itself also supports `--wait`, `--wait-timeout `, and `--wait-interval `.
Run locally:
```bash
cargo run -- --help
```