migrate

package module
v2.0.0-alpha.14 Latest Latest
Warning

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

Go to latest
Published: Jul 21, 2020 License: MIT Imports: 1 Imported by: 0

README

Migrate

CircleCI branch License GitHub tag (latest SemVer)

The library was originally forked from sql-migrate which is a really great project. However I needed a tool that is somewhat more golang idiomatic in nature. So I completely re-wrote the API for the forked library and optimized on a whole lot of stuff inside. I am using this project to back a few other major developments I am working on and will keep updating things as needed. If you do find bugs please feel free to submit a pull request.

Notice

Version 2.0 is quiet different from the original fork and is the one I use in production for projects I support. It comes with kubernetes releases as migrations. Think helm but in pure golang in-code manifests. This doc below doesn't reflect those changes almost at all. Feel free to explore the code under the different tag and ask questions. Whenever I get some time I will update this doc and create an example illustrating how all that works.

Features

  • Usable as an embedded CLI tool
  • Supports SQLite, PostgreSQL, MySQL, MSSQL (through gorp)
  • Migrations are defined with SQL for full flexibility
  • Transaction based migrations with ability to run transactionless
  • Migration rollback support through up and down commands
  • Supports multiple database types in one project

Installation

To embed the application, use the following from within your project directory:

go get -u github.com/trivigy/migrate

Usage

The way the library works is purely through embedding it in another project as a runnable cmd. You can then create multiple of these for different databases that your project supports.

For example here is a possible project structure where this tool would be embedded:

$ tree ./project
./project
.
├── cmd
│   └── migrate
│       └── main.go
├── go.mod
├── go.sum
├── internal
│   └── migrations
│       ├── 0.0.1_create-users-table.go
│       ├── 0.0.2_create-emails-table.go
│       └── 0.0.3_create-zipcodes-table.go
├── README.md
└── main.go

In this case your main project is inside of main.go located at the tree root. You will then follow by creating the ./cmd/migrate folder and adding a main.go file there. Here is an example of what should be added to that file.

There is absolutely no requirement to call the embedded application migrate. In fact if you are using multiple migration setups, you will have to create a few of these and call them differently.

Skip down here if you just want to see how to write migrations HERE

./cmd/migrate/main.go
package main

import (
	"os"

	"github.com/trivigy/migrate"

	_ "github.com/username/project/internal/migrations"
)

func init() {
	migrate.SetConfigs(map[string]migrate.DataSource{
		"development": {
			Driver: "postgres",
			Source: "host=127.0.0.1 user=postgres dbname=database sslmode=disable",
		},
	})
}

func main() {
	if err := migrate.Execute(); err != nil {
		os.Exit(1)
	}
}

Most important part here is to add the main() function with that exact call to migrate.Execute(). Once you do that, you can run the embedded command to help you do the rest.

As you can see, the configuration for the tool are done programmically through migrate.SetConfigs(). The key of the passed map acts as the environment name. You later reference it when calling different commands. The environment names can be anything you want. In this case I chose to call it development.

Currently SQLite, PostgreSQL, MySQL, MSSQL drivers are supported and the values of driver and source are passed varbatum down to sql.Open(driver, source). Thus the format for source is depended on the type of the database.

Use --help to learn about what commands you can run:

$ go run ./cmd/migrate --help
Idiomatic GO database migration tool

Usage:
  main [command]

Available Commands:
  create      Create a newly versioned migration template file
  down        Undo the last applied database migration
  status      Show migration status for the current database
  up          Migrates the database to the most recent version

Flags:
  -v, --version   Print version information and quit.
      --help      Show help information.

Use "main [command] --help" for more information about a command.

Use the --help flag in combination with any of the commands to get an overview of its usage:

$ go run ./cmd/migrate up --help
Migrates the database to the most recent version

Usage:
  main up [flags]

Flags:
      --dry-run      Simulate a migration printing planned queries.
  -n, --num NUMBER   Indicate NUMBER of migrations to apply.
  -e, --env ENV      Run with configurations named ENV. (required)
      --help         Show help information.

MySQL Caveat

If you are using MySQL, you must append ?parseTime=true to the source DSN configuration. See here for more information. For example:

alternative ./cmd/migrate/main.go
package main

import (
	"os"

	"github.com/trivigy/migrate"

	_ "github.com/username/project/internal/migrations"
)

func init() {
	migrate.SetConfigs(map[string]migrate.DataSource{
		"testing": {
			Driver: "mysql",
			Source: "root@/dbname?parseTime=true",
		},
	})
}

func main() {
	if err := migrate.Execute(); err != nil {
		os.Exit(1)
	}
}

Writing Migrations

Migrations are embedded into the command by referencing them with import _ "github.com/username/project/internal/migrations". You might have noticed this from the ./cmd/migrate/main.go examples above. I am chosing to place the migration files inside ./internal/migrations but in face you may chose to place them elsewhere.

To help you create migration files quicker, there is the create command. What is special about it is that it will auto-increment the migration version tags which need to be unique.

$ go run ./cmd/migrate create --help
Create a newly versioned migration template file

Usage:
  main create NAME[:TAG] [flags]

Flags:
  -d, --dir PATH   Specify directory PATH to create miration file. (default ".")
      --help       Show help information.

The tags follow an almost complete semver model. You can use major, minor, patch, and build parts of the semantic versioning scheme to tag your migrations. The migrations get sorted based on this semantic tagging scheme. For more detail on the precedence order read semver.

An example migration file might look like this:

$ cat ./internal/migrations/0.0.4_create-zipcodes-table.go 
package migrations

import (
        "github.com/trivigy/migrate"
)

func init() {
        migrate.Append(migrate.Migration{
                Tag: "0.0.4",
                Up: []migrate.Operation{
                        {Query: `CREATE TABLE zipcodes (id int)`},
                },
                Down: []migrate.Operation{
                        {Query: `DROP TABLE zipcodes`},
                },
        })
}

The filename for the migration files DO NOT follow a strict naming convention of {tag}_{filename}.go. The actual filename is there just to help the developer communicate file purpose. However, when using the create command filenames are generated with that name.

Documentation

Overview

Package migrate implements an abstract migration tool.

Index

Constants

This section is empty.

Variables

View Source
var Registry types.Registry

Registry is the container holding registered migrations.

Functions

This section is empty.

Types

This section is empty.

Directories

Path Synopsis
Package driver implements driver capability interfaces and drivers for local development.
Package driver implements driver capability interfaces and drivers for local development.
docker
Package docker implements migrate drivers that operate on top of docker.
Package docker implements migrate drivers that operate on top of docker.
generic
Package generic implements abstract drivers for migrate package.
Package generic implements abstract drivers for migrate package.
Package global implements global definitions for migrate package.
Package global implements global definitions for migrate package.
internal
retry
Package retry implements a goroutine based retry ticker.
Package retry implements a goroutine based retry ticker.
store
Package store implements operations associated with update migration records.
Package store implements operations associated with update migration records.
store/model
Package model implements database access objects for the store operations.
Package model implements database access objects for the store operations.
Package require implements cobra arguments verification helpers.
Package require implements cobra arguments verification helpers.
Package resource implements pluggable cobra subcommands.
Package resource implements pluggable cobra subcommands.
database
Package database implements the database subcommand structure.
Package database implements the database subcommand structure.
database/migrations
Package migrations implements the migrations subcommand structure.
Package migrations implements the migrations subcommand structure.
kubernetes
Package kubernetes implements kubernetes related set of commands.
Package kubernetes implements kubernetes related set of commands.
kubernetes/releases
Package releases implements the releases subcommand structure.
Package releases implements the releases subcommand structure.
primitive
Package primitive implements basic set of commands.
Package primitive implements basic set of commands.
Package testutils implements helper functions for running unittests.
Package testutils implements helper functions for running unittests.
Package types implements migrate related interfaces and models.
Package types implements migrate related interfaces and models.

Jump to

Keyboard shortcuts

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