Skip to content
/ adapt Public

📦 adapt is a simple general-purpose migration library that gets embedded into your Go application

License

Notifications You must be signed in to change notification settings

harwoeck/adapt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation


adapt is a simple, non-magical general purpose migration library that gets embedded into your application.

Features

  • 🟢 Simplicity: Migration lifecycle and schema versioning is completely abstracted and managed by adapt
  • 🟢 Concurrency controlled (protected from race-conditions): Mutexes and other techniques are used to prevent multiple adapt instances conflicting each other during concurrent boot-ups
  • 🟢 Extensible: Simple Driver and migration Source interfaces
  • 🟢 Migrations: can be provided in a variety of ways and get merged and sorted into a single migration-collection, which is applied against the version-controlled schema in your storage
    • Go Code for all non-database migrations or situations where SQL doesn't do the job
    • Embed migration folders containing your SQL scripts
    • Hardcoded SQL statements
  • 🟢 Branching and merging compatible: adapt automatically catches up with missing migrations ("holes")
  • 🟢 Zero external dependencies
  • 🟢 Customizable Logging: adapt uses slog included with Go 1.21+ so that you can provide your own logging backend.

Supported Storage Driver

Any other storage backend by providing your own Driver, DatabaseDriver or SqlStatementsDriver. Unlike most other migration tools, with adapt there is no reliance on database/sql (such a case can be seen with the included FileDriver)

Supported Migrations

Note

Please support this project and provide additional sources that could be useful for other people

Install

$ go get github.com/harwoeck/adapt

Usage

var db *sql.DB = initDB()

err := adapt.Migrate(
    "backend@v0.1.17",                      // <name> of executor
    adapt.NewMySQLDriver(db),               // Database driver
    adapt.SourceCollection{
        adapt.NewFilesystemSource("./sql"), // SQL-Migration-Scripts from filesystem
    })

Note

Next example: Due to compliance rules you decide to encrypt your users email addresses inside your database. Since this requires actual Go code (and not just SQL statements), you could implement one of the adapt.Hook functions and during your next deployment adapt will notice this new unapplied migration and execute your hook. When no error is returned adapt will commit the transaction and update the schema table with the relevant meta information.

err := adapt.Migrate(
    "backend@v0.1.17",                      // <name> of executor
    adapt.NewMySQLDriver(db),               // Database driver
    adapt.SourceCollection{                 // adapt will automatically merge and sort all provided sources for you
        adapt.NewFilesystemSource("./sql"), // SQL-Migration-Scripts from filesystem
        adapt.NewCodeSource("2020-04-17_1104_encrypt-user-email", adapt.Hook{
            MigrateUpTx: func(tx *sql.Tx) error {
                // For this encrypt-migration you could use `MigrateUpTx` to load
                // the rows, encrypt the content in Go and update the columns again
                // within a single managed transaction.
                return nil
            },
        },
    })

Inspired by

This project was heavily inspired by the features and ideas of these great projects: