Skip to content

Commit

Permalink
Separate cmd package for easier importing
Browse files Browse the repository at this point in the history
  • Loading branch information
amacneil committed Apr 24, 2017
1 parent 247d729 commit d3bd60c
Show file tree
Hide file tree
Showing 21 changed files with 407 additions and 367 deletions.
1 change: 1 addition & 0 deletions .agignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/vendor
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
/dist
.DS_Store
dbmate
dist
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM golang:1.8.0
FROM golang:1.8

# required to force cgo (for sqlite driver) with cross compile
ENV CGO_ENABLED 1
Expand All @@ -19,6 +19,6 @@ COPY . $GOPATH/src/github.com/amacneil/dbmate
WORKDIR $GOPATH/src/github.com/amacneil/dbmate

# build
RUN go install -v
RUN go install -v ./cmd/dbmate

CMD dbmate
17 changes: 9 additions & 8 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
DC := docker-compose
BUILD_FLAGS := -ldflags '-s'
PACKAGES := . ./cmd/dbmate

all: clean container lint test build
all: clean container test lint build

clean:
rm -rf dist
Expand All @@ -12,15 +13,15 @@ container:
$(DC) up -d

lint:
$(DC) run dbmate golint
$(DC) run dbmate go vet
$(DC) run dbmate errcheck
$(DC) run dbmate golint -set_exit_status $(PACKAGES)
$(DC) run dbmate go vet $(PACKAGES)
$(DC) run dbmate errcheck $(PACKAGES)

test:
$(DC) run dbmate go test -v
$(DC) run dbmate go test -v $(PACKAGES)

build: clean
$(DC) run -e GOARCH=386 dbmate go build $(BUILD_FLAGS) -o dist/dbmate-linux-i386
$(DC) run -e GOARCH=amd64 dbmate go build $(BUILD_FLAGS) -o dist/dbmate-linux-amd64
$(DC) run -e GOARCH=386 dbmate go build $(BUILD_FLAGS) -o dist/dbmate-linux-i386 ./cmd/dbmate
$(DC) run -e GOARCH=amd64 dbmate go build $(BUILD_FLAGS) -o dist/dbmate-linux-amd64 ./cmd/dbmate
# musl target does not support sqlite
$(DC) run -e GOARCH=amd64 -e CGO_ENABLED=0 dbmate go build $(BUILD_FLAGS) -o dist/dbmate-linux-musl-amd64
$(DC) run -e GOARCH=amd64 -e CGO_ENABLED=0 dbmate go build $(BUILD_FLAGS) -o dist/dbmate-linux-musl-amd64 ./cmd/dbmate
127 changes: 127 additions & 0 deletions cmd/dbmate/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package main

import (
"fmt"
"log"
"net/url"
"os"

"github.com/amacneil/dbmate"
"github.com/joho/godotenv"
"github.com/urfave/cli"
)

func main() {
loadDotEnv()

app := NewApp()
err := app.Run(os.Args)
if err != nil {
fmt.Fprintf(os.Stderr, "Error: %s\n", err)
os.Exit(1)
}
}

// NewApp creates a new command line app
func NewApp() *cli.App {
app := cli.NewApp()
app.Name = "dbmate"
app.Usage = "A lightweight, framework-independent database migration tool."
app.Version = dbmate.Version

app.Flags = []cli.Flag{
cli.StringFlag{
Name: "migrations-dir, d",
Value: dbmate.DefaultMigrationsDir,
Usage: "specify the directory containing migration files",
},
cli.StringFlag{
Name: "env, e",
Value: "DATABASE_URL",
Usage: "specify an environment variable containing the database URL",
},
}

app.Commands = []cli.Command{
{
Name: "new",
Aliases: []string{"n"},
Usage: "Generate a new migration file",
Action: action(func(db *dbmate.DB, c *cli.Context) error {
name := c.Args().First()
return db.New(name)
}),
},
{
Name: "up",
Usage: "Create database (if necessary) and migrate to the latest version",
Action: action(func(db *dbmate.DB, c *cli.Context) error {
return db.Up()
}),
},
{
Name: "create",
Usage: "Create database",
Action: action(func(db *dbmate.DB, c *cli.Context) error {
return db.Create()
}),
},
{
Name: "drop",
Usage: "Drop database (if it exists)",
Action: action(func(db *dbmate.DB, c *cli.Context) error {
return db.Drop()
}),
},
{
Name: "migrate",
Usage: "Migrate to the latest version",
Action: action(func(db *dbmate.DB, c *cli.Context) error {
return db.Migrate()
}),
},
{
Name: "rollback",
Aliases: []string{"down"},
Usage: "Rollback the most recent migration",
Action: action(func(db *dbmate.DB, c *cli.Context) error {
return db.Rollback()
}),
},
}

return app
}

// load environment variables from .env file
func loadDotEnv() {
if _, err := os.Stat(".env"); err != nil {
return
}

if err := godotenv.Load(); err != nil {
log.Fatal("Error loading .env file")
}
}

// action wraps a cli.ActionFunc with dbmate initialization logic
func action(f func(*dbmate.DB, *cli.Context) error) cli.ActionFunc {
return func(c *cli.Context) error {
u, err := getDatabaseURL(c)
if err != nil {
return err
}
db := dbmate.NewDB(u)
db.MigrationsDir = c.GlobalString("migrations-dir")

return f(db, c)
}
}

// getDatabaseURL returns the current environment database url
func getDatabaseURL(c *cli.Context) (u *url.URL, err error) {
env := c.GlobalString("env")
value := os.Getenv(env)

return url.Parse(value)
}
39 changes: 39 additions & 0 deletions cmd/dbmate/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package main

import (
"flag"
"net/url"
"os"
"testing"

"github.com/stretchr/testify/require"
"github.com/urfave/cli"
)

func testContext(t *testing.T, u *url.URL) *cli.Context {
var err error

err = os.Setenv("DATABASE_URL", u.String())
require.Nil(t, err)

app := NewApp()
flagset := flag.NewFlagSet(app.Name, flag.ContinueOnError)
for _, f := range app.Flags {
f.Apply(flagset)
}

return cli.NewContext(app, flagset, nil)
}

func TestGetDatabaseUrl(t *testing.T) {
envURL, err := url.Parse("foo://example.org/db")
require.Nil(t, err)
ctx := testContext(t, envURL)

u, err := getDatabaseURL(ctx)
require.Nil(t, err)

require.Equal(t, "foo", u.Scheme)
require.Equal(t, "example.org", u.Host)
require.Equal(t, "/db", u.Path)
}
169 changes: 0 additions & 169 deletions commands_test.go

This file was deleted.

Loading

0 comments on commit d3bd60c

Please sign in to comment.