Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ Old migrations work exactly as they did the first time they were created.

---

## Simple example

<img src="docs/src/assets/spawn_in_action.png" width="600" alt="Spawn in action">

## A Quick Look: Migrations

**1. Setup**
Expand Down Expand Up @@ -247,6 +251,20 @@ command = {

> Docs: [Manage Databases](https://docs.spawn.dev/guides/manage-databases/) | [Configuration](https://docs.spawn.dev/reference/config/)

## Comparison

| Feature | **Spawn** | **Sqitch** | **Flyway** | **dbmate** |
| :------------------- | :----------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------- | :---------------------------------------------------------------------------- | :------------------------------------------------------------- |
| **Core Philosophy** | **Compiled.** Database logic is a codebase. Migrations are build artifacts. | **DAG.** A dependency graph of changes. No linear version numbers. | **Linear.** Run scripts V1 → V2. "Repeatable" scripts run at the end. | **Simple.** Just run these SQL files in order. |
| **Views/Functions** | **Pinned Components.** Edit in place. Snapshots locked per-migration (CAS). | **Versioned Copies.** The rework command creates a new physical file old migrations. | **Repeatable.** Re-runs `R__` scripts every migration. Doesn't track history. | **Manual.** Copy-paste old logic into new migrations manually. |
| **Templating** | **Native (Minijinja).** Macros, loops, and variables inside SQL. | **None.** Raw SQL only. | **Basic.** `${placeholder}` substitution only. | **None.** Raw SQL only. |
| **Testing** | **Built-in.** `spawn test` with ephemeral DBs & diff assertions. | **Verify Scripts.** Boolean (Pass/Fail) scripts run after deploy. | **None.** Relies on external CI tools. | **None.** |
| **Dependencies** | **Single Binary** (Rust) + `psql` CLI. | **Perl.** | **JRE / Binary.** | **Single Binary** (Go). Very easy install. |
| **Rollbacks** | 🚧 _Planned._ Currently manual, but not needed as much with pinning. | **First Class.** Every change _must_ have a revert script. | **Paid.** `Undo` functionality often gated behind Pro/Enterprise. | **Supported.** `down.sql` files are standard. |
| **DB Support** | **PostgreSQL** (Focus on depth). | **Massive.** Postgres, MySQL, Oracle, SQLite, Vertica, etc. | **Massive.** Every DB known to man. | **Broad.** Postgres, MySQL, SQLite, ClickHouse. |
| **Execution Engine** | **Native CLI Wrapper.** Full parity with `psql` (supports `\copy`, `\gset`, `\set`). | **Native Drivers.** | **JDBC.** (Java Database Connectivity). | **Native Drivers.** (Go drivers). |
| **License** | **AGPL-3.0** | **MIT** | **Apache 2.0** (Community) / Proprietary (Teams). | **MIT** |

## Roadmap

Spawn is currently in **Public Beta**. It is fully functional and has test suites to help prevent regressions, but should be considered experimental software. We recommend testing thoroughly before adopting it for critical production workloads.
Expand Down
Binary file added docs/src/assets/spawn_in_action.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
6 changes: 3 additions & 3 deletions docs/src/content/docs/cli/migration-apply.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
{ flag: "--no-pin", description: "Allow unpinned migrations (use current components)" },
...variablesOption,
{ flag: "--yes", description: "Skip confirmation prompt" },
{ flag: "--retry", description: "Retry a previously failed migration" },
{ flag: "--retry", description: "Retry a previous migration" },
...environmentOption,
...databaseOption,
...globalOptions
Expand Down Expand Up @@ -54,7 +54,7 @@ By default, `apply` requires migrations to have a `lock.toml`. This ensures the

## Retry logic

If a migration previously failed, `apply` will refuse to run it again unless you pass `--retry`. This prevents accidental re-execution of partially applied migrations.
If a migration previously failed, `apply` will refuse to run it again unless you pass `--retry`. This prevents accidental re-execution of partially applied migrations. Retrying a successful migration will run the same migration again.

## Examples

Expand All @@ -70,7 +70,7 @@ Apply a specific migration without confirmation:
spawn migration apply 20260131120000-add-users-table --yes
```

Retry a failed migration:
Retry a previously successful or failed migration:

```bash
spawn migration apply 20260131120000-add-users-table --retry
Expand Down
24 changes: 12 additions & 12 deletions src/engine/postgres_psql.rs
Original file line number Diff line number Diff line change
Expand Up @@ -757,19 +757,19 @@ impl PSQL {
};

if let Some(info) = existing_status {
let name = migration_name.to_string();
let ns = namespace.raw_value().to_string();
if !retry {
let name = migration_name.to_string();
let ns = namespace.raw_value().to_string();

match info.last_status {
MigrationHistoryStatus::Success => {
return Err(MigrationError::AlreadyApplied {
name,
namespace: ns,
info,
});
}
MigrationHistoryStatus::Attempted | MigrationHistoryStatus::Failure => {
if !retry {
match info.last_status {
MigrationHistoryStatus::Success => {
return Err(MigrationError::AlreadyApplied {
name,
namespace: ns,
info,
});
}
MigrationHistoryStatus::Attempted | MigrationHistoryStatus::Failure => {
return Err(MigrationError::PreviousAttemptFailed {
name,
namespace: ns,
Expand Down