drift

package module
v0.1.1 Latest Latest
Warning

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

Go to latest
Published: Feb 24, 2022 License: MIT Imports: 18 Imported by: 0

README

Drift

Drift manages Postgresql database migrations.

There's no shortage of tools for running migrations, but this one embodies my particular opinions:

  1. Migrations should be written in database-specific SQL.
  2. Migrations are not generally idempotent or reversible.
  3. Migration dependencies form a tree, not a line.

Installation

To install Drift as a command, use go install:

go install github.com/metagram-net/drift/cmd/drift

Since this tool is still very unstable, consider pinning the version in your go.mod with the tools pattern.

To use Drift as a library, use go get:

go get github.com/metagram-net/drift

Usage

Run drift help to get usage information from each subcommand.

First-time setup

Write the configuration file (drift.toml) or set the equivalent environment variables. The environment variables take precedence over the file.

The environment variables are upper snake-case versions of the ones in the file with DRIFT_ prefixes. For example, database-url is DRIFT_DATABASE_URL.

# The connection string for the database to run migrations on.
#
# You might prefer to set this using an environment variable.
#
# Default: "" (default PostgreSQL server)
database-url = ""

# The directory used to store migration files.
#
# Default: "migrations"
migrations-dir = "migrations"

# The template to use for new migration files.
#
# Default: "" (use the embedded default migration template)
template-file = "migrations/_template.sql"

# How much info to log to stderr. Greater numbers mean more output, and 0 logs
# nothing.
#
# Default: 1
verbosity = 1

Then, generate the first migration that sets up Drift's requirements:

drift setup

That should have written 0-init.sql to your migrations directory. Read it and make any changes you want.

Finally, run the migration:

drift migrate
Writing a new migration

Create a new empty migration file:

drift new --slug 'create_users_table'

Write your migration in the file. Then run it:

drift migrate
Undoing a migration

For a migration that has already been run in production (or some other shared environment), the best option is to write a new migration to undo the old one.

To be able to re-run a migration you're developing, call _drift_unclaim_migration with the migration ID. You might find it useful to keep an undo.sql file around (ignored by version control) to modify along with the migration.

-- undo.sql
select _drift_unclaim_migration(1645673864);

drop table if exists users;

License

Source code and binaries are distributed under the terms of the MIT license.

Contributing

I welcome contributions from anyone who finds a way to make this better.

In particular, I appreciate these things:

  • Pull requests with clear motivation (tests are nice too!)
  • Bug reports with reproducible setup instructions
  • Ideas about things that work but can be improved

Support

This is is hobby project, so I'll only work on it as much as I find it fun to do so. That said, I find software maintenance techniques interesting, so feel free to start a conversation about a stable v1 if you start relying on this for something important.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNegativeID  = errors.New("migration ID must not be negative")
	ErrDuplicateID = errors.New("duplicate migration ID")
)

Functions

func DefaultTemplate

func DefaultTemplate() string

DefaultTemplate returns the default template contents.

func Migrate

func Migrate(ctx context.Context, io IO, db *sql.DB, migrationsDir string, upto *MigrationID) error

Migrate runs all unapplied migrations in ID order, least to greatest. It skips any migrations that have already been applied.

If upto is non-nil, this will also skip any migrations with IDs greater than that value.

func NewFile

func NewFile(io IO, migrationsDir string, id MigrationID, slug string, tmpl *template.Template) (string, error)

NewFile creates a new migration file with a placeholder comment in it.

func Renumber

func Renumber(io IO, dir string, write bool) error

func Setup

func Setup(migrationsDir string) (string, error)

Setup creates the "init" migration that will prepare the database for migrations. This will create the migrations directory if needed.

Types

type IO

type IO interface {
	Infof(format string, args ...interface{}) (n int, err error)
	Debugf(format string, args ...interface{}) (n int, err error)
}

type MigrationID

type MigrationID int64

A MigrationID is a nonnegative integer that will be used to sort migrations.

This will often be a Unix timestamp in seconds, so it's represented as as an int64 for easy conversion. That technically allows negative numbers (although getting one in modern times would be concerning!), so use NewMigrationID to check for negative values.

func NewMigrationID

func NewMigrationID(i int64) (MigrationID, error)

func (*MigrationID) Set

func (m *MigrationID) Set(s string) error

func (*MigrationID) String

func (m *MigrationID) String() string

func (*MigrationID) Type

func (*MigrationID) Type() string

func (MigrationID) Width

func (m MigrationID) Width() int

type Queryable

type Queryable interface {
	ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
}

type TemplateData

type TemplateData struct {
	ID   MigrationID
	Slug string
}

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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