Skip to content

Commit e81d08a

Browse files
Prometheus2677Doctor-X
authored andcommitted
Add Bitbucket Cloud Support as source (#450)
* Added bitbucket cloud support as source for migration * added test * address PR Comments * Add entry in README.md; update go.mod and go.sum Co-authored-by: abhigupta91 <[email protected]>
1 parent e84d6a9 commit e81d08a

File tree

9 files changed

+282
-1
lines changed

9 files changed

+282
-1
lines changed

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
SOURCE ?= file go_bindata github github_ee aws_s3 google_cloud_storage godoc_vfs gitlab
1+
SOURCE ?= file go_bindata github github_ee bitbucket aws_s3 google_cloud_storage godoc_vfs gitlab
22
DATABASE ?= postgres mysql redshift cassandra spanner cockroachdb clickhouse mongodb sqlserver firebird neo4j
33
DATABASE_TEST ?= $(DATABASE) sqlite sqlcipher
44
VERSION ?= $(shell git describe --tags 2>/dev/null | cut -c 2-)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ Source drivers read migrations from local or remote sources. [Add a new source?]
6969
* [Go-Bindata](source/go_bindata) - read from embedded binary data ([jteeuwen/go-bindata](https://github.com/jteeuwen/go-bindata))
7070
* [GitHub](source/github) - read from remote GitHub repositories
7171
* [GitHub Enterprise](source/github_ee) - read from remote GitHub Enterprise repositories
72+
* [Bitbucket](source/bitbucket) - read from remote Bitbucket repositories
7273
* [Gitlab](source/gitlab) - read from remote Gitlab repositories
7374
* [AWS S3](source/aws_s3) - read from Amazon Web Services S3
7475
* [Google Cloud Storage](source/google_cloud_storage) - read from Google Cloud Platform Storage

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ require (
2929
github.com/hashicorp/go-multierror v1.1.0
3030
github.com/jackc/pgconn v1.3.2 // indirect
3131
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
32+
github.com/ktrysmt/go-bitbucket v0.6.4
3233
github.com/lib/pq v1.3.0
3334
github.com/markbates/pkger v0.15.1
3435
github.com/mattn/go-sqlite3 v1.10.0

go.sum

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
150150
github.com/golang/mock v1.4.3 h1:GV+pQPG/EUUbkh47niozDcADz6go/dUwhVzdUQHIVRw=
151151
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
152152
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
153+
github.com/golang/protobuf v1.0.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
153154
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
154155
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
155156
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -262,6 +263,9 @@ github.com/jmoiron/sqlx v1.2.0/go.mod h1:1FEQNm3xlJgrMD+FBdI9+xvCksHtbpVBBw5dYhB
262263
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
263264
github.com/jstemmer/go-junit-report v0.9.1 h1:6QPYqodiu3GuPL+7mfx+NwDdp2eTkp9IfEUpgAwUN0o=
264265
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
266+
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88/go.mod h1:3w7q1U84EfirKl04SVQ/s7nPm1ZPhiXd34z40TNz36k=
267+
github.com/k0kubun/pp v2.3.0+incompatible h1:EKhKbi34VQDWJtq+zpsKSEhkHHs9w2P8Izbq8IhLVSo=
268+
github.com/k0kubun/pp v2.3.0+incompatible/go.mod h1:GWse8YhT0p8pT4ir3ZgBbfZild3tgzSScAn6HmfYukg=
265269
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
266270
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
267271
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
@@ -275,19 +279,27 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
275279
github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
276280
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
277281
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
282+
github.com/ktrysmt/go-bitbucket v0.6.4 h1:C8dUGp0qkwncKtAnozHCbbqhptefzEd1I0sfnuy9rYQ=
283+
github.com/ktrysmt/go-bitbucket v0.6.4/go.mod h1:9u0v3hsd2rqCHRIpbir1oP7F58uo5dq19sBYvuMoyQ4=
278284
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
279285
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
280286
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
281287
github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU=
282288
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
283289
github.com/markbates/pkger v0.15.1 h1:3MPelV53RnGSW07izx5xGxl4e/sdRD6zqseIk0rMASY=
284290
github.com/markbates/pkger v0.15.1/go.mod h1:0JoVlrol20BSywW79rN3kdFFsE5xYM+rSCQDXbLhiuI=
291+
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
292+
github.com/mattn/go-colorable v0.1.1 h1:G1f5SKeVxmagw/IyvzvtZE4Gybcc4Tr1tf7I8z0XgOg=
285293
github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ=
294+
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
286295
github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
296+
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
287297
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
288298
github.com/mattn/go-sqlite3 v1.9.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
289299
github.com/mattn/go-sqlite3 v1.10.0 h1:jbhqpg7tQe4SupckyijYiy0mJJ/pRyHvXf7JdWK860o=
290300
github.com/mattn/go-sqlite3 v1.10.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
301+
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238 h1:+MZW2uvHgN8kYvksEN3f7eFL2wpzk0GxmlFsMybWc7E=
302+
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
291303
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
292304
github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
293305
github.com/mutecomm/go-sqlcipher/v4 v4.4.0 h1:sV1tWCWGAVlPhNGT95Q+z/txFxuhAYWwHD1afF5bMZg=
@@ -421,6 +433,7 @@ golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
421433
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
422434
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
423435
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
436+
golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
424437
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
425438
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
426439
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -456,6 +469,7 @@ golang.org/x/net v0.0.0-20200707034311-ab3426394381 h1:VXak5I6aEWmAXeQjA+QSZzlgN
456469
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
457470
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc h1:zK/HqS5bZxDptfPJNq8v7vJfXtkU7r9TLIoSr1bXaP4=
458471
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
472+
golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
459473
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
460474
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
461475
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -474,6 +488,7 @@ golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a h1:WXEvlFVvvGxCJLG6REjsT03i
474488
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
475489
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208 h1:qwRHBd0NqMbJxfbotnDhm2ByMI1Shq4Y6oRJo21SGJA=
476490
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
491+
golang.org/x/sys v0.0.0-20180224232135-f6cff0780e54/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
477492
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
478493
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
479494
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -602,6 +617,7 @@ google.golang.org/api v0.29.0 h1:BaiDisFir8O4IJxvAabCGGkQ6yCJegNQqSVoYUNAnbk=
602617
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
603618
google.golang.org/api v0.30.0 h1:yfrXXP61wVuLb0vBcG6qaOoIoqYEzOQS8jum51jkv2w=
604619
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
620+
google.golang.org/appengine v1.0.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
605621
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
606622
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
607623
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=

internal/cli/build_bitbucket.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// +build bitbucket
2+
3+
package cli
4+
5+
import (
6+
_ "github.com/golang-migrate/migrate/v4/source/bitbucket"
7+
)

source/bitbucket/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.bitbucket_test_secrets

source/bitbucket/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# bitbucket
2+
3+
This driver is catered for those that want to source migrations from bitbucket cloud(https://bitbucket.com).
4+
5+
`bitbucket://user:password@owner/repo/path#ref`
6+
7+
| URL Query | WithInstance Config | Description |
8+
|------------|---------------------|-------------|
9+
| user | | The username of the user connecting |
10+
| password | | User's password or an app password with repo read permission |
11+
| owner | | the repo owner |
12+
| repo | | the name of the repository |
13+
| path | | path in repo to migrations |
14+
| ref | | (optional) can be a SHA, branch, or tag |

source/bitbucket/bitbucket.go

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
package bitbucket
2+
3+
import (
4+
"fmt"
5+
"io"
6+
"io/ioutil"
7+
nurl "net/url"
8+
"os"
9+
"path"
10+
"path/filepath"
11+
"strings"
12+
13+
"github.com/golang-migrate/migrate/v4/source"
14+
"github.com/ktrysmt/go-bitbucket"
15+
)
16+
17+
func init() {
18+
source.Register("bitbucket", &Bitbucket{})
19+
}
20+
21+
var (
22+
ErrNoUserInfo = fmt.Errorf("no username:password provided")
23+
ErrNoAccessToken = fmt.Errorf("no password/app password")
24+
ErrInvalidRepo = fmt.Errorf("invalid repo")
25+
ErrInvalidBitbucketClient = fmt.Errorf("expected *bitbucket.Client")
26+
ErrNoDir = fmt.Errorf("no directory")
27+
)
28+
29+
type Bitbucket struct {
30+
config *Config
31+
client *bitbucket.Client
32+
migrations *source.Migrations
33+
}
34+
35+
type Config struct {
36+
Owner string
37+
Repo string
38+
Path string
39+
Ref string
40+
}
41+
42+
func (b *Bitbucket) Open(url string) (source.Driver, error) {
43+
u, err := nurl.Parse(url)
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
if u.User == nil {
49+
return nil, ErrNoUserInfo
50+
}
51+
52+
password, ok := u.User.Password()
53+
if !ok {
54+
return nil, ErrNoAccessToken
55+
}
56+
57+
cl := bitbucket.NewBasicAuth(u.User.Username(), password)
58+
59+
cfg := &Config{}
60+
// set owner, repo and path in repo
61+
cfg.Owner = u.Host
62+
pe := strings.Split(strings.Trim(u.Path, "/"), "/")
63+
if len(pe) < 1 {
64+
return nil, ErrInvalidRepo
65+
}
66+
cfg.Repo = pe[0]
67+
if len(pe) > 1 {
68+
cfg.Path = strings.Join(pe[1:], "/")
69+
}
70+
cfg.Ref = u.Fragment
71+
72+
bi, err := WithInstance(cl, cfg)
73+
if err != nil {
74+
return nil, err
75+
}
76+
77+
return bi, nil
78+
}
79+
80+
func WithInstance(client *bitbucket.Client, config *Config) (source.Driver, error) {
81+
bi := &Bitbucket{
82+
client: client,
83+
config: config,
84+
migrations: source.NewMigrations(),
85+
}
86+
87+
if err := bi.readDirectory(); err != nil {
88+
return nil, err
89+
}
90+
91+
return bi, nil
92+
}
93+
94+
func (b *Bitbucket) readDirectory() error {
95+
b.ensureFields()
96+
97+
fOpt := &bitbucket.RepositoryFilesOptions{
98+
Owner: b.config.Owner,
99+
RepoSlug: b.config.Repo,
100+
Ref: b.config.Ref,
101+
Path: b.config.Path,
102+
}
103+
104+
dirContents, err := b.client.Repositories.Repository.ListFiles(fOpt)
105+
106+
if err != nil {
107+
return err
108+
}
109+
110+
for _, fi := range dirContents {
111+
112+
m, err := source.DefaultParse(filepath.Base(fi.Path))
113+
if err != nil {
114+
continue // ignore files that we can't parse
115+
}
116+
if !b.migrations.Append(m) {
117+
return fmt.Errorf("unable to parse file %v", fi.Path)
118+
}
119+
}
120+
121+
return nil
122+
}
123+
124+
func (b *Bitbucket) ensureFields() {
125+
if b.config == nil {
126+
b.config = &Config{}
127+
}
128+
}
129+
130+
func (b *Bitbucket) Close() error {
131+
return nil
132+
}
133+
134+
func (b *Bitbucket) First() (version uint, er error) {
135+
b.ensureFields()
136+
137+
if v, ok := b.migrations.First(); !ok {
138+
return 0, &os.PathError{Op: "first", Path: b.config.Path, Err: os.ErrNotExist}
139+
} else {
140+
return v, nil
141+
}
142+
}
143+
144+
func (b *Bitbucket) Prev(version uint) (prevVersion uint, err error) {
145+
b.ensureFields()
146+
147+
if v, ok := b.migrations.Prev(version); !ok {
148+
return 0, &os.PathError{Op: fmt.Sprintf("prev for version %v", version), Path: b.config.Path, Err: os.ErrNotExist}
149+
} else {
150+
return v, nil
151+
}
152+
}
153+
154+
func (b *Bitbucket) Next(version uint) (nextVersion uint, err error) {
155+
b.ensureFields()
156+
157+
if v, ok := b.migrations.Next(version); !ok {
158+
return 0, &os.PathError{Op: fmt.Sprintf("next for version %v", version), Path: b.config.Path, Err: os.ErrNotExist}
159+
} else {
160+
return v, nil
161+
}
162+
}
163+
164+
func (b *Bitbucket) ReadUp(version uint) (r io.ReadCloser, identifier string, err error) {
165+
b.ensureFields()
166+
167+
if m, ok := b.migrations.Up(version); ok {
168+
fBlobOpt := &bitbucket.RepositoryBlobOptions{
169+
Owner: b.config.Owner,
170+
RepoSlug: b.config.Repo,
171+
Ref: b.config.Ref,
172+
Path: path.Join(b.config.Path, m.Raw),
173+
}
174+
file, err := b.client.Repositories.Repository.GetFileBlob(fBlobOpt)
175+
if err != nil {
176+
return nil, "", err
177+
}
178+
if file != nil {
179+
r := file.Content
180+
return ioutil.NopCloser(strings.NewReader(string(r))), m.Identifier, nil
181+
}
182+
}
183+
return nil, "", &os.PathError{Op: fmt.Sprintf("read version %v", version), Path: b.config.Path, Err: os.ErrNotExist}
184+
}
185+
186+
func (b *Bitbucket) ReadDown(version uint) (r io.ReadCloser, identifier string, err error) {
187+
b.ensureFields()
188+
189+
if m, ok := b.migrations.Down(version); ok {
190+
fBlobOpt := &bitbucket.RepositoryBlobOptions{
191+
Owner: b.config.Owner,
192+
RepoSlug: b.config.Repo,
193+
Ref: b.config.Ref,
194+
Path: path.Join(b.config.Path, m.Raw),
195+
}
196+
file, err := b.client.Repositories.Repository.GetFileBlob(fBlobOpt)
197+
198+
if err != nil {
199+
return nil, "", err
200+
}
201+
if file != nil {
202+
r := file.Content
203+
204+
return ioutil.NopCloser(strings.NewReader(string(r))), m.Identifier, nil
205+
}
206+
}
207+
return nil, "", &os.PathError{Op: fmt.Sprintf("read version %v", version), Path: b.config.Path, Err: os.ErrNotExist}
208+
}

source/bitbucket/bitbucket_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package bitbucket
2+
3+
import (
4+
"bytes"
5+
"io/ioutil"
6+
"testing"
7+
8+
st "github.com/golang-migrate/migrate/v4/source/testing"
9+
)
10+
11+
var BitbucketTestSecret = "" // username:password
12+
13+
func init() {
14+
secrets, err := ioutil.ReadFile(".bitbucket_test_secrets")
15+
if err == nil {
16+
BitbucketTestSecret = string(bytes.TrimSpace(secrets)[:])
17+
}
18+
}
19+
20+
func Test(t *testing.T) {
21+
if len(BitbucketTestSecret) == 0 {
22+
t.Skip("test requires .bitbucket_test_secrets")
23+
}
24+
25+
b := &Bitbucket{}
26+
27+
d, err := b.Open("bitbucket://" + BitbucketTestSecret + "@abhishekbipp/test-migration/migrations/test#master")
28+
if err != nil {
29+
t.Fatal(err)
30+
}
31+
32+
st.Test(t, d)
33+
}

0 commit comments

Comments
 (0)