Skip to content

Commit 8917d66

Browse files
zeripathtechknowlogick
authored andcommitted
Add migration test (#5773)
* Add migration test This commit adds a simple migration test for v1.5.3, v1.6.4 and v1.7.0-rc3 Signed-off-by: Andrew Thornton <[email protected]> * Automigrate based on available dbs * remove old ini file * Standardise the dialect names
1 parent bc748f2 commit 8917d66

12 files changed

+277
-1
lines changed

.drone.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ pipeline:
127127
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
128128
- apt-get install -y git-lfs
129129
- (sleep 1200 && (echo 'kill -ABRT $(pidof gitea) $(pidof integrations.sqlite.test)' | sh)) &
130+
- make test-sqlite-migration
130131
- make test-sqlite
131132
when:
132133
event: [ push, tag, pull_request ]
@@ -141,6 +142,7 @@ pipeline:
141142
commands:
142143
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
143144
- apt-get install -y git-lfs
145+
- make test-mysql-migration
144146
- make integration-test-coverage
145147
when:
146148
event: [ push, pull_request ]
@@ -157,6 +159,7 @@ pipeline:
157159
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
158160
- apt-get install -y git-lfs
159161
- (sleep 1200 && (echo 'kill -ABRT $(pidof gitea) $(pidof integrations.test)' | sh)) &
162+
- make test-mysql-migration
160163
- make test-mysql
161164
when:
162165
event: [ tag ]
@@ -172,6 +175,7 @@ pipeline:
172175
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
173176
- apt-get install -y git-lfs
174177
- (sleep 1200 && (echo 'kill -ABRT $(pidof gitea) $(pidof integrations.test)' | sh)) &
178+
- make test-pgsql-migration
175179
- make test-pgsql
176180
when:
177181
event: [ push, tag, pull_request ]
@@ -186,6 +190,7 @@ pipeline:
186190
commands:
187191
- curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
188192
- apt-get install -y git-lfs
193+
- make test-mssql-migration
189194
- make test-mssql
190195
when:
191196
event: [ push, tag, pull_request ]

Makefile

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ endif
3535

3636
LDFLAGS := -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
3737

38-
PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations,$(shell $(GO) list ./... | grep -v /vendor/))
38+
PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(filter-out code.gitea.io/gitea/integrations,$(shell $(GO) list ./... | grep -v /vendor/)))
3939
SOURCES ?= $(shell find . -name "*.go" -type f)
4040

4141
TAGS ?=
@@ -197,6 +197,10 @@ test-vendor: vendor
197197
test-sqlite: integrations.sqlite.test
198198
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test
199199

200+
.PHONY: test-sqlite-migration
201+
test-sqlite-migration: migrations.sqlite.test
202+
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./migrations.sqlite.test
203+
200204
generate-ini:
201205
sed -e 's|{{TEST_MYSQL_HOST}}|${TEST_MYSQL_HOST}|g' \
202206
-e 's|{{TEST_MYSQL_DBNAME}}|${TEST_MYSQL_DBNAME}|g' \
@@ -218,14 +222,28 @@ generate-ini:
218222
test-mysql: integrations.test generate-ini
219223
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql.ini ./integrations.test
220224

225+
.PHONY: test-mysql-migration
226+
test-mysql-migration: migrations.test generate-ini
227+
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mysql.ini ./migrations.test
228+
221229
.PHONY: test-pgsql
222230
test-pgsql: integrations.test generate-ini
223231
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./integrations.test
224232

233+
.PHONY: test-pgsql-migration
234+
test-pgsql-migration: migrations.test generate-ini
235+
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/pgsql.ini ./migrations.test
236+
237+
225238
.PHONY: test-mssql
226239
test-mssql: integrations.test generate-ini
227240
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mssql.ini ./integrations.test
228241

242+
.PHONY: test-mssql-migration
243+
test-mssql-migration: migrations.test generate-ini
244+
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/mssql.ini ./migrations.test
245+
246+
229247
.PHONY: bench-sqlite
230248
bench-sqlite: integrations.sqlite.test
231249
GITEA_ROOT=${CURDIR} GITEA_CONF=integrations/sqlite.ini ./integrations.sqlite.test -test.cpuprofile=cpu.out -test.run DontRunTests -test.bench .
@@ -252,6 +270,14 @@ integrations.sqlite.test: $(SOURCES)
252270
integrations.cover.test: $(SOURCES)
253271
$(GO) test -c code.gitea.io/gitea/integrations -coverpkg $(shell echo $(PACKAGES) | tr ' ' ',') -o integrations.cover.test
254272

273+
.PHONY: migrations.test
274+
migrations.test: $(SOURCES)
275+
$(GO) test -c code.gitea.io/gitea/integrations/migration-test -o migrations.test
276+
277+
.PHONY: migrations.sqlite.test
278+
migrations.sqlite.test: $(SOURCES)
279+
$(GO) test -c code.gitea.io/gitea/integrations/migration-test -o migrations.sqlite.test -tags 'sqlite sqlite_unlock_notify'
280+
255281
.PHONY: check
256282
check: test
257283

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
// Copyright 2019 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package migrations
6+
7+
import (
8+
"compress/gzip"
9+
"database/sql"
10+
"fmt"
11+
"io/ioutil"
12+
"log"
13+
"os"
14+
"path"
15+
"regexp"
16+
"sort"
17+
"testing"
18+
19+
"code.gitea.io/gitea/models"
20+
"code.gitea.io/gitea/models/migrations"
21+
"code.gitea.io/gitea/modules/setting"
22+
23+
"github.com/go-xorm/xorm"
24+
"github.com/stretchr/testify/assert"
25+
)
26+
27+
var currentEngine *xorm.Engine
28+
29+
func initMigrationTest() {
30+
giteaRoot := os.Getenv("GITEA_ROOT")
31+
if giteaRoot == "" {
32+
fmt.Println("Environment variable $GITEA_ROOT not set")
33+
os.Exit(1)
34+
}
35+
setting.AppPath = path.Join(giteaRoot, "gitea")
36+
if _, err := os.Stat(setting.AppPath); err != nil {
37+
fmt.Printf("Could not find gitea binary at %s\n", setting.AppPath)
38+
os.Exit(1)
39+
}
40+
41+
giteaConf := os.Getenv("GITEA_CONF")
42+
if giteaConf == "" {
43+
fmt.Println("Environment variable $GITEA_CONF not set")
44+
os.Exit(1)
45+
} else if !path.IsAbs(giteaConf) {
46+
setting.CustomConf = path.Join(giteaRoot, giteaConf)
47+
} else {
48+
setting.CustomConf = giteaConf
49+
}
50+
51+
setting.NewContext()
52+
setting.CheckLFSVersion()
53+
models.LoadConfigs()
54+
}
55+
56+
func getDialect() string {
57+
dialect := "sqlite"
58+
switch {
59+
case setting.UseSQLite3:
60+
dialect = "sqlite"
61+
case setting.UseMySQL:
62+
dialect = "mysql"
63+
case setting.UsePostgreSQL:
64+
dialect = "pgsql"
65+
case setting.UseMSSQL:
66+
dialect = "mssql"
67+
}
68+
return dialect
69+
}
70+
71+
func availableVersions() ([]string, error) {
72+
migrationsDir, err := os.Open("integrations/migration-test")
73+
if err != nil {
74+
return nil, err
75+
}
76+
defer migrationsDir.Close()
77+
versionRE, err := regexp.Compile("gitea-v(?P<version>.+)\\." + regexp.QuoteMeta(models.DbCfg.Type) + "\\.sql.gz")
78+
if err != nil {
79+
return nil, err
80+
}
81+
82+
filenames, err := migrationsDir.Readdirnames(-1)
83+
if err != nil {
84+
return nil, err
85+
}
86+
versions := []string{}
87+
for _, filename := range filenames {
88+
if versionRE.MatchString(filename) {
89+
substrings := versionRE.FindStringSubmatch(filename)
90+
versions = append(versions, substrings[1])
91+
}
92+
}
93+
sort.Strings(versions)
94+
return versions, nil
95+
}
96+
97+
func readSQLFromFile(version string) (string, error) {
98+
filename := fmt.Sprintf("integrations/migration-test/gitea-v%s.%s.sql.gz", version, models.DbCfg.Type)
99+
100+
if _, err := os.Stat(filename); os.IsNotExist(err) {
101+
return "", nil
102+
}
103+
104+
file, err := os.Open(filename)
105+
if err != nil {
106+
return "", err
107+
}
108+
defer file.Close()
109+
110+
gr, err := gzip.NewReader(file)
111+
if err != nil {
112+
return "", err
113+
}
114+
defer gr.Close()
115+
116+
bytes, err := ioutil.ReadAll(gr)
117+
if err != nil {
118+
return "", err
119+
}
120+
121+
return string(bytes), nil
122+
}
123+
124+
func restoreOldDB(t *testing.T, version string) bool {
125+
data, err := readSQLFromFile(version)
126+
assert.NoError(t, err)
127+
if len(data) == 0 {
128+
log.Printf("No db found to restore for %s version: %s\n", models.DbCfg.Type, version)
129+
return false
130+
}
131+
132+
switch {
133+
case setting.UseSQLite3:
134+
os.Remove(models.DbCfg.Path)
135+
err := os.MkdirAll(path.Dir(models.DbCfg.Path), os.ModePerm)
136+
assert.NoError(t, err)
137+
138+
db, err := sql.Open("sqlite3", fmt.Sprintf("file:%s?cache=shared&mode=rwc&_busy_timeout=%d", models.DbCfg.Path, models.DbCfg.Timeout))
139+
assert.NoError(t, err)
140+
defer db.Close()
141+
142+
_, err = db.Exec(data)
143+
assert.NoError(t, err)
144+
db.Close()
145+
146+
case setting.UseMySQL:
147+
db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/",
148+
models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host))
149+
assert.NoError(t, err)
150+
defer db.Close()
151+
152+
_, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", models.DbCfg.Name))
153+
assert.NoError(t, err)
154+
155+
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE IF NOT EXISTS %s", models.DbCfg.Name))
156+
assert.NoError(t, err)
157+
158+
db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?multiStatements=true",
159+
models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.Name))
160+
assert.NoError(t, err)
161+
defer db.Close()
162+
163+
_, err = db.Exec(data)
164+
assert.NoError(t, err)
165+
db.Close()
166+
167+
case setting.UsePostgreSQL:
168+
db, err := sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/?sslmode=%s",
169+
models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.SSLMode))
170+
assert.NoError(t, err)
171+
defer db.Close()
172+
173+
_, err = db.Exec(fmt.Sprintf("DROP DATABASE IF EXISTS %s", models.DbCfg.Name))
174+
assert.NoError(t, err)
175+
176+
_, err = db.Exec(fmt.Sprintf("CREATE DATABASE %s", models.DbCfg.Name))
177+
assert.NoError(t, err)
178+
db.Close()
179+
180+
db, err = sql.Open("postgres", fmt.Sprintf("postgres://%s:%s@%s/%s?sslmode=%s",
181+
models.DbCfg.User, models.DbCfg.Passwd, models.DbCfg.Host, models.DbCfg.Name, models.DbCfg.SSLMode))
182+
assert.NoError(t, err)
183+
defer db.Close()
184+
185+
_, err = db.Exec(data)
186+
assert.NoError(t, err)
187+
db.Close()
188+
189+
case setting.UseMSSQL:
190+
host, port := models.ParseMSSQLHostPort(models.DbCfg.Host)
191+
db, err := sql.Open("mssql", fmt.Sprintf("server=%s; port=%s; database=%s; user id=%s; password=%s;",
192+
host, port, "master", models.DbCfg.User, models.DbCfg.Passwd))
193+
assert.NoError(t, err)
194+
defer db.Close()
195+
196+
_, err = db.Exec("DROP DATABASE IF EXISTS gitea")
197+
assert.NoError(t, err)
198+
199+
_, err = db.Exec("CREATE DATABASE gitea")
200+
assert.NoError(t, err)
201+
202+
_, err = db.Exec(data)
203+
assert.NoError(t, err)
204+
db.Close()
205+
}
206+
return true
207+
}
208+
209+
func wrappedMigrate(x *xorm.Engine) error {
210+
currentEngine = x
211+
return migrations.Migrate(x)
212+
}
213+
214+
func doMigrationTest(t *testing.T, version string) {
215+
log.Printf("Performing migration test for %s version: %s", models.DbCfg.Type, version)
216+
if !restoreOldDB(t, version) {
217+
return
218+
}
219+
220+
setting.NewXORMLogService(false)
221+
err := models.SetEngine()
222+
assert.NoError(t, err)
223+
224+
err = models.NewEngine(wrappedMigrate)
225+
assert.NoError(t, err)
226+
currentEngine.Close()
227+
}
228+
229+
func TestMigrations(t *testing.T) {
230+
initMigrationTest()
231+
232+
dialect := models.DbCfg.Type
233+
versions, err := availableVersions()
234+
assert.NoError(t, err)
235+
236+
if len(versions) == 0 {
237+
log.Printf("No old database versions available to migration test for %s\n", dialect)
238+
return
239+
}
240+
241+
log.Printf("Preparing to test %d migrations for %s\n", len(versions), dialect)
242+
for _, version := range versions {
243+
doMigrationTest(t, version)
244+
}
245+
}

0 commit comments

Comments
 (0)