GithubHelp home page GithubHelp logo

goose's Introduction

Documentation Build Status Coverage Status

goose

goose is a database migration tool.

You can manage your database's evolution by creating incremental SQL or Go scripts.

Stability notice

This repo is a fork from https://bitbucket.org/liamstask/goose. There are many things that we plan to change, mostly to make the tool easier to use, and more standardized.

As such, until this notice goes away, vendoring is highly recommended.

Install

$ go get github.com/CloudCom/goose/cmd/goose

This will install the goose binary to your $GOPATH/bin directory.

You can also build goose into your own applications by importing github.com/CloudCom/goose/lib/goose. Documentation is available at godoc.org.

NOTE: the API is still new, and may undergo some changes.

Omitting drivers

The default goose binary includes support for all available drivers. Sometimes this results in a lengthy build process. Drivers may be omitted from the build by using build tags.

For example

$ go get -tags nosqlite3 github.com/CloudCom/goose/cmd/goose

The available tags are:

  • nomymysql
  • nomysql
  • nopq
  • nosqlite3

Usage

goose provides several commands to help manage your database schema.

create

Create a new SQL migration.

$ goose create AddSomeColumns
$ goose: created db/migrations/20130106093224_AddSomeColumns.sql

Edit the newly created script to define the behavior of your migration.

You can also create a Go migration:

$ goose create -type go AddSomeColumns
$ goose: created db/migrations/20130106093224_AddSomeColumns.go

up

Apply all available migrations.

$ goose up
$ goose: migrating db environment 'development', current version: 0, target: 3
$ OK    001_basics.sql
$ OK    002_next.sql
$ OK    003_and_again.go

option: pgschema

Use the pgschema flag with the up command specify a postgres schema.

$ goose -pgschema=my_schema_name up
$ goose: migrating db environment 'development', current version: 0, target: 3
$ OK    001_basics.sql
$ OK    002_next.sql
$ OK    003_and_again.go

down

Roll back a single migration from the current version.

$ goose down
$ goose: migrating db environment 'development', current version: 3, target: 2
$ OK    003_and_again.go

redo

Roll back the most recently applied migration, then run it again.

$ goose redo
$ goose: migrating db environment 'development', current version: 3, target: 2
$ OK    003_and_again.go
$ goose: migrating db environment 'development', current version: 2, target: 3
$ OK    003_and_again.go

status

Print the status of all migrations:

$ goose status
$ goose: status for environment 'development'
$   Applied At                  Migration
$   =======================================
$   Sun Jan  6 11:25:03 2013 -- 001_basics.sql
$   Sun Jan  6 11:25:03 2013 -- 002_next.sql
$   Pending                  -- 003_and_again.go

dbversion

Print the current version of the database:

$ goose dbversion
$ goose: dbversion 002

goose -h provides more detailed info on each command.

Migrations

goose supports migrations written in SQL or in Go - see the goose create command above for details on how to generate them.

SQL Migrations

A sample SQL migration looks like:

-- +goose Up
CREATE TABLE post (
    id int NOT NULL,
    title text,
    body text,
    PRIMARY KEY(id)
);

-- +goose Down
DROP TABLE post;

Notice the annotations in the comments. Any statements following -- +goose Up will be executed as part of a forward migration, and any statements following -- +goose Down will be executed as part of a rollback.

By default, SQL statements are delimited by semicolons - in fact, query statements must end with a semicolon to be properly recognized by goose.

More complex statements (PL/pgSQL) that have semicolons within them must be annotated with -- +goose StatementBegin and -- +goose StatementEnd to be properly recognized. For example:

-- +goose Up
-- +goose StatementBegin
CREATE OR REPLACE FUNCTION histories_partition_creation( DATE, DATE )
returns void AS $$
DECLARE
  create_query text;
BEGIN
  FOR create_query IN SELECT
      'CREATE TABLE IF NOT EXISTS histories_'
      || TO_CHAR( d, 'YYYY_MM' )
      || ' ( CHECK( created_at >= timestamp '''
      || TO_CHAR( d, 'YYYY-MM-DD 00:00:00' )
      || ''' AND created_at < timestamp '''
      || TO_CHAR( d + INTERVAL '1 month', 'YYYY-MM-DD 00:00:00' )
      || ''' ) ) inherits ( histories );'
    FROM generate_series( $1, $2, '1 month' ) AS d
  LOOP
    EXECUTE create_query;
  END LOOP;  -- LOOP END
END;         -- FUNCTION END
$$
language plpgsql;
-- +goose StatementEnd

Go Migrations

A sample Go migration looks like:

package main

import (
    "database/sql"
    "fmt"
)

func Up_20130106222315(txn *sql.Tx) {
    fmt.Println("Hello from migration 20130106222315 Up!")
}

func Down_20130106222315(txn *sql.Tx) {
    fmt.Println("Hello from migration 20130106222315 Down!")
}

Up_20130106222315() will be executed as part of a forward migration, and Down_20130106222315() will be executed as part of a rollback.

The numeric portion of the function name (20130106222315) must be the leading portion of migration's filename, such as 20130106222315_descriptive_name.go. goose create does this by default.

A transaction is provided, rather than the DB instance directly, since goose also needs to record the schema version within the same transaction. Each migration should run as a single transaction to ensure DB integrity, so it's good practice anyway.

Configuration

goose expects you to maintain a folder (typically called "db"), which contains the following:

  • a dbconf.yaml file that describes the database configurations you'd like to use
  • a folder called "migrations" which contains .sql and/or .go scripts that implement your migrations

You may use the -path option to specify an alternate location for the folder containing your config and migrations.

A sample dbconf.yml looks like

development:
    driver: postgres
    open: user=liam dbname=tester sslmode=disable

Here, development specifies the name of the environment, and the driver and open elements are passed directly to database/sql to access the specified database.

You may include as many environments as you like, and you can use the -env command line option to specify which one to use. goose defaults to using an environment called development.

The configuration may also be environment-less, with all fields at the top level. For example:

driver: postgres
open: user=liam dbname=tester sslmode=disable

You can even use a mixture of both. If a field is not specified within an environment, goose will fall back to looking at the top level.

You may also include environment variables in any field of the config. Specify them as $MY_ENV_VAR or ${MY_ENV_VAR}.

Configless

Goose can also run without a config file, by pulling all parameters from environment variables. This mode operates exactly as if you passed the following config file:

migrationsDir: $DB_MIGRATIONS_DIR
driver: $DB_DRIVER
import: $DB_DRIVER_IMPORT
dialect: $DB_DIALECT
open: $DB_DSN

Other Drivers

goose knows about some common SQL drivers, but it can still be used to run Go-based migrations with any driver supported by database/sql. An import path and known dialect are required.

Currently, available dialects are: "postgres", "mysql", "sqlite3", and "redshift"

To run Go-based migrations with another driver, specify its import path and dialect, as shown below.

myenv:
    driver: custom
    open: custom open string
    import: github.com/custom/driver
    dialect: mysql

NOTE: Because migrations written in SQL are executed directly by the goose binary, only drivers compiled into goose may be used for these migrations.

Using goose with Heroku

These instructions assume that you're using Keith Rarick's Heroku Go buildpack. First, add a file to your project called (e.g.) install_goose.go to trigger building of the goose executable during deployment, with these contents:

// use build constraints to work around http://code.google.com/p/go/issues/detail?id=4210
// +build heroku

// note: need at least one blank line after build constraint
package main

import _ "github.com/CloudCom/goose/cmd/goose"

Set up your Heroku database(s) as usual.

Then make use of environment variable expansion in your dbconf.yml:

production:
    driver: postgres
    open: $DATABASE_URL

To run goose in production, use heroku run:

heroku run goose -env production up

Contributors

Thank you!

  • Josh Bleecher Snyder (josharian)
  • Abigail Walthall (ghthor)
  • Daniel Heath (danielrheath)
  • Chris Baynes (chris_baynes)
  • Michael Gerow (gerow)
  • Vytautas Šaltenis (rtfb)
  • James Cooper (coopernurse)
  • Gyepi Sam (gyepisam)
  • Matt Sherman (clipperhouse)
  • runner_mei
  • John Luebs (jkl1337)
  • Luke Hutton (lukehutton)
  • Kevin Gorjan (kevingorjan)
  • Brendan Fosberry (Fozz)
  • Nate Guerin (gusennan)

goose's People

Contributors

abourget avatar chris-baynes avatar clipperhouse avatar danielheath avatar gyepisam avatar jkl1337 avatar josharian avatar kevingorjan avatar liamstask avatar lukehutton avatar mrgossett avatar oinume avatar parkr avatar phemmer avatar rubenv avatar shuhaowu avatar technosophos avatar tonkpils avatar vinibaggio avatar zabawaba99 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

goose's Issues

Should show specific statement that failed

When a migration fails, the output only shows the resulting error message. If the migration is running multiple statements, there's no way to know which one failed.

We should probably log the statement being executed.

Who is the maintainer ?

Are the folks at Cloud.com maintaining this project now ? There are several interesting PRs back at bitbucket.org .. and Liam over there doesn't seem to be taking great care of the project.

I have things I'd like to improve.. but I'm still looking for the canonical location to which to contribute. I'd be glad it's this place.. instead of trying to take it over.

Move lib/goose to root

we have cmd/goose and lib/goose, and nothing in the top level directory. One of the two should be in root. Probably lib/goose.

Get rid of DBConf.PgSchema

The OpenDBFromDBConf function uses the DBConf.PgSchema variable to execute a command setting a postgres client connection parameter when first initializing the sql.DB object. This is a bad idea as the connection parameter is only applied for that specific connection. Golang's sql.DB driver transparently uses multiple connections, and there's a chance that you can get a new connection where that parameter has not been set.

If a consumer of this package wants to set a client connection parameter, they are welcome to set it within the transaction code.

make `goose create` easier to use

Couple points here:

  • The default should be to create an SQL migration, not a GO migration.
  • Whether to create a GO or SQL migration should be controlled via a flag, not a bare argument. E.G.: goose create --type go foo_bar
  • Should have a way to launch $EDITOR. I personally favor launching $EDITOR automatically, just like git does for most of it's stuff. But I think a --edit flag would be acceptable. Also, if the editor exits without making a change to the file, the file should be automatically removed.

goose generate

We should have a goose generate command which generates a .go file with embedded configuration & migrations. Alleviating the need for loading files at runtime, and granting the ability to build a self-sufficient binary.

This might look like

goose generate -w goose.go -p main

Which would write goose.go, using package main.
If no output file is specified, write to STDOUT.
If no package is provided, we might default to main, or scan for other .go files in the destination directory, and use whatever package they are using.

The generated .go file should import the github.com/CloudCom/goose/lib/goose package, and not try to embed the entire goose library into the file. It should instead operate in a fashion such as:

var gooseMigrator *goose.Migrator

func init() {
  gooseMigrator = goose.NewMigrator(gooseConfig)
  gooseMigrator.AddMigration(migrationID, upFunc, downFunc)
}

migrationID would come from the migration file name.
In the case of a go migration (goose create -type=go foo), upFunc and downFunc would be the functions in that migration.
In the case of a sql migration (goose create -type=sql foo), upFunc and downFunc would be the sql file converted into go code.

The user's code would then call gooseMigrator.MigrateUp().


Once we have this capability, we can then provide a goose build command, which utilizes much of the above to build a standalone migrator binary.
This would mostly be taking github.com/CloudCom/goose/cmd/goose, and throwing the goose generate file in that package. The package can then look to see if the gooseMigrator variable has been set, and if so use it, otherwise do the standard runtime file loading.

fix tests fighting over shared database

The redshift tests will randomly fail because we trigger multiple travis jobs, and they all share the same DB.
The travis job should create a new database (not a new server, just a new db), and tear it down when done.

Looking for the best fork of Goose to use in production

Hey everyone - I've been trying to determine which fork of the original Goose project is the most maintained, preferably one that's already used in production. Would you advise using this fork or will the original become the standard since it looks like it's being maintained again. Thanks!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.