Skip to content

Commit 37815ff

Browse files
Update Documentation (#25)
This adds an update to the `README.md` and `doc/` to help folks understand how Kat works better.
1 parent c5a4aa9 commit 37815ff

File tree

12 files changed

+901
-85
lines changed

12 files changed

+901
-85
lines changed

.mise.toml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
[env]
2+
VERSION = "dev"
3+
4+
[tools]
5+
go = "1.23.0"
6+
7+
[tasks.install]
8+
description = "Install Kat CLI tool"
9+
run = "go install ./..."
10+
11+
[tasks.run]
12+
description = "Run Kat CLI with custom arguments"
13+
run = "go run ./cmd/kat $ARGS"
14+
env = { ARGS = "${ARGS:-}" }
15+
16+
[tasks."start-doc"]
17+
description = "Start Jekyll documentation server"
18+
run = "bundle exec jekyll serve"
19+
dir = "doc"
20+
21+
[tasks.build]
22+
description = "Build Kat binary with version information"
23+
run = "go build -ldflags \"-X github.com/BolajiOlajide/kat/internal/version.version=$VERSION\" ./cmd/kat"
24+
25+
[tasks.test]
26+
description = "Run all tests"
27+
run = "go test ./..."
28+
29+
[tasks."test-verbose"]
30+
description = "Run all tests with verbose output"
31+
run = "go test -v ./..."
32+
33+
[tasks.check]
34+
description = "Run type checking and linting"
35+
run = "go vet ./..."
36+
37+
[tasks.clean]
38+
description = "Clean build artifacts"
39+
run = "rm -f kat"
40+
41+
[tasks.fmt]
42+
description = "Format Go code"
43+
run = "go fmt ./..."

Gemfile.lock

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,13 +216,15 @@ GEM
216216
rb-fsevent (~> 0.10, >= 0.10.3)
217217
rb-inotify (~> 0.9, >= 0.9.10)
218218
mercenary (0.3.6)
219+
mini_portile2 (2.8.9)
219220
minima (2.5.1)
220221
jekyll (>= 3.5, < 5.0)
221222
jekyll-feed (~> 0.9)
222223
jekyll-seo-tag (~> 2.1)
223224
minitest (5.20.0)
224225
mutex_m (0.2.0)
225-
nokogiri (1.15.5-x86_64-darwin)
226+
nokogiri (1.15.5)
227+
mini_portile2 (~> 2.8.2)
226228
racc (~> 1.4)
227229
octokit (4.25.1)
228230
faraday (>= 1, < 3)
@@ -262,6 +264,7 @@ GEM
262264
webrick (1.8.1)
263265

264266
PLATFORMS
267+
arm64-darwin-24
265268
x86_64-darwin-23
266269

267270
DEPENDENCIES

README.md

Lines changed: 173 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,28 @@
22

33
[![License](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://github.com/BolajiOlajide/kat/blob/main/LICENSE)
44
[![Go Report Card](https://goreportcard.com/badge/github.com/BolajiOlajide/kat)](https://goreportcard.com/report/github.com/BolajiOlajide/kat)
5+
[![Go Reference](https://pkg.go.dev/badge/github.com/BolajiOlajide/kat.svg)](https://pkg.go.dev/github.com/BolajiOlajide/kat)
56
[![CI](https://github.com/BolajiOlajide/kat/actions/workflows/ci.yml/badge.svg)](https://github.com/BolajiOlajide/kat/actions/workflows/ci.yml)
67
[![Release](https://github.com/BolajiOlajide/kat/actions/workflows/release.yml/badge.svg)](https://github.com/BolajiOlajide/kat/actions/workflows/release.yml)
8+
[![Docs](https://img.shields.io/badge/docs-kat.bolaji.de-blue)](https://kat.bolaji.de/)
79

8-
Kat is a lightweight, powerful CLI tool for PostgreSQL database migrations. It allows you to manage your database schema using SQL files with a simple, intuitive workflow.
10+
<details>
11+
<summary>📑 Table of Contents</summary>
12+
13+
- [Why Graph-Based Migrations?](#why-graph-based-migrations)
14+
- [Installation](#installation)
15+
- [Quick Start](#quick-start)
16+
- [Comparison with Other Tools](#comparison-with-other-tools)
17+
- [Architecture Overview](#architecture-overview)
18+
- [Go Library Usage](#go-library-usage)
19+
- [Best Practices](#best-practices)
20+
- [Limitations](#limitations)
21+
- [Quick Reference](#quick-reference)
22+
- [Documentation](#documentation)
23+
24+
</details>
25+
26+
Kat is (probably?) the first open-source PostgreSQL migration tool that treats your schema as a Directed Acyclic Graph, not a linear log. It enables topological sort migrations with explicit dependencies, parallel development workflows, and deterministic ordering.
927

1028
![Kat Banner](doc/assets/images/layout/logo.png)
1129

@@ -23,6 +41,29 @@ Kat is a lightweight, powerful CLI tool for PostgreSQL database migrations. It a
2341
- **Custom Logger Support**: Configure custom logging for migrations
2442
- **Go Library**: Use Kat programmatically in your Go applications
2543

44+
## Why Graph-Based Migrations?
45+
46+
Traditional migration tools force you into a linear sequence where every developer must coordinate their schema changes. Kat's graph-based approach solves this by allowing migrations to declare explicit parent dependencies, creating a Directed Acyclic Graph (DAG) that determines execution order.
47+
48+
**Benefits of the DAG approach:**
49+
- **Parallel Development**: Multiple developers can create feature migrations simultaneously without conflicts
50+
- **Deterministic Ordering**: Kat computes the optimal execution order based on dependencies, not timestamps
51+
- **Safe Branching**: Feature branches can include their own migrations that merge cleanly
52+
- **Complex Dependencies**: A migration can depend on multiple parents, enabling sophisticated schema evolution
53+
54+
```text
55+
Linear (traditional): Graph-based (Kat):
56+
57+
001_users 001_users ──┬─→ 003_posts
58+
002_posts │
59+
003_add_email 002_add_email ──┘
60+
61+
Order: 1→2→3 Order: 1→2→3 OR 1→3→2
62+
(rigid) (flexible, dependency-aware)
63+
```
64+
65+
This means you can create migrations for different features in parallel, and Kat will figure out the correct order when you run `kat up`.
66+
2667
## Installation
2768

2869
### Quick Install (macOS & Linux)
@@ -50,29 +91,65 @@ For more installation options, see the [installation documentation](https://kat.
5091

5192
## Quick Start
5293

94+
Here's a realistic example showing how Kat's graph-based system handles parallel development:
95+
5396
```bash
5497
# Initialize a new Kat project
5598
kat init
5699

57-
# Create a new migration
100+
# Create foundation migration
58101
kat add create_users_table
59102

60-
# Create another migration with a parent dependency
103+
# Developer A: Add email feature (Kat determines create_users_table as parent)
104+
kat add add_email_column
105+
106+
# Developer B: Add posts feature (creates parallel branch from users table)
61107
kat add create_posts_table
62108

63-
# Edit the generated migration files in migrations/TIMESTAMP_create_users_table/
109+
# Developer C: Add full-text search (Kat resolves dependencies automatically)
110+
kat add add_full_text_search
64111

65-
# Apply all pending migrations (ordered based on dependencies)
66-
kat up
112+
# Visualize the dependency graph
113+
kat export --file graph.dot
114+
dot -Tpng graph.dot -o migrations.png # Requires Graphviz
67115

68-
# Roll back the most recent migration
69-
kat down
116+
# Apply all migrations - Kat determines the correct order automatically
117+
kat up
70118

71119
# Test database connection
72120
kat ping
73121

74-
# Visualize your migration graph (requires Graphviz)
75-
kat export --file migrations.dot
122+
# Roll back specific number of migrations
123+
kat down --count 2
124+
```
125+
126+
### Example Migration Structure
127+
128+
Each migration is a directory containing SQL files and metadata:
129+
130+
```
131+
migrations/
132+
├── 1679012345_create_users_table/
133+
│ ├── up.sql
134+
│ ├── down.sql
135+
│ └── metadata.yaml
136+
├── 1679012398_add_email_column/
137+
│ ├── up.sql
138+
│ ├── down.sql
139+
│ └── metadata.yaml # parents: [1679012345]
140+
└── 1679012401_create_posts_table/
141+
├── up.sql
142+
├── down.sql
143+
└── metadata.yaml # parents: [1679012345]
144+
```
145+
146+
**metadata.yaml example:**
147+
```yaml
148+
id: 1679012398
149+
name: add_email_column
150+
description: Add email column to users table
151+
parents:
152+
- 1679012345 # create_users_table
76153
```
77154
78155
## Usage
@@ -117,6 +194,35 @@ database:
117194

118195
For detailed usage instructions, see the [documentation](https://kat.bolaji.de/).
119196

197+
## Comparison with Other Tools
198+
199+
| Feature | Kat | Flyway | Goose | Atlas |
200+
|---------|-----|---------|-------|-------|
201+
| Graph-based dependencies | ✅ | ❌ | ❌ | ⚠️ |
202+
| Parallel development friendly | ✅ | ❌ | ❌ | ⚠️ |
203+
| Raw SQL migrations | ✅ | ✅ | ✅ | ⚠️ |
204+
| Go library + CLI | ✅ | ❌ | ✅ | ✅ |
205+
| Transaction per migration | ✅ | ✅ | ✅ | ✅ |
206+
| Rollback support | ✅ | ✅ | ✅ | ✅ |
207+
| Migration visualization | ✅ | ❌ | ❌ | ✅ |
208+
209+
## Architecture Overview
210+
211+
```
212+
┌─────────────┐ ┌──────────────┐ ┌─────────────┐ ┌──────────────┐
213+
│ CLI Command │ -> │ Migration │ -> │ Graph │ -> │ Runner │
214+
│ (cmd/) │ │ (discovery) │ │ (DAG ops) │ │ (execution) │
215+
└─────────────┘ └──────────────┘ └─────────────┘ └──────────────┘
216+
│ │ │
217+
v v v
218+
┌──────────────┐ ┌─────────────┐ ┌──────────────┐
219+
│ File System │ │ Topological │ │ Database │
220+
│ Scanner │ │ Sort │ │ Operations │
221+
└──────────────┘ └─────────────┘ └──────────────┘
222+
```
223+
224+
**Flow**: Discovery → Graph Construction → Topological Ordering → Transactional Execution
225+
120226
## Go Library Usage
121227
122228
Kat can also be used as a Go library in your applications:
@@ -128,6 +234,7 @@ import (
128234
"context"
129235
"embed"
130236
"log"
237+
"time"
131238
132239
"github.com/BolajiOlajide/kat"
133240
)
@@ -136,21 +243,33 @@ import (
136243
var migrationsFS embed.FS
137244
138245
func main() {
139-
// Basic usage
246+
// Basic usage with embedded migrations
140247
m, err := kat.New("postgres://user:pass@localhost:5432/db", migrationsFS, "migrations")
141248
if err != nil {
142249
log.Fatal(err)
143250
}
144251
145-
// Apply all pending migrations
146-
err = m.Up(context.Background(), 0)
252+
// Apply all pending migrations with cancellation
253+
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
254+
defer cancel()
255+
256+
err = m.Up(ctx, 0) // 0 = apply all pending
257+
if err != nil {
258+
log.Fatal(err)
259+
}
260+
261+
// Roll back the most recent migration
262+
err = m.Down(context.Background(), 1)
147263
if err != nil {
148264
log.Fatal(err)
149265
}
150266
151-
// With custom logger
152-
m, err = kat.New("postgres://user:pass@localhost:5432/db", migrationsFS, "migrations",
267+
// Advanced usage with custom logger and existing DB connection
268+
connStr := "postgres://user:pass@localhost:5432/db"
269+
db, _ := sql.Open("postgres", connStr)
270+
m, err = kat.New("", migrationsFS, "schema_migrations",
153271
kat.WithLogger(customLogger),
272+
kat.WithSqlDB(db), // Reuse existing connection
154273
)
155274
if err != nil {
156275
log.Fatal(err)
@@ -160,21 +279,52 @@ func main() {
160279

161280
For more details on custom logging, see the [logger documentation](https://kat.bolaji.de/logger/).
162281

163-
## Migration Structure
282+
## Best Practices
164283

165-
Migrations are organized in a directory structure like this:
284+
### Writing Idempotent Migrations
285+
```sql
286+
-- up.sql
287+
CREATE TABLE IF NOT EXISTS users (
288+
id SERIAL PRIMARY KEY,
289+
email VARCHAR(255) UNIQUE
290+
);
166291

292+
-- down.sql
293+
DROP TABLE IF EXISTS users;
167294
```
168-
migrations/
169-
└─ 1679012345_create_users_table/
170-
├─ up.sql # SQL to apply the migration
171-
├─ down.sql # SQL to reverse the migration
172-
└─ metadata.yaml # Migration metadata including dependencies
295+
296+
### Branch Workflow
297+
1. Create feature branch: `git checkout -b feature/user-profiles`
298+
2. Add dependent migrations: `kat add add_profile_table` (Kat determines dependencies)
299+
3. Test locally: `kat up --dry-run`
300+
4. Merge: Kat automatically handles dependency ordering
301+
302+
### CI/CD Integration
303+
```yaml
304+
# .github/workflows/migrations.yml
305+
- name: Validate migrations
306+
run: |
307+
kat ping
308+
kat up --dry-run
173309
```
174310
311+
**Compatibility**: Tested with Go 1.20+ (tested on 1.23), PostgreSQL 12-16. Supported OS: Linux, macOS, Windows (amd64/arm64)
312+
313+
## Quick Reference
314+
315+
| Command | Purpose | Common Flags |
316+
|---------|---------|--------------|
317+
| `kat add NAME` | Create migration (Kat determines dependencies) | `--config, -c` |
318+
| `kat up --count 3` | Apply next 3 migrations | `--dry-run, --verbose` |
319+
| `kat down --count 2` | Roll back 2 migrations | `--force` |
320+
| `kat export --file graph.dot` | Export dependency graph | `--format json` |
321+
| `kat ping` | Test database connectivity | |
322+
323+
➡️ *Need help?* Visit [GitHub Discussions](https://github.com/BolajiOlajide/kat/discussions) for questions and [GitHub Issues](https://github.com/BolajiOlajide/kat/issues) for bug reports.
324+
175325
## Documentation
176326

177-
Visit the [Kat documentation site](https://kat.bolaji.de/) for detailed guides on:
327+
Visit the [Kat documentation site](https://kat.bolaji.de/) for detailed guides:
178328

179329
- [Installation](https://kat.bolaji.de/installation/)
180330
- [Initialization](https://kat.bolaji.de/init/)

0 commit comments

Comments
 (0)