migration

package
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Aug 31, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrChecksumMismatch is returned when a previously applied migration's
	// content no longer matches the checksum recorded at apply time.
	ErrChecksumMismatch = errors.New("migration: checksum mismatch, applied migration was modified")
	// ErrDirtyState is returned when the history table contains a migration
	// left in an incomplete (dirty) state by a previous failed run.
	ErrDirtyState = errors.New("migration: dirty migration state, manual intervention required")
	// ErrDuplicateVersion is returned when two migrations declare the same version.
	ErrDuplicateVersion = errors.New("migration: duplicate migration version")
	// ErrLocked is returned when the migration lock could not be acquired.
	ErrLocked = errors.New("migration: could not acquire migration lock")
	// ErrNoMigrations is returned when no migrations are available to run.
	ErrNoMigrations = errors.New("migration: no migrations found")
	// ErrAlreadyApplied is returned when attempting to reapply a migration
	// that is already recorded as applied.
	ErrAlreadyApplied = errors.New("migration: already applied")
	// ErrNotApplied is returned when attempting to roll back a migration
	// that was never applied.
	ErrNotApplied = errors.New("migration: not applied")
	// ErrOutOfOrder is returned when a pending migration has a lower version
	// than one already applied, and out-of-order execution was not allowed.
	ErrOutOfOrder = errors.New("migration: out-of-order migration")
)

Functions

func Checksum

func Checksum(content []byte) string

Checksum returns the hex-encoded SHA-256 digest of content. It is used to detect modifications to a migration after it has been applied.

Types

type DB

type DB interface {
	ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
	QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
	QueryRowContext(ctx context.Context, query string, args ...any) *sql.Row
}

DB is the minimal database surface the migration engine depends on. Concrete providers (postgres, mariadb) wrap a *sql.DB or *sql.Tx to satisfy it.

type Direction

type Direction int

Direction identifies which side of a migration is being executed.

const (
	Up Direction = iota
	Down
)

func (Direction) String

func (d Direction) String() string

type Engine

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

Engine runs migrations against a database using a Provider for locking, transactional behavior and history storage. The CLI and the MCP server both operate exclusively through this type, so they share identical guarantees.

func NewEngine

func NewEngine(db DB, provider Provider, entries []Entry) (*Engine, error)

NewEngine builds an Engine from a sorted, de-duplicated migration set.

func (*Engine) Fresh

func (e *Engine) Fresh(ctx context.Context) (Result, error)

Fresh reverts every applied migration and then re-applies all of them.

func (*Engine) Plan

func (e *Engine) Plan(ctx context.Context, dir Direction, steps int) ([]Entry, error)

Plan reports which migrations Up or Rollback would execute, without modifying the database.

func (*Engine) Reset

func (e *Engine) Reset(ctx context.Context) (Result, error)

Reset reverts every applied migration, newest first.

func (*Engine) Rollback

func (e *Engine) Rollback(ctx context.Context, steps int) (Result, error)

Rollback reverts the most recently applied batch, or the last N applied migrations overall when steps > 0.

func (*Engine) Status

func (e *Engine) Status(ctx context.Context) ([]StatusEntry, error)

Status lists every known migration alongside its applied state.

func (*Engine) Up

func (e *Engine) Up(ctx context.Context, steps int) (Result, error)

Up applies pending migrations in ascending version order. steps <= 0 applies all of them.

func (*Engine) Validate

func (e *Engine) Validate(ctx context.Context) error

Validate verifies checksums of applied migrations and reports dirty state, without touching the database beyond reading the history table.

type Entry

type Entry struct {
	Migration
	Checksum string
}

Entry pairs a Migration with the checksum used to detect later modifications. SQL migrations are checksummed from their file contents; Go migrations carry a checksum supplied at registration time (typically generated by `goforge generate` from the source file contents).

func Load

func Load(fsys fs.FS, reg *Registry) ([]Entry, error)

Load combines SQL migrations discovered in fsys with Go migrations from reg into a single, version-sorted list. reg may be nil if the project has no Go migrations.

func LoadSQLMigrations

func LoadSQLMigrations(fsys fs.FS) ([]Entry, error)

LoadSQLMigrations discovers *.up.sql / *.down.sql pairs directly under the root of fsys, named "000001_create_users.up.sql". Both files must exist for a given version. The developer's SQL is executed as written; GoForge never rewrites or translates it between providers.

type HistoryStore

type HistoryStore interface {
	// EnsureTable creates the history table if it does not exist yet.
	EnsureTable(ctx context.Context, db DB) error
	// List returns all recorded migrations ordered by version.
	List(ctx context.Context, db DB) ([]Record, error)
	// Begin records a migration as started (dirty=true) before it runs.
	// For providers without transactional DDL this is what allows a crash
	// mid-migration to be detected on the next run.
	Begin(ctx context.Context, db DB, version uint64, name, checksum string, batch int) error
	// Complete marks a previously begun migration as finished successfully.
	Complete(ctx context.Context, db DB, version uint64, executionTime time.Duration) error
	// Remove deletes a migration's record, used when rolling back.
	Remove(ctx context.Context, db DB, version uint64) error
}

HistoryStore persists migration history. Providers implement it on top of their own SQL dialect (column types, quoting) while the engine only depends on this interface.

type Locker

type Locker interface {
	Lock(ctx context.Context) error
	Unlock(ctx context.Context) error
}

Locker prevents two processes from running migrations concurrently against the same database. Implementations are provider-specific (PostgreSQL advisory locks, MariaDB GET_LOCK).

type Migration

type Migration interface {
	Version() uint64
	Name() string
	Up(ctx context.Context, db DB) error
	Down(ctx context.Context, db DB) error
}

Migration is a single, versioned schema change. Implementations are provided either as Go code (registered explicitly via a Registry) or generated from a pair of .up.sql / .down.sql files.

type Provider

type Provider interface {
	Name() string
	// SupportsTransactionalDDL reports whether a migration's Up/Down and its
	// history bookkeeping can be wrapped in a single transaction.
	SupportsTransactionalDDL() bool
	Locker(db DB) Locker
	History() HistoryStore
}

Provider encapsulates the database-specific behavior the engine needs: locking strategy, transactional DDL support and history storage.

type Record

type Record struct {
	Version       uint64
	Name          string
	Checksum      string
	AppliedAt     time.Time
	ExecutionTime time.Duration
	Batch         int
	Dirty         bool
}

Record is a row of the goforge_migrations history table.

type Registry

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

Registry holds explicitly registered Go migrations. Go migration files are never parsed dynamically; they must call Register (directly, or through the file generated by `goforge generate`) to be picked up by the engine.

func NewRegistry

func NewRegistry() *Registry

NewRegistry returns an empty Registry.

func (*Registry) All

func (r *Registry) All() []Entry

All returns every registered entry, unordered.

func (*Registry) Register

func (r *Registry) Register(m Migration, checksum string) error

Register adds a Go migration with the checksum computed at generation time from its source file. It returns ErrDuplicateVersion if the version was already registered.

type Result

type Result struct {
	Executed []Record
	Batch    int
}

Result reports what an Up/Rollback/Reset/Fresh call executed.

type StatusEntry

type StatusEntry struct {
	Version   uint64
	Name      string
	Applied   bool
	AppliedAt time.Time
	Batch     int
	Dirty     bool
}

StatusEntry describes one migration's applied/pending state.

type Tx

type Tx interface {
	DB
	Commit() error
	Rollback() error
}

Tx is an in-flight transaction. *sql.Tx satisfies this interface, but the engine depends only on this instead of the concrete type so that transactional execution can be unit tested without a real database.

type TxCapableDB

type TxCapableDB interface {
	DB
	BeginTx(ctx context.Context, opts *sql.TxOptions) (Tx, error)
}

TxCapableDB is implemented by connections that can open transactions. Providers that support transactional DDL must pass a DB satisfying this interface to the engine.

Jump to

Keyboard shortcuts

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