dbmigrator

package
v0.0.13 Latest Latest
Warning

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

Go to latest
Published: Mar 5, 2026 License: MIT Imports: 10 Imported by: 0

README

dbmigrator

A thin wrapper around golang-migrate that runs PostgreSQL schema migrations from one or more embedded filesystems (embed.FS).

Features

  • Runs UP migrations automatically on call
  • Reads migration files from embed.FS — no filesystem access at runtime
  • Supports multiple sources merged into a single migration sequence
  • Returns the schema version before and after migration
  • Detects and rejects dirty database state before running

Migration file format

Files follow the standard golang-migrate naming convention:

{version}_{title}.up.sql
{version}_{title}.down.sql
  • version — positive integer, determines execution order
  • title — arbitrary label (underscores, letters, digits)
  • Both .up.sql and .down.sql files are required for each version

Example:

migrations/
  001_create_users.up.sql
  001_create_users.down.sql
  002_add_email_index.up.sql
  002_add_email_index.down.sql

Version numbers must be globally unique across all sources when using multiple sources.

Usage

Single source
package main

import (
    "embed"
    "log"

    "github.com/ashep/go-app/dbmigrator"
    "github.com/rs/zerolog"
)

//go:embed migrations/*.sql
var migrationsFS embed.FS

func main() {
    logger := zerolog.New(os.Stderr)

    result, err := dbmigrator.RunPostgres(
        "postgres://user:pass@localhost:5432/mydb",
        logger,
        dbmigrator.Source{FS: migrationsFS, Path: "migrations"},
    )
    if err != nil {
        log.Fatal(err)
    }

    log.Printf("migrated: v%d -> v%d", result.PrevVersion, result.NewVersion)
}
Multiple sources

Useful when migrations are spread across multiple packages (e.g., a core module and a plugin each own their own schema files).

//go:embed core/migrations/*.sql
var coreFS embed.FS

//go:embed plugin/migrations/*.sql
var pluginFS embed.FS

result, err := dbmigrator.RunPostgres(
    "postgres://user:pass@localhost:5432/mydb",
    logger,
    dbmigrator.Source{FS: coreFS,   Path: "core/migrations"},
    dbmigrator.Source{FS: pluginFS, Path: "plugin/migrations"},
)

Sources are merged in the order they are provided. If two sources contain a file with the same name, the first source wins and the duplicate is silently ignored. To avoid ambiguity, keep version numbers unique across all sources.

API

RunPostgres
func RunPostgres(url string, l zerolog.Logger, sources ...Source) (*MigrationResult, error)

Connects to the PostgreSQL database at url, merges all provided sources, and applies any pending UP migrations.

Returns MigrationResult on success, or an error if:

  • A source path cannot be read
  • The database connection fails
  • The current schema version is dirty
  • A migration fails to apply

Calling RunPostgres when the database is already up-to-date is safe — it returns the current version without error.

Source
type Source struct {
    FS   embed.FS
    Path string
}

Pairs an embedded filesystem with the subdirectory within it that contains migration files.

MigrationResult
type MigrationResult struct {
    PrevVersion uint
    NewVersion  uint
}

Both fields are 0 when the database has no migrations applied yet (ErrNilVersion is treated as version 0).

Error handling

Situation Behavior
Database already at latest version Returns current version, nil error
Database has no migrations applied PrevVersion: 0, runs all migrations
Dirty version detected Returns error: current version is dirty: N
Duplicate file name across sources First source wins; duplicate is ignored
Duplicate version number across sources golang-migrate returns an error
Migration SQL fails Returns error, database left in dirty state

Schema migrations table

golang-migrate tracks the applied version in a schema_migrations table created automatically in the target database. Do not modify this table manually.

Dependencies

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type MigrationResult

type MigrationResult struct {
	PrevVersion uint
	NewVersion  uint
}

func RunPostgres

func RunPostgres(url string, l zerolog.Logger, sources ...Source) (*MigrationResult, error)

type Source added in v0.0.13

type Source struct {
	FS   embed.FS
	Path string
}

Jump to

Keyboard shortcuts

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