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

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

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 into go code

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages