From 35dc7abfae2a046d59abb9a3b90d82d6e86b30f4 Mon Sep 17 00:00:00 2001 From: Sung Won Cho Date: Sat, 29 Jun 2019 12:31:42 +1000 Subject: [PATCH] Server migration (#214) * Allow to run server side postgres migration * Automate migration creation * Check if sql-migrate exists --- Gopkg.lock | 20 ++++++++ Gopkg.toml | 4 ++ Makefile | 10 ++++ pkg/server/api/.env.dev | 2 +- pkg/server/database/migrate.yml | 8 ++++ pkg/server/database/migrate/main.go | 46 +++++++++++++++++++ .../database/scripts/create-migration.sh | 21 +++++++++ .../database/scripts/install-sql-migrate.sh | 3 ++ 8 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 pkg/server/database/migrate.yml create mode 100644 pkg/server/database/migrate/main.go create mode 100755 pkg/server/database/scripts/create-migration.sh create mode 100755 pkg/server/database/scripts/install-sql-migrate.sh diff --git a/Gopkg.lock b/Gopkg.lock index ae4e6b18..b50d93d1 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -206,6 +206,17 @@ revision = "b41be1df696709bb6395fe435af20370037c0b4c" version = "v1.2.0" +[[projects]] + branch = "master" + digest = "1:83eb06141fc25c7fd89f8b39717962ac930a7480796aab3d46c7e88507a69173" + name = "github.com/rubenv/sql-migrate" + packages = [ + ".", + "sqlparse", + ] + pruneopts = "UT" + revision = "f4d34eae5a5cf210693e81c604e6bac5f6727927" + [[projects]] digest = "1:274f67cb6fed9588ea2521ecdac05a6d62a8c51c074c1fccc6a49a40ba80e925" name = "github.com/satori/go.uuid" @@ -351,6 +362,14 @@ revision = "41f3572897373c5538c50a2402db15db079fa4fd" version = "2.0.0" +[[projects]] + digest = "1:1b36b0cb56126316f637ad55cfd5ed84c945fe45bd90e944666b4107a80a1da9" + name = "gopkg.in/gorp.v1" + packages = ["."] + pruneopts = "UT" + revision = "6a667da9c028871f98598d85413e3fc4c6daa52e" + version = "v1.7.2" + [[projects]] digest = "1:4d2e5a73dc1500038e504a8d78b986630e3626dc027bc030ba5c75da257cdb96" name = "gopkg.in/yaml.v2" @@ -380,6 +399,7 @@ "github.com/mattn/go-sqlite3", "github.com/pkg/errors", "github.com/robfig/cron", + "github.com/rubenv/sql-migrate", "github.com/satori/go.uuid", "github.com/sergi/go-diff/diffmatchpatch", "github.com/spf13/cobra", diff --git a/Gopkg.toml b/Gopkg.toml index 9b1c5b44..11322922 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -116,3 +116,7 @@ [prune] go-tests = true unused-packages = true + +[[constraint]] + revision = "f4d34eae5a5cf210693e81c604e6bac5f6727927" + name = "github.com/rubenv/sql-migrate" diff --git a/Makefile b/Makefile index 77b56780..cb6e2fef 100644 --- a/Makefile +++ b/Makefile @@ -58,3 +58,13 @@ build-dev-cli: @echo "==> building dev cli" @${GOPATH}/src/github.com/dnote/dnote/pkg/cli/scripts/dev.sh .PHONY: build-dev-cli + +## migrate +migrate: +ifndef GO_ENV + $(error "environment variable GO_ENV is required.") +endif + + @echo "==> running migrations" + @(cd ${GOPATH}/src/github.com/dnote/dnote/pkg/server/database/migrate && go run *.go --migrationDir ../migrations) +.PHONY: migrate diff --git a/pkg/server/api/.env.dev b/pkg/server/api/.env.dev index 976dcecd..356e7dac 100644 --- a/pkg/server/api/.env.dev +++ b/pkg/server/api/.env.dev @@ -4,7 +4,7 @@ WebPort=3000 GO_ENV=DEVELOPMENT DB_HOST=localhost -POSTGRES_DB=dnote_test +POSTGRES_DB=dnote POSTGRES_USER=sung SmtpUsername=mock-SmtpUsername diff --git a/pkg/server/database/migrate.yml b/pkg/server/database/migrate.yml new file mode 100644 index 00000000..fa4ddb1b --- /dev/null +++ b/pkg/server/database/migrate.yml @@ -0,0 +1,8 @@ +# a configuration for sql-migrate tool. We don't need to configure production, +# because we programmatically connect to the database and run migrations. +# Its main purpose is to generate migrations using `sql-migrate new` + +development: + dialect: postgres + datasource: dbname=dnote sslmode=disable + dir: ./migrations diff --git a/pkg/server/database/migrate/main.go b/pkg/server/database/migrate/main.go new file mode 100644 index 00000000..ce132687 --- /dev/null +++ b/pkg/server/database/migrate/main.go @@ -0,0 +1,46 @@ +package main + +import ( + "flag" + "fmt" + "os" + + "github.com/dnote/dnote/pkg/server/database" + "github.com/joho/godotenv" + "github.com/pkg/errors" + "github.com/rubenv/sql-migrate" +) + +var ( + migrationDir = flag.String("migrationDir", "../migrations", "the path to the directory with migraiton files") +) + +func init() { + fmt.Println("Migrating Dnote database...") + + // Load env + if os.Getenv("GO_ENV") != "PRODUCTION" { + if err := godotenv.Load("../../api/.env.dev"); err != nil { + panic(err) + } + } + + database.InitDB() +} + +func main() { + flag.Parse() + + db := database.DBConn + + migrations := &migrate.FileMigrationSource{ + Dir: *migrationDir, + } + + n, err := migrate.Exec(db.DB(), "postgres", migrations, migrate.Up) + if err != nil { + panic(errors.Wrap(err, "executing migrations")) + } + + fmt.Printf("Applied %d migrations\n", n) +} diff --git a/pkg/server/database/scripts/create-migration.sh b/pkg/server/database/scripts/create-migration.sh new file mode 100755 index 00000000..e45af691 --- /dev/null +++ b/pkg/server/database/scripts/create-migration.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# create-migration.sh creates a new SQL migration file for the +# server side Postgres database using the sql-migrate tool. +set -eux + +is_command () { + command -v "$1" >/dev/null 2>&1; +} + +if ! is_command sql-migrate; then + echo "sql-migrate is not found. Please run install-sql-migrate.sh" + exit 1 +fi + +if [ "$#" == 0 ]; then + echo "filename not provided" + exit 1 +fi + +filename=$1 +sql-migrate new -config=migrate.yml "$filename" diff --git a/pkg/server/database/scripts/install-sql-migrate.sh b/pkg/server/database/scripts/install-sql-migrate.sh new file mode 100755 index 00000000..73938dac --- /dev/null +++ b/pkg/server/database/scripts/install-sql-migrate.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +go get -v github.com/rubenv/sql-migrate/...