mirror of https://github.com/status-im/migrate.git
Merge remote-tracking branch 'origin/master' into postgres-lock-fix
This commit is contained in:
commit
ab7dfb38ac
|
@ -4,3 +4,4 @@ cli/cli
|
|||
cli/migrate
|
||||
.coverage
|
||||
.godoc.pid
|
||||
vendor/
|
44
.travis.yml
44
.travis.yml
|
@ -2,46 +2,53 @@ language: go
|
|||
sudo: required
|
||||
|
||||
go:
|
||||
- 1.7
|
||||
- 1.8
|
||||
- 1.9
|
||||
- 1.9.1
|
||||
- 1.9.2
|
||||
- "1.9.x"
|
||||
- "1.10"
|
||||
|
||||
env:
|
||||
- MIGRATE_TEST_CONTAINER_BOOT_DELAY=10
|
||||
- MIGRATE_TEST_CONTAINER_BOOT_TIMEOUT=60
|
||||
|
||||
# TODO: https://docs.docker.com/engine/installation/linux/ubuntu/
|
||||
# pre-provision with travis docker setup and pin down docker version in install step
|
||||
services:
|
||||
- docker
|
||||
- docker
|
||||
|
||||
before_cache:
|
||||
- mv $GOPATH/src/github.com/golang-migrate /tmp/golang-migrate
|
||||
- rm -rf $GOPATH/pkg/**/github.com/golang-migrate
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $GOPATH/src
|
||||
- $GOPATH/pkg
|
||||
|
||||
install:
|
||||
- make deps
|
||||
- (cd $GOPATH/src/github.com/docker/docker && git fetch --all --tags --prune && git checkout v17.05.0-ce)
|
||||
- sudo apt-get update && sudo apt-get install docker-ce=17.05.0*
|
||||
- sudo apt-get update && sudo apt-get --allow-downgrades install docker-ce=17.05.0*
|
||||
- go get github.com/mattn/goveralls
|
||||
|
||||
script:
|
||||
- make test
|
||||
- make test COVERAGE_DIR=/tmp/coverage
|
||||
|
||||
after_success:
|
||||
- goveralls -service=travis-ci -coverprofile .coverage/combined.txt
|
||||
- mv /tmp/golang-migrate $GOPATH/src/github.com/golang-migrate
|
||||
- goveralls -service=travis-ci -coverprofile /tmp/coverage/combined.txt
|
||||
- make list-external-deps > dependency_tree.txt && cat dependency_tree.txt
|
||||
|
||||
before_deploy:
|
||||
- make build-cli
|
||||
- gem install --no-ri --no-rdoc fpm
|
||||
- fpm -s dir -t deb -n migrate -v "$(git describe --tags 2>/dev/null | cut -c 2-)" --license MIT -m matthias.kadenbach@gmail.com --url https://github.com/mattes/migrate --description='Database migrations' -a amd64 -p migrate.$(git describe --tags 2>/dev/null | cut -c 2-).deb --deb-no-default-config-files -f -C cli/build migrate.linux-amd64=/usr/bin/migrate
|
||||
- fpm -s dir -t deb -n migrate -v "$(git describe --tags 2>/dev/null | cut -c 2-)" --license MIT -m dhui@users.noreply.github.com --url https://github.com/golang-migrate/migrate --description='Database migrations' -a amd64 -p migrate.$(git describe --tags 2>/dev/null | cut -c 2-).deb --deb-no-default-config-files -f -C cli/build migrate.linux-amd64=/usr/bin/migrate
|
||||
|
||||
deploy:
|
||||
- provider: releases
|
||||
api_key:
|
||||
secure: EFow50BI448HVb/uQ1Kk2Kq0xzmwIYq3V67YyymXIuqSCodvXEsMiBPUoLrxEknpPEIc67LEQTNdfHBgvyHk6oRINWAfie+7pr5tKrpOTF9ghyxoN1PlO8WKQCqwCvGMBCnc5ur5rvzp0bqfpV2rs5q9/nngy3kBuEvs12V7iho=
|
||||
secure: hWH1HLPpzpfA8pXQ93T1qKQVFSpQp0as/JLQ7D91jHuJ8p+RxVeqblDrR6HQY/95R/nyiE9GJmvUolSuw5h449LSrGxPtVWhdh6EnkxlQHlen5XeMhVjRjFV0sE9qGe8v7uAkiTfRO61ktTWHrEAvw5qpyqnNISodmZS78XIasPODQbNlzwINhWhDTHIjXGb4FpizYaL3OGCanrxfR9fQyCaqKGGBjRq3Mfq8U6Yd4mApmsE+uJxgaZV8K5zBqpkSzQRWhcVGNL5DuLsU3gfSJOo7kZeA2G71SHffH577dBoqtCZ4VFv169CoUZehLWCb+7XKJZmHXVujCURATSySLGUOPc6EoLFAn3YtsCA04mS4bZVo5FZPWVwfhjmkhtDR4f6wscKp7r1HsFHSOgm59QfETQdrn4MnZ44H2Jd39axqndn5DvK9EcZVjPHynOPnueXP2u6mTuUgh2VyyWBCDO3CNo0fGlo7VJI69IkIWNSD87K9cHZWYMClyKZkUzS+PmRAhHRYbVd+9ZjKOmnU36kUHNDG/ft1D4ogsY+rhVtXB4lgWDM5adri+EIScYdYnB1/pQexLBigcJY9uE7nQTR0U6QgVNYvun7uRNs40E0c4voSfmPdFO0FlOD2y1oQhnaXfWLbu9nMcTcs4RFGrcC7NzkUN4/WjG8s285V6w=
|
||||
skip_cleanup: true
|
||||
on:
|
||||
go: 1.9
|
||||
repo: mattes/migrate
|
||||
go: "1.10"
|
||||
repo: golang-migrate/migrate
|
||||
tags: true
|
||||
file:
|
||||
- cli/build/migrate.linux-amd64.tar.gz
|
||||
|
@ -51,14 +58,13 @@ deploy:
|
|||
- dependency_tree.txt
|
||||
- provider: packagecloud
|
||||
repository: migrate
|
||||
username: mattes
|
||||
username: golang-migrate
|
||||
token:
|
||||
secure: RiHJ/+J9DvXUah/APYdWySWZ5uOOISYJ0wS7xddc7/BNStRVjzFzvJ9zmb67RkyZZrvGuVjPiL4T8mtDyCJCj47RmU/56wPdEHbar/FjsiUCgwvR19RlulkgbV4okBCePbwzMw6HNHRp14TzfQCPtnN4kef0lOI4gZJkImN7rtQ=
|
||||
secure: aICwu3gJ1sJ1QVCD3elpg+Jxzt4P+Zj1uoh5f0sOwnjDNIZ4FwUT1cMrWloP8P2KD0iyCOawuZER27o/kQ21oX2OxHvQbYPReA2znLm7lHzCmypAAOHPxpgnQ4rMGHHJXd+OsxtdclGs67c+EbdBfoRRbK400Qz/vjPJEDeH4mh02ZHC2nw4Nk/wV4jjBIkIt9dGEx6NgOA17FCMa3MaPHlHeFIzU7IfTlDHbS0mCCYbg/wafWBWcbGqtZLWAYtJDmfjrAStmDLdAX5J5PsB7taGSGPZHmPmpGoVgrKt/tb9Xz1rFBGslTpGROOiO4CiMAvkEKFn8mxrBGjfSBqp7Dp3eeSalKXB1DJAbEXx2sEbMcvmnoR9o43meaAn+ZRts8lRL8S/skBloe6Nk8bx3NlJCGB9WPK1G56b7c/fZnJxQbrCw6hxDfbZwm8S2YPviFTo/z1BfZDhRsL74reKsN2kgnGo2W/k38vvzIpsssQ9DHN1b0TLCxolCNPtQ7oHcQ1ohcjP2UgYXk0FhqDoL+9LQva/DU4N9sKH0UbAaqsMVSErLeG8A4aauuFcVrWRBaDYyTag4dQqzTulEy7iru2kDDIBgSQ1gMW/yoBOIPK4oi6MtbTf1X39fzXFLS1cDd3LW61yAu3YrbjAetpfx2frIvrRAiL9TxWA1gnrs5o=
|
||||
dist: ubuntu/xenial
|
||||
package_glob: '*.deb'
|
||||
skip_cleanup: true
|
||||
on:
|
||||
go: 1.9
|
||||
repo: mattes/migrate
|
||||
go: "1.10"
|
||||
repo: golang-migrate/migrate
|
||||
tags: true
|
||||
|
||||
|
|
|
@ -12,11 +12,12 @@
|
|||
|
||||
Some more helpful commands:
|
||||
|
||||
* You can specify which database/ source tests to run:
|
||||
* You can specify which database/ source tests to run:
|
||||
`make test-short SOURCE='file go-bindata' DATABASE='postgres cassandra'`
|
||||
* After `make test`, run `make html-coverage` which opens a shiny test coverage overview.
|
||||
* After `make test`, run `make html-coverage` which opens a shiny test coverage overview.
|
||||
* Missing imports? `make deps`
|
||||
* `make build-cli` builds the CLI in directory `cli/build/`.
|
||||
* `make list-external-deps` lists all external dependencies for each package
|
||||
* `make docs && make open-docs` opens godoc in your browser, `make kill-docs` kills the godoc server.
|
||||
Repeatedly call `make docs` to refresh the server.
|
||||
* `make docs && make open-docs` opens godoc in your browser, `make kill-docs` kills the godoc server.
|
||||
Repeatedly call `make docs` to refresh the server.
|
||||
* Set the `DOCKER_API_VERSION` environment variable to the latest supported version if you get errors regarding the docker client API version being too new.
|
||||
|
|
24
Makefile
24
Makefile
|
@ -1,15 +1,16 @@
|
|||
SOURCE ?= file go-bindata github aws-s3 google-cloud-storage
|
||||
DATABASE ?= postgres mysql redshift cassandra sqlite3 spanner cockroachdb clickhouse
|
||||
DATABASE ?= postgres mysql redshift cassandra spanner cockroachdb clickhouse
|
||||
VERSION ?= $(shell git describe --tags 2>/dev/null | cut -c 2-)
|
||||
TEST_FLAGS ?=
|
||||
REPO_OWNER ?= $(shell cd .. && basename "$$(pwd)")
|
||||
COVERAGE_DIR ?= .coverage
|
||||
|
||||
|
||||
build-cli: clean
|
||||
-mkdir ./cli/build
|
||||
cd ./cli && CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -a -o build/migrate.linux-amd64 -ldflags='-X main.Version=$(VERSION)' -tags '$(DATABASE) $(SOURCE)' .
|
||||
cd ./cli && CGO_ENABLED=1 GOOS=darwin GOARCH=amd64 go build -a -o build/migrate.darwin-amd64 -ldflags='-X main.Version=$(VERSION)' -tags '$(DATABASE) $(SOURCE)' .
|
||||
cd ./cli && CGO_ENABLED=1 GOOS=windows GOARCH=amd64 go build -a -o build/migrate.windows-amd64.exe -ldflags='-X main.Version=$(VERSION)' -tags '$(DATABASE) $(SOURCE)' .
|
||||
cd ./cli && GOOS=linux GOARCH=amd64 go build -a -o build/migrate.linux-amd64 -ldflags='-X main.Version=$(VERSION)' -tags '$(DATABASE) $(SOURCE)' .
|
||||
cd ./cli && GOOS=darwin GOARCH=amd64 go build -a -o build/migrate.darwin-amd64 -ldflags='-X main.Version=$(VERSION)' -tags '$(DATABASE) $(SOURCE)' .
|
||||
cd ./cli && GOOS=windows GOARCH=amd64 go build -a -o build/migrate.windows-amd64.exe -ldflags='-X main.Version=$(VERSION)' -tags '$(DATABASE) $(SOURCE)' .
|
||||
cd ./cli/build && find . -name 'migrate*' | xargs -I{} tar czf {}.tar.gz {}
|
||||
cd ./cli/build && shasum -a 256 * > sha256sum.txt
|
||||
cat ./cli/build/sha256sum.txt
|
||||
|
@ -24,11 +25,11 @@ test-short:
|
|||
|
||||
|
||||
test:
|
||||
@-rm -r .coverage
|
||||
@mkdir .coverage
|
||||
make test-with-flags TEST_FLAGS='-v -race -covermode atomic -coverprofile .coverage/_$$(RAND).txt -bench=. -benchmem'
|
||||
@echo 'mode: atomic' > .coverage/combined.txt
|
||||
@cat .coverage/*.txt | grep -v 'mode: atomic' >> .coverage/combined.txt
|
||||
@-rm -r $(COVERAGE_DIR)
|
||||
@mkdir $(COVERAGE_DIR)
|
||||
make test-with-flags TEST_FLAGS='-v -race -covermode atomic -coverprofile $$(COVERAGE_DIR)/_$$(RAND).txt -bench=. -benchmem -timeout 20m'
|
||||
@echo 'mode: atomic' > $(COVERAGE_DIR)/combined.txt
|
||||
@cat $(COVERAGE_DIR)/_*.txt | grep -v 'mode: atomic' >> $(COVERAGE_DIR)/combined.txt
|
||||
|
||||
|
||||
test-with-flags:
|
||||
|
@ -53,14 +54,15 @@ kill-orphaned-docker-containers:
|
|||
|
||||
|
||||
html-coverage:
|
||||
go tool cover -html=.coverage/combined.txt
|
||||
go tool cover -html=$(COVERAGE_DIR)/combined.txt
|
||||
|
||||
|
||||
deps:
|
||||
-go get -v -u ./...
|
||||
-go test -v -i ./...
|
||||
# TODO: why is this not being fetched with the command above?
|
||||
# TODO: why are these not being fetched by `go get`?
|
||||
-go get -u github.com/fsouza/fake-gcs-server/fakestorage
|
||||
-go get -u github.com/kshvakov/clickhouse
|
||||
|
||||
|
||||
list-external-deps:
|
||||
|
|
32
README.md
32
README.md
|
@ -1,7 +1,9 @@
|
|||
[![Build Status](https://travis-ci.org/mattes/migrate.svg?branch=master)](https://travis-ci.org/mattes/migrate)
|
||||
[![GoDoc](https://godoc.org/github.com/mattes/migrate?status.svg)](https://godoc.org/github.com/mattes/migrate)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/mattes/migrate/badge.svg?branch=v3.0-prev)](https://coveralls.io/github/mattes/migrate?branch=v3.0-prev)
|
||||
[![packagecloud.io](https://img.shields.io/badge/deb-packagecloud.io-844fec.svg)](https://packagecloud.io/mattes/migrate?filter=debs)
|
||||
[![Build Status](https://img.shields.io/travis/golang-migrate/migrate/master.svg)](https://travis-ci.org/golang-migrate/migrate)
|
||||
[![GoDoc](https://godoc.org/github.com/golang-migrate/migrate?status.svg)](https://godoc.org/github.com/golang-migrate/migrate)
|
||||
[![Coverage Status](https://img.shields.io/coveralls/github/golang-migrate/migrate/master.svg)](https://coveralls.io/github/golang-migrate/migrate?branch=master)
|
||||
[![packagecloud.io](https://img.shields.io/badge/deb-packagecloud.io-844fec.svg)](https://packagecloud.io/golang-migrate/migrate?filter=debs)
|
||||
[![GitHub Release](https://img.shields.io/github/release/golang-migrate/migrate.svg)](https://github.com/golang-migrate/migrate/releases)
|
||||
|
||||
|
||||
# migrate
|
||||
|
||||
|
@ -9,12 +11,12 @@ __Database migrations written in Go. Use as [CLI](#cli-usage) or import as [libr
|
|||
|
||||
* Migrate reads migrations from [sources](#migration-sources)
|
||||
and applies them in correct order to a [database](#databases).
|
||||
* Drivers are "dumb", migrate glues everything together and makes sure the logic is bulletproof.
|
||||
* Drivers are "dumb", migrate glues everything together and makes sure the logic is bulletproof.
|
||||
(Keeps the drivers lightweight, too.)
|
||||
* Database drivers don't assume things or try to correct user input. When in doubt, fail.
|
||||
|
||||
|
||||
Looking for [v1](https://github.com/mattes/migrate/tree/v1)?
|
||||
Looking for [v1](https://github.com/golang-migrate/migrate/tree/v1)?
|
||||
|
||||
|
||||
## Databases
|
||||
|
@ -25,7 +27,7 @@ Database drivers run migrations. [Add a new database?](database/driver.go)
|
|||
* [Redshift](database/redshift)
|
||||
* [Ql](database/ql)
|
||||
* [Cassandra](database/cassandra)
|
||||
* [SQLite](database/sqlite3)
|
||||
* [SQLite](database/sqlite3) ([todo #165](https://github.com/mattes/migrate/issues/165))
|
||||
* [MySQL/ MariaDB](database/mysql)
|
||||
* [Neo4j](database/neo4j) ([todo #167](https://github.com/mattes/migrate/issues/167))
|
||||
* [MongoDB](database/mongodb) ([todo #169](https://github.com/mattes/migrate/issues/169))
|
||||
|
@ -69,19 +71,19 @@ $ migrate -database postgres://localhost:5432/database up 2
|
|||
* API is stable and frozen for this release (v3.x).
|
||||
* Package migrate has no external dependencies.
|
||||
* Only import the drivers you need.
|
||||
(check [dependency_tree.txt](https://github.com/mattes/migrate/releases) for each driver)
|
||||
(check [dependency_tree.txt](https://github.com/golang-migrate/migrate/releases) for each driver)
|
||||
* To help prevent database corruptions, it supports graceful stops via `GracefulStop chan bool`.
|
||||
* Bring your own logger.
|
||||
* Uses `io.Reader` streams internally for low memory overhead.
|
||||
* Thread-safe and no goroutine leaks.
|
||||
|
||||
__[Go Documentation](https://godoc.org/github.com/mattes/migrate)__
|
||||
__[Go Documentation](https://godoc.org/github.com/golang-migrate/migrate)__
|
||||
|
||||
```go
|
||||
import (
|
||||
"github.com/mattes/migrate"
|
||||
_ "github.com/mattes/migrate/database/postgres"
|
||||
_ "github.com/mattes/migrate/source/github"
|
||||
"github.com/golang-migrate/migrate"
|
||||
_ "github.com/golang-migrate/migrate/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/source/github"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
@ -98,9 +100,9 @@ Want to use an existing database client?
|
|||
import (
|
||||
"database/sql"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/mattes/migrate/database/postgres"
|
||||
_ "github.com/mattes/migrate/source/file"
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/source/file"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -5,8 +5,8 @@
|
|||
#### With Go toolchain
|
||||
|
||||
```
|
||||
$ go get -u -d github.com/mattes/migrate/cli github.com/lib/pq
|
||||
$ go build -tags 'postgres' -o /usr/local/bin/migrate github.com/mattes/migrate/cli
|
||||
$ go get -u -d github.com/golang-migrate/migrate/cli github.com/lib/pq
|
||||
$ go build -tags 'postgres' -o /usr/local/bin/migrate github.com/golang-migrate/migrate/cli
|
||||
```
|
||||
|
||||
Note: This example builds the cli which will only work with postgres. In order
|
||||
|
@ -26,18 +26,18 @@ $ brew install migrate --with-postgres
|
|||
#### Linux (*.deb package)
|
||||
|
||||
```
|
||||
$ curl -L https://packagecloud.io/mattes/migrate/gpgkey | apt-key add -
|
||||
$ echo "deb https://packagecloud.io/mattes/migrate/ubuntu/ xenial main" > /etc/apt/sources.list.d/migrate.list
|
||||
$ curl -L https://packagecloud.io/golang-migrate/migrate/gpgkey | apt-key add -
|
||||
$ echo "deb https://packagecloud.io/golang-migrate/migrate/ubuntu/ xenial main" > /etc/apt/sources.list.d/migrate.list
|
||||
$ apt-get update
|
||||
$ apt-get install -y migrate
|
||||
```
|
||||
|
||||
#### Download pre-build binary (Windows, MacOS, or Linux)
|
||||
|
||||
[Release Downloads](https://github.com/mattes/migrate/releases)
|
||||
[Release Downloads](https://github.com/golang-migrate/migrate/releases)
|
||||
|
||||
```
|
||||
$ curl -L https://github.com/mattes/migrate/releases/download/$version/migrate.$platform-amd64.tar.gz | tar xvz
|
||||
$ curl -L https://github.com/golang-migrate/migrate/releases/download/$version/migrate.$platform-amd64.tar.gz | tar xvz
|
||||
```
|
||||
|
||||
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/source/aws-s3"
|
||||
_ "github.com/golang-migrate/migrate/source/aws-s3"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/database/cassandra"
|
||||
_ "github.com/golang-migrate/migrate/database/cassandra"
|
||||
)
|
||||
|
|
|
@ -4,5 +4,5 @@ package main
|
|||
|
||||
import (
|
||||
_ "github.com/kshvakov/clickhouse"
|
||||
_ "github.com/mattes/migrate/database/clickhouse"
|
||||
_ "github.com/golang-migrate/migrate/database/clickhouse"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/database/cockroachdb"
|
||||
_ "github.com/golang-migrate/migrate/database/cockroachdb"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/source/github"
|
||||
_ "github.com/golang-migrate/migrate/source/github"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/source/go-bindata"
|
||||
_ "github.com/golang-migrate/migrate/source/go-bindata"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/source/google-cloud-storage"
|
||||
_ "github.com/golang-migrate/migrate/source/google-cloud-storage"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/database/mysql"
|
||||
_ "github.com/golang-migrate/migrate/database/mysql"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/database/postgres"
|
||||
_ "github.com/golang-migrate/migrate/database/postgres"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/database/ql"
|
||||
_ "github.com/golang-migrate/migrate/database/ql"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/database/redshift"
|
||||
_ "github.com/golang-migrate/migrate/database/redshift"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/database/spanner"
|
||||
_ "github.com/golang-migrate/migrate/database/spanner"
|
||||
)
|
||||
|
|
|
@ -3,5 +3,5 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/mattes/migrate/database/sqlite3"
|
||||
_ "github.com/golang-migrate/migrate/database/sqlite3"
|
||||
)
|
||||
|
|
|
@ -1,24 +1,81 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/mattes/migrate"
|
||||
_ "github.com/mattes/migrate/database/stub" // TODO remove again
|
||||
_ "github.com/mattes/migrate/source/file"
|
||||
"os"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/golang-migrate/migrate"
|
||||
_ "github.com/golang-migrate/migrate/database/stub" // TODO remove again
|
||||
_ "github.com/golang-migrate/migrate/source/file"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func createCmd(dir string, timestamp int64, name string, ext string) {
|
||||
base := fmt.Sprintf("%v%v_%v.", dir, timestamp, name)
|
||||
func nextSeq(matches []string, dir string, seqDigits int) (string, error) {
|
||||
if seqDigits <= 0 {
|
||||
return "", errors.New("Digits must be positive")
|
||||
}
|
||||
|
||||
nextSeq := 1
|
||||
if len(matches) > 0 {
|
||||
filename := matches[len(matches)-1]
|
||||
matchSeqStr := strings.TrimPrefix(filename, dir)
|
||||
idx := strings.Index(matchSeqStr, "_")
|
||||
if idx < 1 { // Using 1 instead of 0 since there should be at least 1 digit
|
||||
return "", errors.New("Malformed migration filename: " + filename)
|
||||
}
|
||||
matchSeqStr = matchSeqStr[0:idx]
|
||||
var err error
|
||||
nextSeq, err = strconv.Atoi(matchSeqStr)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
nextSeq++
|
||||
}
|
||||
if nextSeq <= 0 {
|
||||
return "", errors.New("Next sequence number must be positive")
|
||||
}
|
||||
|
||||
nextSeqStr := strconv.Itoa(nextSeq)
|
||||
if len(nextSeqStr) > seqDigits {
|
||||
return "", fmt.Errorf("Next sequence number %s too large. At most %d digits are allowed", nextSeqStr, seqDigits)
|
||||
}
|
||||
padding := seqDigits - len(nextSeqStr)
|
||||
if padding > 0 {
|
||||
nextSeqStr = strings.Repeat("0", padding) + nextSeqStr
|
||||
}
|
||||
return nextSeqStr, nil
|
||||
}
|
||||
|
||||
func createCmd(dir string, timestamp int64, name string, ext string, seq bool, seqDigits int) {
|
||||
var base string
|
||||
if seq {
|
||||
if seqDigits <= 0 {
|
||||
log.fatalErr(errors.New("Digits must be positive"))
|
||||
}
|
||||
matches, err := filepath.Glob(dir + "*" + ext)
|
||||
if err != nil {
|
||||
log.fatalErr(err)
|
||||
}
|
||||
nextSeqStr, err := nextSeq(matches, dir, seqDigits)
|
||||
if err != nil {
|
||||
log.fatalErr(err)
|
||||
}
|
||||
base = fmt.Sprintf("%v%v_%v.", dir, nextSeqStr, name)
|
||||
} else {
|
||||
base = fmt.Sprintf("%v%v_%v.", dir, timestamp, name)
|
||||
}
|
||||
|
||||
os.MkdirAll(dir, os.ModePerm)
|
||||
createFile(base + "up" + ext)
|
||||
createFile(base + "down" + ext)
|
||||
}
|
||||
|
||||
func createFile(fname string) {
|
||||
if _, err := os.Create(fname); err != nil {
|
||||
log.fatalErr(err)
|
||||
}
|
||||
if _, err := os.Create(fname); err != nil {
|
||||
log.fatalErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
func gotoCmd(m *migrate.Migrate, v uint) {
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNextSeq(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
matches []string
|
||||
dir string
|
||||
seqDigits int
|
||||
expected string
|
||||
expectedErrStr string
|
||||
}{
|
||||
{"Bad digits", []string{}, "migrationDir", 0, "", "Digits must be positive"},
|
||||
{"Single digit initialize", []string{}, "migrationDir", 1, "1", ""},
|
||||
{"Single digit malformed", []string{"bad"}, "migrationDir", 1, "", "Malformed migration filename: bad"},
|
||||
{"Single digit no int", []string{"bad_bad"}, "migrationDir", 1, "", "strconv.Atoi: parsing \"bad\": invalid syntax"},
|
||||
{"Single digit negative seq", []string{"-5_test"}, "migrationDir", 1, "", "Next sequence number must be positive"},
|
||||
{"Single digit increment", []string{"3_test", "4_test"}, "migrationDir", 1, "5", ""},
|
||||
{"Single digit overflow", []string{"9_test"}, "migrationDir", 1, "", "Next sequence number 10 too large. At most 1 digits are allowed"},
|
||||
{"Zero-pad initialize", []string{}, "migrationDir", 6, "000001", ""},
|
||||
{"Zero-pad malformed", []string{"bad"}, "migrationDir", 6, "", "Malformed migration filename: bad"},
|
||||
{"Zero-pad no int", []string{"bad_bad"}, "migrationDir", 6, "", "strconv.Atoi: parsing \"bad\": invalid syntax"},
|
||||
{"Zero-pad negative seq", []string{"-000005_test"}, "migrationDir", 6, "", "Next sequence number must be positive"},
|
||||
{"Zero-pad increment", []string{"000003_test", "000004_test"}, "migrationDir", 6, "000005", ""},
|
||||
{"Zero-pad overflow", []string{"999999_test"}, "migrationDir", 6, "", "Next sequence number 1000000 too large. At most 6 digits are allowed"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.name, func(t *testing.T) {
|
||||
nextSeq, err := nextSeq(c.matches, c.dir, c.seqDigits)
|
||||
if nextSeq != c.expected {
|
||||
t.Error("Incorrect nextSeq: " + nextSeq + " != " + c.expected)
|
||||
}
|
||||
if err != nil {
|
||||
if err.Error() != c.expectedErrStr {
|
||||
t.Error("Incorrect error: " + err.Error() + " != " + c.expectedErrStr)
|
||||
}
|
||||
} else if c.expectedErrStr != "" {
|
||||
t.Error("Expected error: " + c.expectedErrStr + " but got nil instead")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -3,8 +3,8 @@ FROM ubuntu:xenial
|
|||
RUN apt-get update && \
|
||||
apt-get install -y curl apt-transport-https
|
||||
|
||||
RUN curl -L https://packagecloud.io/mattes/migrate/gpgkey | apt-key add - && \
|
||||
echo "deb https://packagecloud.io/mattes/migrate/ubuntu/ xenial main" > /etc/apt/sources.list.d/migrate.list && \
|
||||
RUN curl -L https://packagecloud.io/golang-migrate/migrate/gpgkey | apt-key add - && \
|
||||
echo "deb https://packagecloud.io/golang-migrate/migrate/ubuntu/ xenial main" > /etc/apt/sources.list.d/migrate.list && \
|
||||
apt-get update && \
|
||||
apt-get install -y migrate
|
||||
|
||||
|
|
13
cli/main.go
13
cli/main.go
|
@ -10,7 +10,7 @@ import (
|
|||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/golang-migrate/migrate"
|
||||
)
|
||||
|
||||
// set main log
|
||||
|
@ -42,8 +42,9 @@ Options:
|
|||
-help Print usage
|
||||
|
||||
Commands:
|
||||
create [-ext E] [-dir D] NAME
|
||||
Create a set of timestamped up/down migrations titled NAME, in directory D with extension E
|
||||
create [-ext E] [-dir D] [-seq] [-digits N] NAME
|
||||
Create a set of timestamped up/down migrations titled NAME, in directory D with extension E.
|
||||
Use -seq option to generate sequential up/down migrations with N digits.
|
||||
goto V Migrate to version V
|
||||
up [N] Apply all or N up migrations
|
||||
down [N] Apply all or N down migrations
|
||||
|
@ -106,10 +107,14 @@ Commands:
|
|||
switch flag.Arg(0) {
|
||||
case "create":
|
||||
args := flag.Args()[1:]
|
||||
seq := false
|
||||
seqDigits := 6
|
||||
|
||||
createFlagSet := flag.NewFlagSet("create", flag.ExitOnError)
|
||||
extPtr := createFlagSet.String("ext", "", "File extension")
|
||||
dirPtr := createFlagSet.String("dir", "", "Directory to place file in (default: current working directory)")
|
||||
createFlagSet.BoolVar(&seq, "seq", seq, "Use sequential numbers instead of timestamps (default: false)")
|
||||
createFlagSet.IntVar(&seqDigits, "digits", seqDigits, "The number of digits to use in sequences (default: 6)")
|
||||
createFlagSet.Parse(args)
|
||||
|
||||
if createFlagSet.NArg() == 0 {
|
||||
|
@ -126,7 +131,7 @@ Commands:
|
|||
|
||||
timestamp := startTime.Unix()
|
||||
|
||||
createCmd(*dirPtr, timestamp, name, *extPtr)
|
||||
createCmd(*dirPtr, timestamp, name, *extPtr, seq, seqDigits)
|
||||
|
||||
case "goto":
|
||||
if migraterErr != nil {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/gocql/gocql"
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -3,8 +3,8 @@ package cassandra
|
|||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
dt "github.com/mattes/migrate/database/testing"
|
||||
mt "github.com/mattes/migrate/testing"
|
||||
dt "github.com/golang-migrate/migrate/database/testing"
|
||||
mt "github.com/golang-migrate/migrate/testing"
|
||||
"github.com/gocql/gocql"
|
||||
"time"
|
||||
"strconv"
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
"net/url"
|
||||
"time"
|
||||
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
)
|
||||
|
||||
var DefaultMigrationsTable = "schema_migrations"
|
||||
|
|
|
@ -9,8 +9,8 @@ import (
|
|||
|
||||
"github.com/cockroachdb/cockroach-go/crdb"
|
||||
"github.com/lib/pq"
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"context"
|
||||
|
@ -223,7 +223,7 @@ func (c *CockroachDb) Run(migration io.Reader) error {
|
|||
|
||||
func (c *CockroachDb) SetVersion(version int, dirty bool) error {
|
||||
return crdb.ExecuteTx(context.Background(), c.db, nil, func(tx *sql.Tx) error {
|
||||
if _, err := tx.Exec( `TRUNCATE "` + c.config.MigrationsTable + `"`); err != nil {
|
||||
if _, err := tx.Exec(`DELETE FROM "` + c.config.MigrationsTable + `"`); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/lib/pq"
|
||||
dt "github.com/mattes/migrate/database/testing"
|
||||
mt "github.com/mattes/migrate/testing"
|
||||
dt "github.com/golang-migrate/migrate/database/testing"
|
||||
mt "github.com/golang-migrate/migrate/testing"
|
||||
"bytes"
|
||||
)
|
||||
|
||||
|
|
|
@ -1,53 +1,53 @@
|
|||
# MySQL
|
||||
|
||||
`mysql://user:password@tcp(host:port)/dbname?query`
|
||||
|
||||
| URL Query | WithInstance Config | Description |
|
||||
|------------|---------------------|-------------|
|
||||
| `x-migrations-table` | `MigrationsTable` | Name of the migrations table |
|
||||
| `dbname` | `DatabaseName` | The name of the database to connect to |
|
||||
| `user` | | The user to sign in as |
|
||||
| `password` | | The user's password |
|
||||
| `host` | | The host to connect to. |
|
||||
| `port` | | The port to bind to. |
|
||||
| `x-tls-ca` | | The location of the root certificate file. |
|
||||
| `x-tls-cert` | | Cert file location. |
|
||||
| `x-tls-key` | | Key file location. |
|
||||
| `x-tls-insecure-skip-verify` | | Whether or not to use SSL (true\|false) |
|
||||
|
||||
## Use with existing client
|
||||
|
||||
If you use the MySQL driver with existing database client, you must create the client with parameter `multiStatements=true`:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/mattes/migrate/database/mysql"
|
||||
_ "github.com/mattes/migrate/source/file"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db, _ := sql.Open("mysql", "user:password@tcp(host:port)/dbname?multiStatements=true")
|
||||
driver, _ := mysql.WithInstance(db, &mysql.Config{})
|
||||
m, _ := migrate.NewWithDatabaseInstance(
|
||||
"file:///migrations",
|
||||
"mysql",
|
||||
driver,
|
||||
)
|
||||
|
||||
m.Steps(2)
|
||||
}
|
||||
```
|
||||
|
||||
## Upgrading from v1
|
||||
|
||||
1. Write down the current migration version from schema_migrations
|
||||
1. `DROP TABLE schema_migrations`
|
||||
2. Wrap your existing migrations in transactions ([BEGIN/COMMIT](https://dev.mysql.com/doc/refman/5.7/en/commit.html)) if you use multiple statements within one migration.
|
||||
3. Download and install the latest migrate version.
|
||||
4. Force the current migration version with `migrate force <current_version>`.
|
||||
# MySQL
|
||||
|
||||
`mysql://user:password@tcp(host:port)/dbname?query`
|
||||
|
||||
| URL Query | WithInstance Config | Description |
|
||||
|------------|---------------------|-------------|
|
||||
| `x-migrations-table` | `MigrationsTable` | Name of the migrations table |
|
||||
| `dbname` | `DatabaseName` | The name of the database to connect to |
|
||||
| `user` | | The user to sign in as |
|
||||
| `password` | | The user's password |
|
||||
| `host` | | The host to connect to. |
|
||||
| `port` | | The port to bind to. |
|
||||
| `x-tls-ca` | | The location of the root certificate file. |
|
||||
| `x-tls-cert` | | Cert file location. |
|
||||
| `x-tls-key` | | Key file location. |
|
||||
| `x-tls-insecure-skip-verify` | | Whether or not to use SSL (true\|false) |
|
||||
|
||||
## Use with existing client
|
||||
|
||||
If you use the MySQL driver with existing database client, you must create the client with parameter `multiStatements=true`:
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database/mysql"
|
||||
_ "github.com/golang-migrate/migrate/source/file"
|
||||
)
|
||||
|
||||
func main() {
|
||||
db, _ := sql.Open("mysql", "user:password@tcp(host:port)/dbname?multiStatements=true")
|
||||
driver, _ := mysql.WithInstance(db, &mysql.Config{})
|
||||
m, _ := migrate.NewWithDatabaseInstance(
|
||||
"file:///migrations",
|
||||
"mysql",
|
||||
driver,
|
||||
)
|
||||
|
||||
m.Steps(2)
|
||||
}
|
||||
```
|
||||
|
||||
## Upgrading from v1
|
||||
|
||||
1. Write down the current migration version from schema_migrations
|
||||
1. `DROP TABLE schema_migrations`
|
||||
2. Wrap your existing migrations in transactions ([BEGIN/COMMIT](https://dev.mysql.com/doc/refman/5.7/en/commit.html)) if you use multiple statements within one migration.
|
||||
3. Download and install the latest migrate version.
|
||||
4. Force the current migration version with `migrate force <current_version>`.
|
||||
|
|
|
@ -12,8 +12,8 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/go-sql-driver/mysql"
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -8,9 +8,9 @@ import (
|
|||
// "log"
|
||||
"testing"
|
||||
|
||||
// "github.com/go-sql-driver/mysql"
|
||||
dt "github.com/mattes/migrate/database/testing"
|
||||
mt "github.com/mattes/migrate/testing"
|
||||
"github.com/go-sql-driver/mysql"
|
||||
dt "github.com/golang-migrate/migrate/database/testing"
|
||||
mt "github.com/golang-migrate/migrate/testing"
|
||||
)
|
||||
|
||||
var versions = []mt.Version{
|
||||
|
@ -26,9 +26,13 @@ func isReady(i mt.Instance) bool {
|
|||
return false
|
||||
}
|
||||
defer db.Close()
|
||||
err = db.Ping()
|
||||
|
||||
if err == sqldriver.ErrBadConn {
|
||||
if err = db.Ping(); err != nil {
|
||||
switch err {
|
||||
case sqldriver.ErrBadConn, mysql.ErrInvalidConn:
|
||||
return false
|
||||
default:
|
||||
fmt.Println(err)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
|
@ -46,6 +50,7 @@ func Test(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
defer d.Close()
|
||||
dt.Test(t, d, []byte("SELECT 1"))
|
||||
|
||||
// check ensureVersionTable
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// +build go1.9
|
||||
|
||||
package postgres
|
||||
|
||||
import (
|
||||
|
@ -8,10 +9,10 @@ import (
|
|||
"io/ioutil"
|
||||
nurl "net/url"
|
||||
|
||||
"github.com/lib/pq"
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/mattes/migrate/database"
|
||||
"context"
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
"github.com/lib/pq"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -207,7 +208,7 @@ func (p *Postgres) SetVersion(version int, dirty bool) error {
|
|||
|
||||
func (p *Postgres) Version() (version int, dirty bool, err error) {
|
||||
query := `SELECT version, dirty FROM "` + p.config.MigrationsTable + `" LIMIT 1`
|
||||
err = p.db.QueryRowContext(context.Background(),query).Scan(&version, &dirty)
|
||||
err = p.db.QueryRowContext(context.Background(), query).Scan(&version, &dirty)
|
||||
switch {
|
||||
case err == sql.ErrNoRows:
|
||||
return database.NilVersion, false, nil
|
||||
|
@ -228,7 +229,7 @@ func (p *Postgres) Version() (version int, dirty bool, err error) {
|
|||
func (p *Postgres) Drop() error {
|
||||
// select all tables in current schema
|
||||
query := `SELECT table_name FROM information_schema.tables WHERE table_schema=(SELECT current_schema())`
|
||||
tables, err := p.db.QueryContext(context.Background(),query)
|
||||
tables, err := p.db.QueryContext(context.Background(), query)
|
||||
if err != nil {
|
||||
return &database.Error{OrigErr: err, Query: []byte(query)}
|
||||
}
|
||||
|
@ -266,7 +267,7 @@ func (p *Postgres) ensureVersionTable() error {
|
|||
// check if migration table exists
|
||||
var count int
|
||||
query := `SELECT COUNT(1) FROM information_schema.tables WHERE table_name = $1 AND table_schema = (SELECT current_schema()) LIMIT 1`
|
||||
if err := p.db.QueryRowContext(context.Background(),query, p.config.MigrationsTable).Scan(&count); err != nil {
|
||||
if err := p.db.QueryRowContext(context.Background(), query, p.config.MigrationsTable).Scan(&count); err != nil {
|
||||
return &database.Error{OrigErr: err, Query: []byte(query)}
|
||||
}
|
||||
if count == 1 {
|
||||
|
@ -275,7 +276,7 @@ func (p *Postgres) ensureVersionTable() error {
|
|||
|
||||
// if not, create the empty migration table
|
||||
query = `CREATE TABLE "` + p.config.MigrationsTable + `" (version bigint not null primary key, dirty boolean not null)`
|
||||
if _, err := p.db.ExecContext(context.Background(),query); err != nil {
|
||||
if _, err := p.db.ExecContext(context.Background(), query); err != nil {
|
||||
return &database.Error{OrigErr: err, Query: []byte(query)}
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -5,14 +5,15 @@ package postgres
|
|||
import (
|
||||
"bytes"
|
||||
"database/sql"
|
||||
sqldriver "database/sql/driver"
|
||||
"fmt"
|
||||
"io"
|
||||
"testing"
|
||||
|
||||
"github.com/lib/pq"
|
||||
dt "github.com/mattes/migrate/database/testing"
|
||||
mt "github.com/mattes/migrate/testing"
|
||||
"context"
|
||||
dt "github.com/golang-migrate/migrate/database/testing"
|
||||
mt "github.com/golang-migrate/migrate/testing"
|
||||
// "github.com/lib/pq"
|
||||
)
|
||||
|
||||
var versions = []mt.Version{
|
||||
|
@ -29,14 +30,14 @@ func isReady(i mt.Instance) bool {
|
|||
return false
|
||||
}
|
||||
defer db.Close()
|
||||
err = db.Ping()
|
||||
if err == io.EOF {
|
||||
return false
|
||||
|
||||
} else if e, ok := err.(*pq.Error); ok {
|
||||
if e.Code.Name() == "cannot_connect_now" {
|
||||
if err = db.Ping(); err != nil {
|
||||
switch err {
|
||||
case sqldriver.ErrBadConn, io.EOF:
|
||||
return false
|
||||
default:
|
||||
fmt.Println(err)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -51,6 +52,7 @@ func Test(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
defer d.Close()
|
||||
dt.Test(t, d, []byte("SELECT 1"))
|
||||
})
|
||||
}
|
||||
|
@ -64,6 +66,7 @@ func TestMultiStatement(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
defer d.Close()
|
||||
if err := d.Run(bytes.NewReader([]byte("CREATE TABLE foo (foo text); CREATE TABLE bar (bar text);"))); err != nil {
|
||||
t.Fatalf("expected err to be nil, got %v", err)
|
||||
}
|
||||
|
@ -84,10 +87,11 @@ func TestFilterCustomQuery(t *testing.T) {
|
|||
func(t *testing.T, i mt.Instance) {
|
||||
p := &Postgres{}
|
||||
addr := fmt.Sprintf("postgres://postgres@%v:%v/postgres?sslmode=disable&x-custom=foobar", i.Host(), i.Port())
|
||||
_, err := p.Open(addr)
|
||||
d, err := p.Open(addr)
|
||||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
defer d.Close()
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -100,6 +104,7 @@ func TestWithSchema(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
defer d.Close()
|
||||
|
||||
// create foobar schema
|
||||
if err := d.Run(bytes.NewReader([]byte("CREATE SCHEMA foobar AUTHORIZATION postgres"))); err != nil {
|
||||
|
@ -114,6 +119,7 @@ func TestWithSchema(t *testing.T) {
|
|||
if err != nil {
|
||||
t.Fatalf("%v", err)
|
||||
}
|
||||
defer d2.Close()
|
||||
|
||||
version, _, err := d2.Version()
|
||||
if err != nil {
|
||||
|
@ -184,4 +190,4 @@ func TestPostgres_Lock(t *testing.T) {
|
|||
t.Fatal(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,8 +10,8 @@ import (
|
|||
nurl "net/url"
|
||||
|
||||
_ "github.com/cznic/ql/driver"
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -9,9 +9,9 @@ import (
|
|||
"testing"
|
||||
|
||||
_ "github.com/cznic/ql/driver"
|
||||
"github.com/mattes/migrate"
|
||||
dt "github.com/mattes/migrate/database/testing"
|
||||
_ "github.com/mattes/migrate/source/file"
|
||||
"github.com/golang-migrate/migrate"
|
||||
dt "github.com/golang-migrate/migrate/database/testing"
|
||||
_ "github.com/golang-migrate/migrate/source/file"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
|
|
@ -3,8 +3,8 @@ package redshift
|
|||
import (
|
||||
"net/url"
|
||||
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/mattes/migrate/database/postgres"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
"github.com/golang-migrate/migrate/database/postgres"
|
||||
)
|
||||
|
||||
// init registers the driver under the name 'redshift'
|
||||
|
|
|
@ -14,8 +14,8 @@ import (
|
|||
"cloud.google.com/go/spanner"
|
||||
sdb "cloud.google.com/go/spanner/admin/database/apiv1"
|
||||
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
|
||||
"google.golang.org/api/iterator"
|
||||
adminpb "google.golang.org/genproto/googleapis/spanner/admin/database/v1"
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
dt "github.com/mattes/migrate/database/testing"
|
||||
dt "github.com/golang-migrate/migrate/database/testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
|
|
@ -3,8 +3,8 @@ package sqlite3
|
|||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
|
|
|
@ -3,9 +3,9 @@ package sqlite3
|
|||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"github.com/mattes/migrate"
|
||||
dt "github.com/mattes/migrate/database/testing"
|
||||
_ "github.com/mattes/migrate/source/file"
|
||||
"github.com/golang-migrate/migrate"
|
||||
dt "github.com/golang-migrate/migrate/database/testing"
|
||||
_ "github.com/golang-migrate/migrate/source/file"
|
||||
_ "github.com/mattn/go-sqlite3"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"io/ioutil"
|
||||
"reflect"
|
||||
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -3,7 +3,7 @@ package stub
|
|||
import (
|
||||
"testing"
|
||||
|
||||
dt "github.com/mattes/migrate/database/testing"
|
||||
dt "github.com/golang-migrate/migrate/database/testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
)
|
||||
|
||||
// Test runs tests against database implementations.
|
||||
|
|
|
@ -10,8 +10,8 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/mattes/migrate/database"
|
||||
"github.com/mattes/migrate/source"
|
||||
"github.com/golang-migrate/migrate/database"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
)
|
||||
|
||||
// DefaultPrefetchMigrations sets the number of migrations to pre-read
|
||||
|
|
|
@ -8,9 +8,9 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
dStub "github.com/mattes/migrate/database/stub"
|
||||
"github.com/mattes/migrate/source"
|
||||
sStub "github.com/mattes/migrate/source/stub"
|
||||
dStub "github.com/golang-migrate/migrate/database/stub"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
sStub "github.com/golang-migrate/migrate/source/stub"
|
||||
)
|
||||
|
||||
// sourceStubMigrations hold the following migrations:
|
||||
|
@ -104,7 +104,7 @@ func ExampleNewWithDatabaseInstance() {
|
|||
|
||||
// Create driver instance from db.
|
||||
// Check each driver if it supports the WithInstance function.
|
||||
// `import "github.com/mattes/migrate/database/postgres"`
|
||||
// `import "github.com/golang-migrate/migrate/database/postgres"`
|
||||
instance, err := dStub.WithInstance(db, &dStub.Config{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
@ -154,7 +154,7 @@ func ExampleNewWithSourceInstance() {
|
|||
|
||||
// Create driver instance from DummyInstance di.
|
||||
// Check each driver if it support the WithInstance function.
|
||||
// `import "github.com/mattes/migrate/source/stub"`
|
||||
// `import "github.com/golang-migrate/migrate/source/stub"`
|
||||
instance, err := sStub.WithInstance(di, &sStub.Config{})
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"github.com/aws/aws-sdk-go/aws/session"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/aws/aws-sdk-go/service/s3/s3iface"
|
||||
"github.com/mattes/migrate/source"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/service/s3"
|
||||
"github.com/mattes/migrate/source"
|
||||
st "github.com/mattes/migrate/source/testing"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
st "github.com/golang-migrate/migrate/source/testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/mattes/migrate/source"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
st "github.com/mattes/migrate/source/testing"
|
||||
st "github.com/golang-migrate/migrate/source/testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
|
|
@ -12,7 +12,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/google/go-github/github"
|
||||
"github.com/mattes/migrate/source"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
st "github.com/mattes/migrate/source/testing"
|
||||
st "github.com/golang-migrate/migrate/source/testing"
|
||||
)
|
||||
|
||||
var GithubTestSecret = "" // username:token
|
||||
|
|
|
@ -13,9 +13,9 @@ cd examples/migrations && go-bindata -pkg migrations .
|
|||
|
||||
```go
|
||||
import (
|
||||
"github.com/mattes/migrate"
|
||||
"github.com/mattes/migrate/source/go-bindata"
|
||||
"github.com/mattes/migrate/source/go-bindata/examples/migrations"
|
||||
"github.com/golang-migrate/migrate"
|
||||
"github.com/golang-migrate/migrate/source/go-bindata"
|
||||
"github.com/golang-migrate/migrate/source/go-bindata/examples/migrations"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/mattes/migrate/source"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
)
|
||||
|
||||
type AssetFunc func(name string) ([]byte, error)
|
||||
|
|
|
@ -3,8 +3,8 @@ package bindata
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mattes/migrate/source/go-bindata/testdata"
|
||||
st "github.com/mattes/migrate/source/testing"
|
||||
"github.com/golang-migrate/migrate/source/go-bindata/testdata"
|
||||
st "github.com/golang-migrate/migrate/source/testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"cloud.google.com/go/storage"
|
||||
"github.com/mattes/migrate/source"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
"golang.org/x/net/context"
|
||||
"google.golang.org/api/iterator"
|
||||
)
|
||||
|
|
|
@ -4,8 +4,8 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/fsouza/fake-gcs-server/fakestorage"
|
||||
"github.com/mattes/migrate/source"
|
||||
st "github.com/mattes/migrate/source/testing"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
st "github.com/golang-migrate/migrate/source/testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
|
|
@ -9,7 +9,7 @@ type Direction string
|
|||
|
||||
const (
|
||||
Down Direction = "down"
|
||||
Up = "up"
|
||||
Up Direction = "up"
|
||||
)
|
||||
|
||||
// Migration is a helper struct for source drivers that need to
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
"github.com/mattes/migrate/source"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -3,8 +3,8 @@ package stub
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/mattes/migrate/source"
|
||||
st "github.com/mattes/migrate/source/testing"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
st "github.com/golang-migrate/migrate/source/testing"
|
||||
)
|
||||
|
||||
func Test(t *testing.T) {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/mattes/migrate/source"
|
||||
"github.com/golang-migrate/migrate/source"
|
||||
)
|
||||
|
||||
// Test runs tests against source implementations.
|
||||
|
|
|
@ -5,17 +5,18 @@ import (
|
|||
"bufio"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
dockertypes "github.com/docker/docker/api/types"
|
||||
dockercontainer "github.com/docker/docker/api/types/container"
|
||||
dockernetwork "github.com/docker/docker/api/types/network"
|
||||
dockerclient "github.com/docker/docker/client"
|
||||
"io"
|
||||
"math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
dockertypes "github.com/docker/docker/api/types"
|
||||
dockercontainer "github.com/docker/docker/api/types/container"
|
||||
dockernetwork "github.com/docker/docker/api/types/network"
|
||||
dockerclient "github.com/docker/docker/client"
|
||||
)
|
||||
|
||||
func NewDockerContainer(t testing.TB, image string, env []string, cmd []string) (*DockerContainer, error) {
|
||||
|
@ -33,7 +34,7 @@ func NewDockerContainer(t testing.TB, image string, env []string, cmd []string)
|
|||
client: c,
|
||||
ImageName: image,
|
||||
ENV: env,
|
||||
Cmd: cmd,
|
||||
Cmd: cmd,
|
||||
}
|
||||
|
||||
if err := contr.PullImage(); err != nil {
|
||||
|
@ -62,6 +63,9 @@ type DockerContainer struct {
|
|||
}
|
||||
|
||||
func (d *DockerContainer) PullImage() error {
|
||||
if d == nil {
|
||||
return errors.New("Cannot pull image on a nil *DockerContainer")
|
||||
}
|
||||
d.t.Logf("Docker: Pull image %v", d.ImageName)
|
||||
r, err := d.client.ImagePull(context.Background(), d.ImageName, dockertypes.ImagePullOptions{})
|
||||
if err != nil {
|
||||
|
@ -84,7 +88,11 @@ func (d *DockerContainer) PullImage() error {
|
|||
}
|
||||
|
||||
func (d *DockerContainer) Start() error {
|
||||
containerName := fmt.Sprintf("migrate_test_%v", pseudoRandStr(10))
|
||||
if d == nil {
|
||||
return errors.New("Cannot start a nil *DockerContainer")
|
||||
}
|
||||
|
||||
containerName := fmt.Sprintf("migrate_test_%s", pseudoRandStr(10))
|
||||
|
||||
// create container first
|
||||
resp, err := d.client.ContainerCreate(context.Background(),
|
||||
|
@ -119,16 +127,24 @@ func (d *DockerContainer) Start() error {
|
|||
}
|
||||
|
||||
func (d *DockerContainer) KeepForDebugging() {
|
||||
if d == nil {
|
||||
return
|
||||
}
|
||||
|
||||
d.keepForDebugging = true
|
||||
}
|
||||
|
||||
func (d *DockerContainer) Remove() error {
|
||||
if d == nil {
|
||||
return errors.New("Cannot remove a nil *DockerContainer")
|
||||
}
|
||||
|
||||
if d.keepForDebugging {
|
||||
return nil
|
||||
}
|
||||
|
||||
if len(d.ContainerId) == 0 {
|
||||
return fmt.Errorf("missing containerId")
|
||||
return errors.New("missing containerId")
|
||||
}
|
||||
if err := d.client.ContainerRemove(context.Background(), d.ContainerId,
|
||||
dockertypes.ContainerRemoveOptions{
|
||||
|
@ -142,8 +158,12 @@ func (d *DockerContainer) Remove() error {
|
|||
}
|
||||
|
||||
func (d *DockerContainer) Inspect() error {
|
||||
if d == nil {
|
||||
return errors.New("Cannot inspect a nil *DockerContainer")
|
||||
}
|
||||
|
||||
if len(d.ContainerId) == 0 {
|
||||
return fmt.Errorf("missing containerId")
|
||||
return errors.New("missing containerId")
|
||||
}
|
||||
resp, err := d.client.ContainerInspect(context.Background(), d.ContainerId)
|
||||
if err != nil {
|
||||
|
@ -156,8 +176,11 @@ func (d *DockerContainer) Inspect() error {
|
|||
}
|
||||
|
||||
func (d *DockerContainer) Logs() (io.ReadCloser, error) {
|
||||
if d == nil {
|
||||
return nil, errors.New("Cannot view logs for a nil *DockerContainer")
|
||||
}
|
||||
if len(d.ContainerId) == 0 {
|
||||
return nil, fmt.Errorf("missing containerId")
|
||||
return nil, errors.New("missing containerId")
|
||||
}
|
||||
|
||||
return d.client.ContainerLogs(context.Background(), d.ContainerId, dockertypes.ContainerLogsOptions{
|
||||
|
@ -190,13 +213,16 @@ func (d *DockerContainer) portMapping(selectFirst bool, cPort int) (containerPor
|
|||
}
|
||||
|
||||
if selectFirst {
|
||||
return 0, "", 0, fmt.Errorf("no port binding")
|
||||
return 0, "", 0, errors.New("no port binding")
|
||||
} else {
|
||||
return 0, "", 0, fmt.Errorf("specified port not bound")
|
||||
return 0, "", 0, errors.New("specified port not bound")
|
||||
}
|
||||
}
|
||||
|
||||
func (d *DockerContainer) Host() string {
|
||||
if d == nil {
|
||||
panic("Cannot get host for a nil *DockerContainer")
|
||||
}
|
||||
_, hostIP, _, err := d.portMapping(true, -1)
|
||||
if err != nil {
|
||||
d.t.Fatal(err)
|
||||
|
@ -210,6 +236,9 @@ func (d *DockerContainer) Host() string {
|
|||
}
|
||||
|
||||
func (d *DockerContainer) Port() uint {
|
||||
if d == nil {
|
||||
panic("Cannot get port for a nil *DockerContainer")
|
||||
}
|
||||
_, _, port, err := d.portMapping(true, -1)
|
||||
if err != nil {
|
||||
d.t.Fatal(err)
|
||||
|
@ -218,6 +247,9 @@ func (d *DockerContainer) Port() uint {
|
|||
}
|
||||
|
||||
func (d *DockerContainer) PortFor(cPort int) uint {
|
||||
if d == nil {
|
||||
panic("Cannot get port for a nil *DockerContainer")
|
||||
}
|
||||
_, _, port, err := d.portMapping(false, cPort)
|
||||
if err != nil {
|
||||
d.t.Fatal(err)
|
||||
|
@ -226,6 +258,9 @@ func (d *DockerContainer) PortFor(cPort int) uint {
|
|||
}
|
||||
|
||||
func (d *DockerContainer) NetworkSettings() dockertypes.NetworkSettings {
|
||||
if d == nil {
|
||||
panic("Cannot get network settings for a nil *DockerContainer")
|
||||
}
|
||||
netSettings := d.ContainerJSON.NetworkSettings
|
||||
return *netSettings
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@ type Version struct {
|
|||
}
|
||||
|
||||
func ParallelTest(t *testing.T, versions []Version, readyFn IsReadyFunc, testFn TestFunc) {
|
||||
delay, err := strconv.Atoi(os.Getenv("MIGRATE_TEST_CONTAINER_BOOT_DELAY"))
|
||||
timeout, err := strconv.Atoi(os.Getenv("MIGRATE_TEST_CONTAINER_BOOT_TIMEOUT"))
|
||||
if err != nil {
|
||||
delay = 0
|
||||
timeout = 60 // Cassandra docker image can take ~30s to start
|
||||
}
|
||||
|
||||
for i, version := range versions {
|
||||
|
@ -49,8 +49,8 @@ func ParallelTest(t *testing.T, versions []Version, readyFn IsReadyFunc, testFn
|
|||
|
||||
// wait until database is ready
|
||||
tick := time.Tick(1000 * time.Millisecond)
|
||||
timeout := time.After(time.Duration(delay + 60) * time.Second)
|
||||
outer:
|
||||
timeout := time.After(time.Duration(timeout) * time.Second)
|
||||
outer:
|
||||
for {
|
||||
select {
|
||||
case <-tick:
|
||||
|
@ -63,8 +63,6 @@ func ParallelTest(t *testing.T, versions []Version, readyFn IsReadyFunc, testFn
|
|||
}
|
||||
}
|
||||
|
||||
time.Sleep(time.Duration(int64(delay)) * time.Second)
|
||||
|
||||
// we can now run the tests
|
||||
testFn(t, container)
|
||||
})
|
||||
|
@ -75,13 +73,13 @@ func ParallelTest(t *testing.T, versions []Version, readyFn IsReadyFunc, testFn
|
|||
func containerLogs(t *testing.T, c *DockerContainer) []byte {
|
||||
r, err := c.Logs()
|
||||
if err != nil {
|
||||
t.Error("%v", err)
|
||||
t.Error(err)
|
||||
return nil
|
||||
}
|
||||
defer r.Close()
|
||||
b, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
t.Error("%v", err)
|
||||
t.Error(err)
|
||||
return nil
|
||||
}
|
||||
return b
|
||||
|
|
32
util.go
32
util.go
|
@ -1,12 +1,9 @@
|
|||
package migrate
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
nurl "net/url"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// MultiError holds multiple errors.
|
||||
|
@ -46,35 +43,6 @@ func suint(n int) uint {
|
|||
return uint(n)
|
||||
}
|
||||
|
||||
// newSlowReader turns an io.ReadCloser into a slow io.ReadCloser.
|
||||
// Use this to simulate a slow internet connection.
|
||||
func newSlowReader(r io.ReadCloser) io.ReadCloser {
|
||||
return &slowReader{
|
||||
rx: r,
|
||||
reader: bufio.NewReader(r),
|
||||
}
|
||||
}
|
||||
|
||||
type slowReader struct {
|
||||
rx io.ReadCloser
|
||||
reader *bufio.Reader
|
||||
}
|
||||
|
||||
func (b *slowReader) Read(p []byte) (n int, err error) {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
c, err := b.reader.ReadByte()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
} else {
|
||||
copy(p, []byte{c})
|
||||
return 1, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (b *slowReader) Close() error {
|
||||
return b.rx.Close()
|
||||
}
|
||||
|
||||
var errNoScheme = fmt.Errorf("no scheme")
|
||||
|
||||
// schemeFromUrl returns the scheme from a URL string
|
||||
|
|
Loading…
Reference in New Issue