Skip to content

Commit dd13cf9

Browse files
author
Sergey Podgornyy
committed
Initial commit
0 parents  commit dd13cf9

26 files changed

+4398
-0
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
coverage.out
2+
tmp.out
3+
profile.out

.travis.yml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
language: go
2+
3+
matrix:
4+
fast_finish: true
5+
include:
6+
- go: 1.11.x
7+
env: GO111MODULE=on
8+
- go: 1.12.x
9+
env: GO111MODULE=on
10+
- go: 1.13.x
11+
- go: 1.13.x
12+
env:
13+
- TESTTAGS=nomsgpack
14+
- go: 1.14.x
15+
- go: 1.14.x
16+
env:
17+
- TESTTAGS=nomsgpack
18+
- go: master
19+
20+
git:
21+
depth: 10
22+
23+
before_install:
24+
- if [[ "${GO111MODULE}" = "on" ]]; then mkdir "${HOME}/go"; export GOPATH="${HOME}/go"; fi
25+
26+
install:
27+
- if [[ "${GO111MODULE}" = "on" ]]; then go mod download; fi
28+
- if [[ "${GO111MODULE}" = "on" ]]; then export PATH="${GOPATH}/bin:${GOROOT}/bin:${PATH}"; fi
29+
- if [[ "${GO111MODULE}" = "on" ]]; then make tools; fi
30+
31+
go_import_path: github.com/larapulse/migrator
32+
33+
script:
34+
- make vet
35+
- make fmt-check
36+
- make misspell-check
37+
- make test
38+
39+
after_success:
40+
- bash <(curl -s https://codecov.io/bash)

LICENSE.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
MIT License
2+
-----------
3+
4+
Copyright (c) 2020 Sergey Podgornyy (https://podgornyy.rocks)
5+
6+
Permission is hereby granted, free of charge, to any person
7+
obtaining a copy of this software and associated documentation
8+
files (the "Software"), to deal in the Software without
9+
restriction, including without limitation the rights to use,
10+
copy, modify, merge, publish, distribute, sublicense, and/or sell
11+
copies of the Software, and to permit persons to whom the
12+
Software is furnished to do so, subject to the following
13+
conditions:
14+
15+
The above copyright notice and this permission notice shall be
16+
included in all copies or substantial portions of the Software.
17+
18+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20+
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22+
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23+
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24+
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25+
OTHER DEALINGS IN THE SOFTWARE.

Makefile

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
GOFMT ?= gofmt "-s"
2+
PACKAGES ?= $(shell go list ./...)
3+
GOFILES := $(shell find . -name "*.go")
4+
TESTTAGS ?= ""
5+
6+
.PHONY: test
7+
test:
8+
echo "mode: count" > coverage.out
9+
for d in $(PACKAGES); do \
10+
go test -timeout 30s -tags $(TESTTAGS) -v -covermode=count -coverprofile=profile.out $$d > tmp.out; \
11+
cat tmp.out; \
12+
if grep -q "^--- FAIL" tmp.out; then \
13+
rm tmp.out; \
14+
exit 1; \
15+
elif grep -q "build failed" tmp.out; then \
16+
rm tmp.out; \
17+
exit 1; \
18+
elif grep -q "setup failed" tmp.out; then \
19+
rm tmp.out; \
20+
exit 1; \
21+
fi; \
22+
if [ -f profile.out ]; then \
23+
cat profile.out | grep -v "mode:" >> coverage.out; \
24+
rm profile.out; \
25+
fi; \
26+
done
27+
28+
.PHONY: fmt
29+
fmt:
30+
$(GOFMT) -w $(GOFILES)
31+
32+
.PHONY: fmt-check
33+
fmt-check:
34+
@diff=$$($(GOFMT) -d $(GOFILES)); \
35+
if [ -n "$$diff" ]; then \
36+
echo "Please run 'make fmt' and commit the result:"; \
37+
echo "$${diff}"; \
38+
exit 1; \
39+
fi;
40+
41+
vet:
42+
go vet $(PACKAGES)
43+
44+
.PHONY: lint
45+
lint:
46+
@hash golint > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
47+
go get -u golang.org/x/lint/golint; \
48+
fi
49+
for PKG in $(PACKAGES); do golint -set_exit_status $$PKG || exit 1; done;
50+
51+
.PHONY: misspell-check
52+
misspell-check:
53+
@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
54+
go get -u github.com/client9/misspell/cmd/misspell; \
55+
fi
56+
misspell -error $(GOFILES)
57+
58+
.PHONY: misspell
59+
misspell:
60+
@hash misspell > /dev/null 2>&1; if [ $$? -ne 0 ]; then \
61+
go get -u github.com/client9/misspell/cmd/misspell; \
62+
fi
63+
misspell -w $(GOFILES)
64+
65+
.PHONY: tools
66+
tools:
67+
go install golang.org/x/lint/golint; \
68+
go install github.com/client9/misspell/cmd/misspell;

README.md

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
# MySQL database migrator
2+
3+
<img align="right" width="159px" src="./logo.png">
4+
5+
[![Build Status](https://travis-ci.org/larapulse/migrator.svg)](https://travis-ci.org/larapulse/migrator)
6+
[![Software License](https://img.shields.io/badge/license-MIT-brightgreen.svg)](LICENSE.md)
7+
[![codecov](https://codecov.io/gh/larapulse/migrator/branch/master/graph/badge.svg)](https://codecov.io/gh/larapulse/migrator)
8+
[![Go Report Card](https://goreportcard.com/badge/github.com/larapulse/migrator)](https://goreportcard.com/report/github.com/larapulse/migrator)
9+
[![GoDoc](https://godoc.org/github.com/larapulse/migrator?status.svg)](https://pkg.go.dev/github.com/larapulse/migrator?tab=doc)
10+
[![Release](https://img.shields.io/github/release/larapulse/migrator.svg)](https://github.com/larapulse/migrator/releases)
11+
[![TODOs](https://badgen.net/https/api.tickgit.com/badgen/github.com/larapulse/migrator)](https://www.tickgit.com/browse?repo=github.com/larapulse/migrator)
12+
13+
MySQL database migrator designed to run migrations to your features and manage database schema update with intuitive go code. It is compatible with latest MySQL v8.
14+
15+
## Installation
16+
17+
To install `migrator` package, you need to install Go and set your Go workspace first.
18+
19+
1. The first need [Go](https://golang.org/) installed (**version 1.13+ is required**), then you can use the below Go command to install `migrator`.
20+
21+
```sh
22+
$ go get -u github.com/larapulse/migrator
23+
```
24+
25+
2. Import it in your code:
26+
27+
```go
28+
import "github.com/larapulse/migrator"
29+
```
30+
31+
## Quick start
32+
33+
Initialize migrator with migration entries:
34+
35+
```go
36+
var migrations = []migrator.Migration{
37+
{
38+
Name: "19700101_0001_create_posts_table",
39+
Up: func() migrator.Schema {
40+
var s migrator.Schema
41+
posts := migrator.Table{Name: "posts"}
42+
43+
posts.UniqueID("id")
44+
posts.Column("title", migrator.String{Precision: 64})
45+
posts.Column("content", migrator.Text{})
46+
posts.Timestamps()
47+
48+
s.CreateTable(posts)
49+
50+
return s
51+
},
52+
Down: func() migrator.Schema {
53+
var s migrator.Schema
54+
55+
s.DropTable("posts")
56+
57+
return s
58+
},
59+
},
60+
{
61+
Name: "19700101_0002_create_comments_table",
62+
Up: func() migrator.Schema {
63+
var s migrator.Schema
64+
comments := migrator.Table{Name: "comments"}
65+
66+
comments.UniqueID("id")
67+
comments.UUID("post_id", "", false)
68+
comments.Column("title", migrator.String{Precision: 64})
69+
comments.Column("content", migrator.Text{})
70+
comments.Timestamps()
71+
72+
comments.Foreign("post_id", "id", "posts", "RESTRICT", "RESTRICT")
73+
74+
s.CreateTable(comments)
75+
76+
return s
77+
},
78+
Down: func() migrator.Schema {
79+
var s migrator.Schema
80+
81+
s.DropTable("comments")
82+
83+
return s
84+
},
85+
},
86+
}
87+
88+
m := migrator.Migrator{Pool: migrations}
89+
migrated, err = m.Migrate(db)
90+
91+
if err != nil {
92+
fmt.Errorf("Could not migrate: %v", err)
93+
os.Exit(1)
94+
}
95+
96+
if len(migrated) == 0 {
97+
fmt.Println("Nothing were migrated.")
98+
}
99+
100+
for _, m := range migrated {
101+
fmt.Println("Migration: "+m+" was migrated ✅")
102+
}
103+
104+
fmt.Println("Migration did run successfully")
105+
```
106+
107+
After first migration run, `migrations` table will be created:
108+
109+
```
110+
+----+-------------------------------------+-------+---------------------+
111+
| id | name | batch | applied_at |
112+
+----+-------------------------------------+-------+---------------------+
113+
| 1 | 19700101_0001_create_posts_table | 1 | 2020-06-27 00:00:00 |
114+
| 2 | 19700101_0002_create_comments_table | 1 | 2020-06-27 00:00:00 |
115+
+----+-------------------------------------+-------+---------------------+
116+
```
117+
118+
If you want to use another name for migration table, change it `Migrator` before running migrations:
119+
120+
```go
121+
m := migrator.Migrator{TableName: "_my_app_migrations"}
122+
```
123+
124+
### Transactional migration
125+
126+
In case you have multiple commands within one migration and you want to be sure it is migrated properly, you might enable transactional execution per migration:
127+
128+
```go
129+
var migration = migrator.Migration{
130+
Name: "19700101_0001_create_posts_and_users_tables",
131+
Up: func() migrator.Schema {
132+
var s migrator.Schema
133+
posts := migrator.Table{Name: "posts"}
134+
posts.UniqueID("id")
135+
posts.Timestamps()
136+
137+
users := migrator.Table{Name: "users"}
138+
users.UniqueID("id")
139+
users.Timestamps()
140+
141+
s.CreateTable(posts)
142+
s.CreateTable(users)
143+
144+
return s
145+
},
146+
Down: func() migrator.Schema {
147+
var s migrator.Schema
148+
149+
s.DropTable("users")
150+
s.DropTable("posts")
151+
152+
return s
153+
},
154+
Transaction: true,
155+
}
156+
```
157+
158+
### Rollback and revert
159+
160+
In case you need to revert your deploy and DB, you can revert last migrated batch:
161+
162+
```go
163+
m := migrator.Migrator{Pool: migrations}
164+
reverted, err := m.Rollback(db)
165+
166+
if err != nil {
167+
fmt.Errorf("Could not roll back migrations: %v", err)
168+
os.Exit(1)
169+
}
170+
171+
if len(reverted) == 0 {
172+
fmt.Println("Nothing were rolled back.")
173+
}
174+
175+
for _, m := range reverted {
176+
fmt.Println("Migration: "+m+" was rolled back ✅")
177+
}
178+
```
179+
180+
To revert all migrated items back, you have to call `Revert()` on your `migrator`:
181+
182+
```go
183+
m := migrator.Migrator{Pool: migrations}
184+
reverted, err := m.Revert(db)
185+
```
186+
187+
## Customize queries
188+
189+
You may add any column definition to the database on your own, just be sure you implement `columnType` interface:
190+
191+
```go
192+
type customType string
193+
194+
func (ct customType) buildRow() string {
195+
return string(ct)
196+
}
197+
198+
posts := migrator.Table{Name: "posts"}
199+
posts.UniqueID("id")
200+
posts.Column("data", customType("json not null"))
201+
posts.Timestamps()
202+
```
203+
204+
Same logic is for adding custom commands to the Schema to be migrated or reverted, just be sure you implement `command` interface:
205+
206+
```go
207+
type customCommand string
208+
209+
func (cc customCommand) toSQL() string {
210+
return string(cc)
211+
}
212+
213+
var s migrator.Schema
214+
215+
c := customCommand("DROP PROCEDURE abc")
216+
s.CustomCommand(c)
217+
```

0 commit comments

Comments
 (0)