Skip to content

ocomsoft/makemigrations

Repository files navigation

makemigrations

A Go-first database migration tool with a Django-style workflow. Define your schema in YAML, generate type-safe Go migration files, and run them with a compiled binary that embeds every migration your project has ever had.

✨ Why Go Migrations?

  • 🔒 Type-safe: Migrations are Go code — caught by the compiler, not at runtime
  • 📦 Self-contained binary: One compiled binary knows all migrations, their dependencies, and their SQL
  • 🗄️ Database-agnostic schema: Write YAML once, deploy to PostgreSQL, MySQL, SQLite, or SQL Server
  • 🔀 DAG-based ordering: Migrations form a dependency graph so parallel branches merge cleanly
  • 🔄 Auto change detection: Diff YAML schemas, generate only what changed
  • ⚠️ Safe destructive ops: Field removals, table drops, and renames require explicit review
  • 🔧 Zero runtime dependency: The compiled binary has no runtime dependency on makemigrations itself

🚀 Quick Start

1. Install

go install github.com/ocomsoft/makemigrations@latest

2. Initialise your project

cd your-project
makemigrations init

This creates:

your-project/
└── migrations/
    ├── main.go     ← compiled binary entry point
    └── go.mod      ← dedicated migrations module

If *.sql Goose files already exist in migrations/, they are automatically converted to Go migrations. See Upgrading from Goose.

3. Define your schema

schema/schema.yaml:

tables:
  - name: users
    fields:
      - name: id
        type: uuid
        primary_key: true
        default: new_uuid
      - name: email
        type: varchar
        length: 255
        nullable: false
      - name: created_at
        type: timestamp
        auto_create: true

  - name: posts
    fields:
      - name: id
        type: uuid
        primary_key: true
        default: new_uuid
      - name: title
        type: varchar
        length: 200
        nullable: false
      - name: user_id
        type: foreign_key
        foreign_key:
          table: users
          on_delete: CASCADE

4. Generate your first migration

makemigrations makemigrations --name "initial"
# Creates: migrations/0001_initial.go

5. Apply to your database

export DATABASE_URL="postgresql://user:pass@localhost/mydb"
makemigrations migrate up

makemigrations migrate compiles the migration binary automatically and runs it with the correct Go workspace settings. No manual go build required.


🔄 Day-to-Day Workflow

# 1. Edit your YAML schema
vim schema/schema.yaml

# 2. Preview what will be generated
makemigrations makemigrations --dry-run

# 3. Generate the migration
makemigrations makemigrations --name "add user preferences"
# Creates: migrations/0004_add_user_preferences.go

# 4. Review the SQL before applying
makemigrations migrate showsql

# 5. Apply
makemigrations migrate up

# 6. Verify
makemigrations migrate status

📋 migrate Subcommands

makemigrations migrate compiles and runs the migration binary. All arguments are forwarded:

makemigrations migrate up                       # apply all pending
makemigrations migrate up --to 0003_add_index   # apply up to a specific migration
makemigrations migrate down                     # roll back one
makemigrations migrate down --steps 3           # roll back multiple
makemigrations migrate status                   # show applied / pending
makemigrations migrate showsql                  # print SQL without running it
makemigrations migrate fake 0001_initial        # mark applied without running SQL
makemigrations migrate dag                      # show migration dependency graph
makemigrations migrate --verbose up             # show build output

🏗️ Project Structure

your-project/
├── schema/
│   └── schema.yaml              ← your YAML schema definition
├── migrations/
│   ├── main.go                  ← binary entry point (generated by init)
│   ├── go.mod                   ← dedicated module (generated by init)
│   ├── 0001_initial.go          ← migration files (generated by makemigrations)
│   ├── 0002_add_posts.go
│   └── 0003_add_index.go
├── go.mod
└── main.go

🗄️ Database Support

Database Status Notes
PostgreSQL ✅ Full UUID, JSONB, arrays, advanced types
MySQL ✅ Supported JSON, AUTO_INCREMENT, InnoDB
SQLite ✅ Supported Simplified types, basic constraints
SQL Server ✅ Supported UNIQUEIDENTIFIER, NVARCHAR, BIT
Amazon Redshift ✅ Provider ready SUPER JSON, IDENTITY sequences
ClickHouse ✅ Provider ready MergeTree engine, Nullable types
TiDB ✅ Provider ready MySQL-compatible, distributed
Vertica ✅ Provider ready Columnar analytics
YDB (Yandex) ✅ Provider ready Optional, native JSON
Turso ✅ Provider ready Edge SQLite
StarRocks ✅ Provider ready MPP analytics, OLAP
Aurora DSQL ✅ Provider ready AWS serverless, PostgreSQL-compatible

PostgreSQL has been tested against real database instances. All other providers have comprehensive unit tests but may need additional validation for production.


⚠️ Destructive Operations

When a field removal, table drop, or rename is detected, makemigrations prompts before generating:

⚠  Destructive operation detected: field_removed on "users" (field: "legacy_col")
  1) Generate  — include SQL in migration
  2) Review    — include with // REVIEW comment
  3) Omit      — skip SQL; schema state still advances (SchemaOnly)
  4) Exit      — cancel migration generation
  5) All       — generate all remaining destructive ops without prompting
Choice [1-5]:

🔀 Branch & Merge

When two developers generate migrations concurrently the DAG develops branches:

0001_initial
├── 0002_add_messaging   (developer A)
└── 0003_add_payments    (developer B)

Resolve with a merge migration:

makemigrations makemigrations --merge
# Creates: migrations/0004_merge_0002_add_messaging_and_0003_add_payments.go

⬆️ Upgrading from Goose SQL migrations

Run makemigrations init in a directory containing Goose *.sql files and they are converted automatically:

# migrations/ has 00001_initial.sql, 00002_add_phone.sql ...
makemigrations init

# Detected 2 Goose SQL migration(s) — running migrate-to-go...
# ✓ Created migrations/0001_initial.go
# ✓ Created migrations/0002_add_phone.go
# ✓ Created migrations/main.go
# ✓ Created migrations/go.mod
# ✓ Created migrations/0003_schema_state.go (schema-state bootstrap)
# ✗ Deleted migrations/00001_initial.sql
# ✗ Deleted migrations/00002_add_phone.sql

If the schema is already applied to your database, fake the historical migrations:

makemigrations migrate fake 0001_initial
makemigrations migrate fake 0002_add_phone
makemigrations migrate status

Or use the dedicated conversion command for more control:

makemigrations migrate-to-go --dir migrations/

⚙️ Configuration

Database connection

The compiled binary reads connection details from migrations/main.go. The generated file uses DATABASE_URL and DB_TYPE:

export DATABASE_URL="postgresql://user:pass@localhost/mydb"
export DB_TYPE=postgresql   # optional, defaults to postgresql

DB_HOST, DB_PORT, DB_USER etc. can be added by editing migrations/main.go — see the Manual Build Guide.

Configuration file

migrations/makemigrations.config.yaml:

database:
  type: postgresql

migration:
  directory: migrations
  include_down_sql: true

output:
  verbose: false

See the Configuration Guide for complete options.


📖 Documentation

Guides

Command Reference

Command Description
init Bootstrap the migrations/ directory
makemigrations Generate .go migration files from YAML schema
migrate Build and run the compiled migration binary
migrate-to-go Convert existing Goose SQL migrations to Go
struct2schema Generate YAML schemas from Go structs
dump_sql Preview generated SQL from schemas
db2schema Reverse-engineer schema from existing database

Legacy SQL Workflow

For projects that predate the Go migration framework, the original YAML→SQL→Goose workflow is still supported:

makemigrations init --sql          # create SQL-based project
makemigrations makemigrations_sql  # generate Goose-compatible SQL files
makemigrations goose up            # apply via Goose

🤝 Contributing

  1. Fork the repository
  2. Create a feature branch: git checkout -b feature/amazing-feature
  3. Add tests for new functionality
  4. Ensure all tests pass: go test ./...
  5. Submit a pull request

📄 License

MIT License — see LICENSE file for details.


Ready to get started? Run makemigrations init in your project directory.

About

Automate creating migrations for https://github.com/pressly/goose

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages