gomigration

package module
v1.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2025 License: MIT Imports: 18 Imported by: 0

README

🧠 GoMigration

GoMigration is a lightweight and extensible database migration library for Go, designed with simplicity and flexibility in mind. It allows you to register migrations in Go code, manage them efficiently, and execute or roll them back in a safe and structured manner.

📝 Note: This project is a fork of ruangdeveloper/qafoia, moved under a new organization for long-term maintenance and development.

✨ Features

  • Register migrations using Go structs.
  • Run, rollback, reset, or re-run migrations with ease.
  • Debug SQL output during migration execution.
  • Automatically generates migration file templates.
  • Tracks applied migrations using a dedicated database table.
  • Ready-to-use MySQL and Postgres drivers.

📦 Installation

To install GoMigration, use the following command:

go get github.com/openframebox/gomigration

🛠️ Usage

1. Initialize GoMigration

First, configure the library by providing a Config:

cfg := &gomigration.Config{
    Driver:             yourDriver,  // Must implement gomigration.Driver
    MigrationFilesDir:  "migrations",  // Optional: default is "migrations"
    MigrationTableName: "migrations",  // Optional: default is "migrations"
    DebugSql:           true,  // Optional: enables SQL debugging
}

q, err := gomigration.New(cfg)
if err != nil {
    log.Fatal(err)
}
2. Register Migrations
q.Register(
    migration1, // Must implement gomigration.Migration
    // Example
    &migrations.M20250418220011CreateUsersTable{},
)

Migration struct is created automatically when creating migration file.

3. Apply Migrations

To apply the migrations:

err := q.Migrate(context.Background())
if err != nil {
    log.Fatal(err)
}
4. Other Operations
  • Create a new migration file:

    q.Create("add_users_table")
    
  • Run fresh migrations (clean + migrate):

    q.Fresh(context.Background())
    
  • Reset migrations (rollback all and reapply):

    q.Reset(context.Background())
    
  • Rollback last n migrations:

    q.Rollback(context.Background(), 2)
    
  • Clean the database:

    q.Clean(context.Background())
    
  • List all registered migrations and their status:

    list, err := q.List(context.Background())
    
5. Set migration files directory before creating migration file

If you want to set migration files directory before creating migration file, you can use SetMigrationFilesDir method. This is useful when you want to dynamically set the migration files directory, e.g. passing it as a command-line argument.

q.SetMigrationFilesDir("migrations")
q.Create("add_users_table")

// or using chain
q.SetMigrationFilesDir("migrations").Create("add_users_table")

📁 Migration Interface

Each migration must implement the following interface:

type Migration interface {
    Name() string
    UpScript() string
    DownScript() string
}

🔌 Driver Interface

You can use any database driver that implements the Driver interface. We currently provide ready-to-use MySQL and Postgres drivers.

MySQL Driver

To use the MySQL driver:

d, err := gomigration.NewMySqlDriver(
    "localhost", // Host
    "3306",      // Port
    "root",      // Username
    "",          // Password
    "gomigration",    // Database Name
    "utf8mb4",   // Charset
)
Postgres Driver

To use the Postgres driver:

d, err := gomigration.NewPostgresDriver(
    "localhost", // Host
    "5432",      // Port
    "root",      // Username
    "",          // Password
    "gomigration",    // Database Name
    "public",    // Schema
)

📦 Generated Migration File Example

When you run q.Create("create_users_table"), a file like this will be created:

package migrations

type M20250418220011CreateUsersTable struct{}

func (m *M20250418220011CreateUsersTable) Name() string {
  // Don't change this name
	return "20250418220011_create_users_table"
}

func (m *M20250418220011CreateUsersTable) UpScript() string {
  // Write your migration SQL here
	return ""
}

func (m *M20250418220011CreateUsersTable) DownScript() string {
  // Write your rollback SQL here
	return ""
}

🧑‍💻 CLI Helper

GoMigration provides an optional CLI helper that simplifies running migrations and other tasks. You can use the CLI as follows:

1. Initialize the CLI

You can initialize the CLI with the CliConfig:

cli, err := gomigration.NewCli(gomigration.CliConfig{
    GoMigration: q,  // The GoMigration instance you've initialized earlier
})

if err != nil {
    log.Fatal(err)
}

err = cli.Execute(context.TODO())

if err != nil {
    log.Fatal(err)
}
2. Run CLI Commands

After setting up the CLI, you can run the following commands directly from the terminal:

  • Clean database (delete all tables):

    go run main.go clean
    
  • Create a new migration:

    go run main.go create
    
  • List all migrations:

    go run main.go list
    
  • Run all pending migrations:

    go run main.go migrate
    
  • Rollback all migrations and re-run all migrations:

    go run main.go reset
    
  • Rollback the last migration:

    go run main.go rollback
    

These commands are built into the CLI, making it easy to perform common migration tasks without having to write custom code each time.

Full Example
package main

import (
	"context"
	"log"

	"github.com/openframebox/gomigration"
	"your_app/migrations"
)

func main() {
	d, err := gomigration.NewMySqlDriver(
		"localhost",
		"3306",
		"root",
		"",
		"gomigration",
		"utf8mb4",
	)

	if err != nil {
		log.Fatal(err)
	}
	q, err := gomigration.New(&gomigration.Config{
		Driver:             d,
		MigrationFilesDir:  "migrations",
		MigrationTableName: "migrations",
		DebugSql:           false,
	})

	if err != nil {
		log.Fatal(err)
	}

	err = q.Register(
		&migrations.M20250418220011CreateUsersTable{},
		&migrations.M20250418233018CreateRolesTable{},
	)

	if err != nil {
		log.Fatal(err)
	}

	cli, err := gomigration.NewCli(gomigration.CliConfg{
		GoMigration: q,
	})

	if err != nil {
		log.Fatal(err)
	}

	err = cli.Execute(context.TODO())

	if err != nil {
		log.Fatal(err)
	}
}

📄 License

MIT License


Documentation

Overview

Package gomigration provides a PostgreSQL migration driver for managing and applying SQL migrations.

Package gomigration provides tools for managing database migrations in Go projects. It supports creating, applying, rolling back, and listing migrations using a customizable driver interface.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrConfigNotProvided          = errors.New("config not provided")
	ErrDriverNotProvided          = errors.New("driver not provided")
	ErrMigrationDirNotProvided    = errors.New("migration directory not provided")
	ErrMigrationDirNotExists      = errors.New("migration directory does not exist")
	ErrMigrationNameNotProvided   = errors.New("migration name not provided")
	ErrMigrationFileAlreadyExists = errors.New("migration file already exists")
	ErrMigrationFileNotFound      = errors.New("migration file not found")
	ErrInvalidRollbackStep        = errors.New("invalid rollback step")
	ErrEmbeddedFSNotProvided      = errors.New("embedded fs not provided")
	ErrGoMigrationNotProvided     = errors.New("gomigration instance not provided")
)

Functions

This section is empty.

Types

type Cli

type Cli struct {
	// contains filtered or unexported fields
}

func NewCli

func NewCli(config CliConfig) (*Cli, error)

func (*Cli) Execute

func (c *Cli) Execute(ctx context.Context) error

type CliConfig

type CliConfig struct {
	GoMigration *GoMigration
	CliName     string
}

type Config

type Config struct {
	Driver             Driver
	MigrationFilesDir  string
	MigrationTableName string
	DebugSql           bool
}

type Driver

type Driver interface {
	// SetMigrationTableName sets the name of the table that stores executed migration records.
	SetMigrationTableName(name string)

	// CreateMigrationsTable creates the migration history table if it does not already exist.
	CreateMigrationsTable(ctx context.Context) error

	// GetExecutedMigrations returns the list of already executed migrations.
	// If reverse is true, the list is returned in descending order (most recent first).
	GetExecutedMigrations(ctx context.Context, reverse bool) ([]ExecutedMigration, error)

	// CleanDatabase drops or truncates all user tables in the database.
	CleanDatabase(ctx context.Context) error

	// ApplyMigrations applies a list of "up" migrations in sequence.
	// The onRunning, onSuccess, and onFailed callbacks are triggered accordingly for each migration.
	ApplyMigrations(
		ctx context.Context,
		migrations []Migration,
		onRunning func(migration *Migration),
		onSuccess func(migration *Migration),
		onFailed func(migration *Migration, err error),
	) error

	// UnapplyMigrations rolls back a list of "down" migrations in sequence.
	// The onRunning, onSuccess, and onFailed callbacks are triggered accordingly for each migration.
	UnapplyMigrations(
		ctx context.Context,
		migrations []Migration,
		onRunning func(migration *Migration),
		onSuccess func(migration *Migration),
		onFailed func(migration *Migration, err error),
	) error

	// Close gracefully closes the connection to the database or releases resources.
	Close() error
}

Driver defines the contract for a migration driver implementation.

type ExecutedMigration

type ExecutedMigration struct {
	Name       string    `json:"name"`
	ExecutedAt time.Time `json:"executed_at"`
}

type GoMigration

type GoMigration struct {
	// contains filtered or unexported fields
}

GoMigration is the main struct for managing and executing database migrations.

func New

func New(config *Config) (*GoMigration, error)

New creates a new instance of GoMigration using the provided configuration. It validates and sets defaults for missing fields, checks for the migration directory, and applies configuration to the driver.

func (*GoMigration) Clean

func (q *GoMigration) Clean(ctx context.Context) error

Clean drops all database tables and objects managed by the migration system.

func (*GoMigration) Create

func (q *GoMigration) Create(fileName string) error

Create generates a new migration file using the given name. The generated file includes a timestamp prefix and basic template content.

func (*GoMigration) Fresh

func (q *GoMigration) Fresh(ctx context.Context) error

Fresh wipes the database clean and reapplies all registered migrations from scratch.

func (*GoMigration) List

List returns all registered migrations along with their execution status.

func (*GoMigration) Migrate

func (q *GoMigration) Migrate(ctx context.Context) error

Migrate applies all pending migrations in the correct order. It skips migrations that have already been executed.

func (*GoMigration) Register

func (q *GoMigration) Register(migrations ...Migration) error

Register adds one or more Migration instances to the internal registry. It ensures no duplicate migration names are registered.

func (*GoMigration) Reset

func (q *GoMigration) Reset(ctx context.Context) error

Reset rolls back all applied migrations and reapplies them from scratch.

func (*GoMigration) Rollback

func (q *GoMigration) Rollback(ctx context.Context, step int) error

Rollback undoes the last `step` number of executed migrations.

func (*GoMigration) SetMigrationFilesDir added in v1.1.0

func (q *GoMigration) SetMigrationFilesDir(dir string) *GoMigration

Set migration files directory.

type Migration

type Migration interface {
	Name() string
	UpScript() string
	DownScript() string
}

type MySqlDriver

type MySqlDriver struct {
	// contains filtered or unexported fields
}

MySqlDriver implements the Driver interface for MySQL.

func NewMySqlDriver

func NewMySqlDriver(
	host string,
	port string,
	user string,
	password string,
	database string,
	charset string,
) (*MySqlDriver, error)

NewMySqlDriver initializes a new MySqlDriver with the given DB config.

func (*MySqlDriver) ApplyMigrations

func (m *MySqlDriver) ApplyMigrations(
	ctx context.Context,
	migrations []Migration,
	onRunning func(migration *Migration),
	onSuccess func(migration *Migration),
	onFailed func(migration *Migration, err error),
) error

ApplyMigrations applies a batch of "up" migrations with optional callbacks.

func (*MySqlDriver) CleanDatabase

func (m *MySqlDriver) CleanDatabase(ctx context.Context) error

CleanDatabase drops all tables from the current database.

func (*MySqlDriver) Close

func (m *MySqlDriver) Close() error

Close closes the database connection.

func (*MySqlDriver) CreateMigrationsTable

func (m *MySqlDriver) CreateMigrationsTable(ctx context.Context) error

CreateMigrationsTable creates the migration table if it doesn't exist.

func (*MySqlDriver) GetExecutedMigrations

func (m *MySqlDriver) GetExecutedMigrations(ctx context.Context, reverse bool) ([]ExecutedMigration, error)

GetExecutedMigrations returns a list of previously executed migrations, optionally in reverse order.

func (*MySqlDriver) SetMigrationTableName

func (m *MySqlDriver) SetMigrationTableName(name string)

SetMigrationTableName sets the name of the migration tracking table.

func (*MySqlDriver) UnapplyMigrations

func (m *MySqlDriver) UnapplyMigrations(
	ctx context.Context,
	migrations []Migration,
	onRunning func(migration *Migration),
	onSuccess func(migration *Migration),
	onFailed func(migration *Migration, err error),
) error

UnapplyMigrations rolls back a batch of "down" migrations with optional callbacks.

type PostgresDriver

type PostgresDriver struct {
	// contains filtered or unexported fields
}

PostgresDriver manages database connections and migration operations for PostgreSQL.

func NewPostgresDriver

func NewPostgresDriver(
	host string,
	port string,
	user string,
	password string,
	database string,
	schema string,
) (*PostgresDriver, error)

NewPostgresDriver creates and returns a new instance of PostgresDriver. It opens a connection to the given PostgreSQL database using the provided credentials and schema.

func (*PostgresDriver) ApplyMigrations

func (p *PostgresDriver) ApplyMigrations(
	ctx context.Context,
	migrations []Migration,
	onRunning func(migration *Migration),
	onSuccess func(migration *Migration),
	onFailed func(migration *Migration, err error),
) error

ApplyMigrations runs the "up" SQL scripts for the given migrations. Optional callbacks can be provided to track the progress of each migration.

func (*PostgresDriver) CleanDatabase

func (p *PostgresDriver) CleanDatabase(ctx context.Context) error

CleanDatabase drops all tables in the "public" schema.

func (*PostgresDriver) Close

func (p *PostgresDriver) Close() error

Close closes the database connection.

func (*PostgresDriver) CreateMigrationsTable

func (p *PostgresDriver) CreateMigrationsTable(ctx context.Context) error

CreateMigrationsTable creates the migration tracking table if it does not exist.

func (*PostgresDriver) GetExecutedMigrations

func (p *PostgresDriver) GetExecutedMigrations(ctx context.Context, reverse bool) ([]ExecutedMigration, error)

GetExecutedMigrations returns a list of executed migrations from the tracking table. If reverse is true, the list is ordered descending by name.

func (*PostgresDriver) SetMigrationTableName

func (p *PostgresDriver) SetMigrationTableName(name string)

SetMigrationTableName sets the name of the table used to track executed migrations. If the provided name is empty, the default "migrations" is used.

func (*PostgresDriver) UnapplyMigrations

func (p *PostgresDriver) UnapplyMigrations(
	ctx context.Context,
	migrations []Migration,
	onRunning func(migration *Migration),
	onSuccess func(migration *Migration),
	onFailed func(migration *Migration, err error),
) error

UnapplyMigrations runs the "down" SQL scripts for the given migrations in reverse order. Optional callbacks can be provided to track the progress of each migration.

type RegisteredMigration

type RegisteredMigration struct {
	Name       string
	UpScript   string
	DownScript string
	IsExecuted bool
	ExecutedAt *time.Time
}

type RegisteredMigrationList

type RegisteredMigrationList []RegisteredMigration

func (RegisteredMigrationList) Print

func (m RegisteredMigrationList) Print()

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL