An open API service indexing awesome lists of open source software.

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

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
```