3
0

add(sam): migrations code start

This commit is contained in:
Tit Petric
2018-10-02 16:22:52 +02:00
parent d5f1e50b0f
commit d54aae2e4b
3 changed files with 122 additions and 0 deletions

80
sam/db/migrate.go Normal file
View File

@@ -0,0 +1,80 @@
package db
import (
"fmt"
"log"
"os"
"regexp"
"sort"
_ "github.com/crusttech/crust/sam/db/mysql"
"github.com/pkg/errors"
"github.com/rakyll/statik/fs"
"github.com/titpetric/factory"
)
//go:generate statik -p mysql -Z -f -src=schema/mysql
func statements(contents []byte, err error) ([]string, error) {
if err != nil {
return []string{}, err
}
return regexp.MustCompilePOSIX(";$").Split(string(contents), -1), nil
}
func Migrate(db *factory.DB) error {
statikFS, err := fs.New()
if err != nil {
return errors.Wrap(err, "Error creating statik filesystem")
}
var files []string
fs.Walk(statikFS, "/", func(filename string, info os.FileInfo, err error) error {
if len(filename) > 4 && filename[len(filename)-4:] == ".sql" {
files = append(files, filename)
}
return nil
})
sort.Strings(files)
if len(files) == 0 {
return errors.New("No files encoded for migration, need at least one SQL file")
}
// @todo: create table migrations by hand, log each filename status/date
/*
create table if not exists migrations (
filename string, status [ok, fail], message string (may be error text?), stamp datetime
)
*/
for _, filename := range files {
// @todo: select * from migrations to check if (filename) was processed, skip if yes
stmts, err := statements(fs.ReadFile(statikFS, filename))
if err != nil {
return errors.Wrap(err, fmt.Sprintf("Error applying migration %s", filename))
}
up := func() error {
log.Println("Running migration for", filename)
for _, query := range stmts {
if _, err := db.Exec(query); err != nil {
return err
}
}
log.Println("Migration done OK")
// @todo: insert/update into migrations with (filename)
return nil
}
if err := db.Transaction(up); err != nil {
return err
}
}
return nil
}

30
sam/db/migrate_test.go Normal file
View File

@@ -0,0 +1,30 @@
package db
import (
"testing"
"github.com/joho/godotenv"
"github.com/namsral/flag"
"github.com/titpetric/factory"
"github.com/crusttech/crust/internal/config"
)
func TestMigrations(t *testing.T) {
// @todo this is a very optimistic initialization, make it more robust
godotenv.Load("../../.env")
dbConfig := new(config.Database).Init("sam")
flag.Parse()
if err := dbConfig.Validate(); err != nil {
t.Fatalf("Error in database config: %+v", err)
}
factory.Database.Add("default", dbConfig.DSN)
db := factory.Database.MustGet()
if err := Migrate(db); err != nil {
t.Fatalf("Unexpected error: %#v", err)
}
}

12
sam/db/mysql/statik.go Normal file

File diff suppressed because one or more lines are too long