Skip to content

Repository files navigation

I Migrate

Interface-driven migrations for Go.

I Migrate is an interface-driven approach to managing database migrations. It was created out of a need for a migration tool that can be used in a Go project that doesn't conform to database/sql, and can execute migrations embedded in a single binary.

This project aims to fulfill the following needs:

  1. Migrations written in pure SQL, stored in flat files.
  2. CLI runner for up, down, redo, rollback, status, dry-run, etc.
  3. CLI template generator for timestamp-prefixed migrations.
  4. fs.FS support, allowing migration files to be embedded via //go:embed.
  5. Database driver agnostic via a sql Exec interface.
  6. No config files. (But config in code)
  7. All public API methods return errors (no panics).
  8. Dry-run mode to preview SQL without executing it.

Read the docs

Usage

Using the built-in *sql.DB adapter

For projects using database/sql, use the provided SQLDB adapter:

db, err:=sql.Open("sqlite3", "db.sqlite3")
iferr!=nil {
log.Fatal(err)
}
deferdb.Close()
executor:=imigrate.NewSQLDB(db)
migrator:=imigrate.NewIMigrator(executor, os.DirFS("."))
imigrate.CLI(migrator)

With embedded migrations

//go:embed migrationsvarmigrationsFS embed.FSfuncmain() {
db, _:=sql.Open("sqlite3", "app.db")
executor:=imigrate.NewSQLDB(db)
migrator:=imigrate.NewIMigrator(executor, migrationsFS)
// WriteDirname tells Create where to write new files on disk,// since the embed.FS is read-only.migrator.WriteDirname="internal/db/migrations"imigrate.CLI(migrator)
}

Custom executor (non-database/sql drivers)

If your database driver does not conform to database/sql, implement the Executor interface:

typeExecutorinterface {
Exec(querystring, args...interface{}) (sql.Result, error)
GetVersions(querystring, args...interface{}) ([]int64, error)
}

Programmatic usage

All public API methods return errors:

// Run all pending migrationserr:=migrator.Up(-1, 0)
// Run a specific number of migrationserr=migrator.Up(2, 0)
// Run a specific versionerr=migrator.Up(-1, 1610069160)
// Roll backerr=migrator.Down(-1, 0)
// Preview what Up would doerr=migrator.DryRun(-1, 0)

CLI with args

Use CLIWithArgs when you need to control the argument parsing:

args:= []string{"up", "-steps=1"}
err:=imigrate.CLIWithArgs(migrator, args)

CLI(migrator) is a convenience wrapper that passes os.Args[1:].

Configuration

migrator:=imigrate.NewIMigrator(executor, fsys)
// Set a separate directory for writing new migration filesmigrator.WriteDirname="internal/db/migrations"// Silence migration outputmigrator.Logger=imigrate.DiscardLogger// Or provide your own loggermigrator.Logger=log.New(os.Stderr, "[migrate] ", log.LstdFlags)

CLI usage

Example CLI usage for a tool named "migrate":

migrate create create_users_table
migrate up
migrate up -steps=1
migrate up -version=1610069160
migrate down
migrate down -steps=1
migrate redo
migrate redo -steps=2
migrate rollback
migrate rollback -steps=3
migrate status
migrate dry-run
migrate dry-run -steps=2
migrate dry-run -version=1610069160

All commands accept a -silent flag to suppress output.

About

Interface-driven migrations in Go. A simple tool to run database migrations for sql drivers that don't conform to database/sql.

Topics

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages