# HG changeset patch # User Peter Sanchez # Date 1644972170 21600 # Tue Feb 15 18:42:50 2022 -0600 # Node ID 9351697225fe835dcb148bfd5199504cf369dd90 # Parent 236e759e7ce9faedffdcb6e87602e7de31efcb44 Adding extra docs and README diff --git a/PREVIOUS_LICENSES b/PREVIOUS_LICENSES new file mode 100644 --- /dev/null +++ b/PREVIOUS_LICENSES @@ -0,0 +1,23 @@ +# The original migrate package was using the following license. + +MIT License + +Copyright (c) 2020 Jon Calhoun + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 --- /dev/null +++ b/README.md @@ -0,0 +1,221 @@ +# migrate + +Database migrations for your Go project. Supports files, functions, and query +migrations. + +**Version:** 0.1.0 + +**Project Links:** [Docs][docs] - [Issues][issues] - [Mailing List][pinbox] - +[Contributing](#contributing) + +**Author:** Peter Sanchez () + +[docs]: https://godocs.io/petersanchez.com/migrate +[issues]: https://todo.code.netlandish.com/~petersanchez/migrate +[pinbox]: https://lists.code.netlandish.com/~petersanchez/public-inbox + +## Requirements + +- Go 1.16+ (probably works with older, I just didn't test it) + +## What? + +This is a simple tool to manage database migrations from within your Go +project. It's not a CLI tool, but a module that you plugin to your own project +as needed. + +It's based on [github.com/joncalhoun/migrate][ogmigrate] but I've done many +changes to make it fit my needs. That is why I am just maintaining my own fork +versus submitting a PR. I feel mine has diverged too far from what Jon +originally wanted. + +Here's some of the changes: + +- Removed sqlx as dependency. +- Added support for a global `context.Context` within migrations. +- Added support for specific timeouts (via `context.Context`) per migration. +- Added ability to specify a up (migrate) or down (rollback) specific version. +- Added ability to "fake" a migration (up only). Essentially just adding the + entry to migration history without actually running it. Useful for edge + cases. +- Added checks for migration ID duplication. +- Added check to ensure migration ID exists when a specific ID is given. This + is to avoid running migrations when an entry error has occurred. + +My fork is a copy of the original repo as of [this commit][mci]. I probably +should have done a repo migration to Mercurial but here we are. All code up to +the commit above is licensed under the MIT license, see the `PREVIOUS_LICENSES` +document. + +[mci]: https://github.com/joncalhoun/migrate/commit/34a9ee7d2b52f7b9f2261c2b6d9a8a0a83890a7f + +## Example usage + +This example will assume you're using PostgreSQL as well (note the changing of +binding type to `migrate.DOLLAR`). + +Let's say you have a simple directory structure like so: + +``` +. +├── accounts +│   ├── input.go +│   ├── models.go +│   ├── routes.go +├── cmd +│   └── webapp +│   └── main.go +├── go.mod +├── go.sum +├── webapp_binary +├── Makefile +├── migrations +│   ├── 0001_initial_rollback.sql +│   └── 0001_initial.sql +├── templates +    ├── login.html +    └── register.html + +``` + +You can see there is a `migrations` directory. You can store your migration +files anywhere you want, but in this example we'll store them there. + +Now let's add migrations to the main binary. We'll edit `cmd/webapp/main.go` to +always call migrations when starting. I'm not recommending this, just a simple +example. + +``` +import ( + ... + "petersanchez.com/migrate", + ... +) + +func main() { + // `db` is your database connection (*sql.DB) + + var ( + verbose, fakeIt bool + direction, stopID string + ) + + mf := flag.NewFlagSet("migrate", flag.ContinueOnError) + mf.BoolVar(&verbose, "verbose", false, "verbose output") + mf.BoolVar(&fakeIt, "fake", false, "fake migrations") + mf.Usage = func() { + msg := fmt.Sprintf("usage: %s migrate [options...] [up | down] [migration ID]\n", os.Args[0]) + fmt.Fprintf(flag.CommandLine.Output(), msg) + mf.PrintDefaults() + } + + if os.Args[1] != "migrate" { + mf.Usage() + return fmt.Errorf("Unknown command: %s", os.Args[1]) + } + + mf.Parse(os.Args[2:]) + args := mf.Args() + + if len(args) > 0 { + direction = args[0] + if direction != "up" && direction != "down" { + return fmt.Errorf("Unknown migration direction: %s", direction) + } + } + + if len(args) > 1 { + stopID = args[1] + } + + // Custom functions should be watching for the context's Done() channel + migrations := []migrate.Migration{ + migrate.FileMigration("0001_initial", "migrations/0001_initial.sql", "migrations/0001_initial_rollback.sql", 0), + migrate.Migration{ + ID: "0002_function", + Migrate: func(ctx context.Context, tx *sql.Tx) error { + // Run your migrate code here. + return nil + }, + Rollback: func(ctx context.Context, tx *sql.Tx) error { + // Run your rollback code here. + return nil + }, + Timeout: 40, // Set a 40 second timeout on the functions + }, + } + + ctx := context.Background() + engine := migrate.NewEngine(db, migrations, migrate.DOLLAR, verbose) + if direction == "down" { + return engine.Rollback(ctx, stopID) + } + return engine.Migrate(ctx, stopID, fakeIt) +} + +``` + +## Why? + +I found the larger database migration projects for Go to be overkill for my +needs. Especially if you wanted to run custom function migrations. + +During my research I stumbled on an article titled [Database migrations in +Go][dbgo] by [Jon Calhoun][jc]. I had already been thinking of how to create my +own migrations package as minimally as possible and this article was close +enough to what I was thinking. John even created the original +[migrate][ogmigrate] package, but it lacked several things I wanted in my +migration solution. + +So I stripped out external dependencies, added a bunch of stuff I wanted, and a +few development hours later, here we are. + +[dbgo]: https://www.calhoun.io/database-migrations-in-go/ +[jc]: https://twitter.com/joncalhoun +[ogmigrate]: https://github.com/joncalhoun/migrate + +## Status + +My needs are fairly simple and the current state of the module basically covers +them. Please submit bugs and/or patches if you find any issues. + +# Contributing + +We accept patches submitted via `hg email` which is the `patchbomb` extension +included with Mercurial. + +The mailing list where you submit your patches is +`~petersanchez/public-inbox@lists.code.netlandish.com`. You can also view the +archives on the web here: + +https://lists.code.netlandish.com/~petersanchez/public-inbox + +To quickly setup your clone of `migrate` to submit to the mailing +list just edit your `.hg/hgrc` file and add the following: + + [email] + to = ~petersanchez/public-inbox@lists.code.netlandish.com + + [patchbomb] + flagtemplate = "migrate" + + [diff] + git = 1 + +We have more information on the topic here: + +- [Contributing][cdoc] +- [Using email with Mercurial][hgemail] +- [Mailing list etiquette][etiquette] + +[etiquette]: https://man.code.netlandish.com/lists/etiquette.md +[hgemail]: https://man.code.netlandish.com/hg/email.md +[cdoc]: https://man.code.netlandish.com/contributing.md + +Copyright & Warranty +==================== + +All documentation, libraries, and sample code are Copyright 2022 Peter +Sanchez <>. The library and sample code +are made available to you under the terms of the BSD license which is +contained in the included file, LICENSE. diff --git a/doc.go b/doc.go new file mode 100644 --- /dev/null +++ b/doc.go @@ -0,0 +1,6 @@ +// Package migrate is a simple and flexible module to manage database migrations. +// +// You can use migration files, queries, and custom functions to manage your +// migrations. Also has full Context support (globally and per migration) and +// has no external dependencies. +package migrate