db-migrate 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.rspec +2 -0
- data/.travis.yml +6 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +46 -0
- data/LICENSE +20 -0
- data/README.md +60 -0
- data/bin/migrate +136 -0
- data/lib/migrate.rb +9 -0
- data/lib/migrate/config.rb +104 -0
- data/lib/migrate/errors.rb +4 -0
- data/lib/migrate/lang.rb +10 -0
- data/lib/migrate/lang/go.rb +37 -0
- data/lib/migrate/lang/javascript.rb +25 -0
- data/lib/migrate/lang/lang.rb +15 -0
- data/lib/migrate/lang/python.rb +25 -0
- data/lib/migrate/lang/ruby.rb +25 -0
- data/lib/migrate/lang/sql.rb +26 -0
- data/lib/migrate/logger.rb +39 -0
- data/lib/migrate/migrator.rb +144 -0
- data/lib/migrate/storage.rb +7 -0
- data/lib/migrate/storage/db.rb +150 -0
- data/lib/migrate/storage/mysql.rb +77 -0
- data/lib/migrate/storage/postgres.rb +74 -0
- data/migrate.gemspec +21 -0
- data/spec/lib/config_spec.rb +103 -0
- data/spec/lib/fixtures/go/down.go +7 -0
- data/spec/lib/fixtures/go/up.go +7 -0
- data/spec/lib/fixtures/js/down.js +1 -0
- data/spec/lib/fixtures/js/up.js +1 -0
- data/spec/lib/fixtures/py/down.py +1 -0
- data/spec/lib/fixtures/py/up.py +1 -0
- data/spec/lib/fixtures/rb/down.rb +1 -0
- data/spec/lib/fixtures/rb/up.rb +1 -0
- data/spec/lib/fixtures/sql/down.sql +1 -0
- data/spec/lib/fixtures/sql/up.sql +1 -0
- data/spec/lib/lang/lang_spec.rb +46 -0
- data/spec/lib/migrator_spec.rb +103 -0
- data/spec/lib/storage/db_spec.rb +104 -0
- data/spec/spec_helper.rb +109 -0
- metadata +184 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9d20012ab53ae15b7b98fec15bb8eae3abd9914e
|
4
|
+
data.tar.gz: e02941b8c31643efaa71774d67b22aba0c4f2bc8
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 6d316f5e858dcdfad7e16449cd78abf3a8a44e51111cb26411467d89bdbaf2cf8900728abebe1f697d05b6553e1dd8839400957ba310d9bb4e4b6066625c13ce
|
7
|
+
data.tar.gz: 8538758ab5dc8d23e9b1923b777187cbb7321d58e7efbe97bd26aa3fca37f32a033bfe795bb6d56f2830e46d9141fc3ee85572cf1a42ade898fe19dd5cc822a6
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
migrate (0.0.1)
|
5
|
+
colorize (= 0.7.7)
|
6
|
+
highline (= 1.7.8)
|
7
|
+
json (= 1.8.3)
|
8
|
+
mysql2 (= 0.4.2)
|
9
|
+
parseconfig (= 1.0.6)
|
10
|
+
pg (= 0.18.4)
|
11
|
+
thor (= 0.19.1)
|
12
|
+
|
13
|
+
GEM
|
14
|
+
remote: https://rubygems.org/
|
15
|
+
specs:
|
16
|
+
colorize (0.7.7)
|
17
|
+
diff-lcs (1.2.5)
|
18
|
+
highline (1.7.8)
|
19
|
+
json (1.8.3)
|
20
|
+
mysql2 (0.4.2)
|
21
|
+
parseconfig (1.0.6)
|
22
|
+
pg (0.18.4)
|
23
|
+
rspec (3.4.0)
|
24
|
+
rspec-core (~> 3.4.0)
|
25
|
+
rspec-expectations (~> 3.4.0)
|
26
|
+
rspec-mocks (~> 3.4.0)
|
27
|
+
rspec-core (3.4.1)
|
28
|
+
rspec-support (~> 3.4.0)
|
29
|
+
rspec-expectations (3.4.0)
|
30
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
31
|
+
rspec-support (~> 3.4.0)
|
32
|
+
rspec-mocks (3.4.0)
|
33
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
34
|
+
rspec-support (~> 3.4.0)
|
35
|
+
rspec-support (3.4.1)
|
36
|
+
thor (0.19.1)
|
37
|
+
|
38
|
+
PLATFORMS
|
39
|
+
ruby
|
40
|
+
|
41
|
+
DEPENDENCIES
|
42
|
+
migrate!
|
43
|
+
rspec
|
44
|
+
|
45
|
+
BUNDLED WITH
|
46
|
+
1.10.6
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Ivan Pusic
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# migrate
|
2
|
+
|
3
|
+
Tool for managing and executing your database migrations.
|
4
|
+
|
5
|
+
### How it works?
|
6
|
+
It saves metadata about your migrations to database. It uses that metadata for executing and creating new migrations.
|
7
|
+
|
8
|
+
It supports multiple databases and multiple languages for executing migrations.
|
9
|
+
|
10
|
+
#### Supported databases
|
11
|
+
- PostgreSQL
|
12
|
+
- MySQL
|
13
|
+
|
14
|
+
#### Supported languages
|
15
|
+
- SQL
|
16
|
+
- Ruby
|
17
|
+
- Python
|
18
|
+
- Javascript (Node.js)
|
19
|
+
- Go
|
20
|
+
|
21
|
+
### What I can do with it?
|
22
|
+
```
|
23
|
+
Commands:
|
24
|
+
migrate init # make configuration file
|
25
|
+
migrate new [DESCRIPTION] # generate files for new migration
|
26
|
+
migrate up # Upgrade database schema
|
27
|
+
migrate down # Downgrade database schema
|
28
|
+
migrate list # Show list of all migrations
|
29
|
+
migrate delete [VERSION] # Will delete migration data
|
30
|
+
migrate version # Show current version
|
31
|
+
migrate help [COMMAND] # Describe available commands or one specific
|
32
|
+
Options:
|
33
|
+
-r, [--root=ROOT] # Sepcify migration root directory, where config file is located
|
34
|
+
# Default: .
|
35
|
+
-c, [--config=CONFIG] # Specify custom configuration file name
|
36
|
+
# Default: migrate.conf
|
37
|
+
```
|
38
|
+
|
39
|
+
### How to use it?
|
40
|
+
|
41
|
+
First thing you have to do is to make initial configuration with **migrate init** command.
|
42
|
+
After that you can start generating migrations by using **migrate new** command. This will generate migration script for you based on your prefered language.
|
43
|
+
|
44
|
+
When you are done with writing your `up` and `down` migration script, you can execute **migrate up** to run up migration script for new version. You can also execute multiple migrations in single call by providing `--to n` argument, where `n` is highest version where you want to navigate.
|
45
|
+
|
46
|
+
You can also use **migrate down** to go one version back. `down` comand also accepts `--to n` argument, but in this case `n` is lowest version where you want to navigate.
|
47
|
+
|
48
|
+
If you are asking yourself about current version, use **migrate version** to find out current version.
|
49
|
+
|
50
|
+
If you don't need some migration, use **migrate delete n** to remove version `n`.
|
51
|
+
|
52
|
+
You can see list of your migrations by running **migrate list**. This command also provides some additional options for filtering results.
|
53
|
+
|
54
|
+
## Contributing
|
55
|
+
- do ruby magic
|
56
|
+
- write tests!
|
57
|
+
- send pull request
|
58
|
+
|
59
|
+
## License
|
60
|
+
*MIT*
|
data/bin/migrate
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "thor"
|
4
|
+
require "json"
|
5
|
+
require "highline"
|
6
|
+
require_relative "../lib/migrate"
|
7
|
+
|
8
|
+
include Migrate
|
9
|
+
$asker = HighLine.new
|
10
|
+
|
11
|
+
class CLI < Thor
|
12
|
+
method_option :root, {
|
13
|
+
:aliases => "-r",
|
14
|
+
:default => ".",
|
15
|
+
:desc => "Sepcify migration root directory, where config file is located"
|
16
|
+
}
|
17
|
+
method_option :config, {
|
18
|
+
:aliases => "-c",
|
19
|
+
:default => "migrate.conf",
|
20
|
+
:desc => "Specify custom configuration file name"
|
21
|
+
}
|
22
|
+
def initialize(*args)
|
23
|
+
super
|
24
|
+
@config = Config.new(options["root"], options["config"])
|
25
|
+
|
26
|
+
init_invoked = ARGV.length > 0 && ARGV[0] == "init"
|
27
|
+
if not init_invoked and @config.exists?
|
28
|
+
@config.load!
|
29
|
+
@migrator = Migrator.new(@config)
|
30
|
+
elsif not init_invoked
|
31
|
+
Log.error("Configuration not found in `#{Pathname.new(@config.root).expand_path}`. " \
|
32
|
+
"Make sure you are in right directory or " \
|
33
|
+
"run `migrate init` to create configuration.")
|
34
|
+
exit
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
desc "init", "make configuration file"
|
39
|
+
def init
|
40
|
+
Log.info("Creating configuration...")
|
41
|
+
|
42
|
+
storage = nil
|
43
|
+
$asker.choose do |menu|
|
44
|
+
menu.prompt = "Which database do you prefer?"
|
45
|
+
|
46
|
+
menu.choice(:mysql) { storage = "mysql" }
|
47
|
+
menu.choices(:pg) { storage = "pg" }
|
48
|
+
end
|
49
|
+
|
50
|
+
db_defaults = case storage
|
51
|
+
when "mysql"
|
52
|
+
{ :port => "3306", :user => "root" }
|
53
|
+
when "pg"
|
54
|
+
{ :port => "5432", :user => "postgres" }
|
55
|
+
end
|
56
|
+
|
57
|
+
lang = nil
|
58
|
+
$asker.choose do |menu|
|
59
|
+
menu.prompt = "What language would you like use for your migration scripts?"
|
60
|
+
|
61
|
+
menu.choice(:sql) { lang = "sql" }
|
62
|
+
menu.choices(:ruby) { lang = "ruby" }
|
63
|
+
menu.choice(:javascript) { lang = "javascript" }
|
64
|
+
menu.choice(:go) { lang = "go" }
|
65
|
+
menu.choice(:python) { lang = "python" }
|
66
|
+
end
|
67
|
+
|
68
|
+
config = {
|
69
|
+
storage: storage,
|
70
|
+
lang: lang,
|
71
|
+
host: $asker.ask("Host: ") {|q| q.default = "localhost"},
|
72
|
+
port: ($asker.ask("Port: ") {|q| q.default = db_defaults[:port]}).to_i,
|
73
|
+
database: $asker.ask("Database Name: ") {|q| q.default = "mydb"},
|
74
|
+
user: $asker.ask("User: ") {|q| q.default = db_defaults[:user]},
|
75
|
+
password: $asker.ask("Password: ") {|q| q.default = nil},
|
76
|
+
version_info: $asker.ask("Version info table: ") {|q| q.default = "version_info"},
|
77
|
+
version_number: $asker.ask("Version number table: ") {|q| q.default = "version_number"}
|
78
|
+
}
|
79
|
+
|
80
|
+
@config.init(config)
|
81
|
+
@config.load!
|
82
|
+
Migrator.new(@config).init
|
83
|
+
rescue Exception => e
|
84
|
+
Log.error("Error while initialization.", e)
|
85
|
+
@config.remove
|
86
|
+
exit
|
87
|
+
end
|
88
|
+
|
89
|
+
desc "new [DESCRIPTION]", "generate files for new migration"
|
90
|
+
def new(description="")
|
91
|
+
@migrator.new(description)
|
92
|
+
end
|
93
|
+
|
94
|
+
desc "up", "Upgrade database schema"
|
95
|
+
option :to, :aliases => "-t", :desc => "Upgrade to the version"
|
96
|
+
def up
|
97
|
+
@migrator.up(options[:to])
|
98
|
+
rescue VersionNotFound => e
|
99
|
+
Log.error("Next version not found.")
|
100
|
+
rescue Exception => e
|
101
|
+
Log.error("Error while migrating up.", e)
|
102
|
+
end
|
103
|
+
|
104
|
+
desc "down [TO_VERSION]", "Downgrade database schema"
|
105
|
+
option :to, :aliases => "-t", :desc => "Downgrade back to the version"
|
106
|
+
def down
|
107
|
+
@migrator.down(options[:to])
|
108
|
+
rescue VersionNotFound => e
|
109
|
+
Log.error("Previous version not found.")
|
110
|
+
rescue Exception => e
|
111
|
+
Log.error("Error while migrating down.", e)
|
112
|
+
end
|
113
|
+
|
114
|
+
desc "list", "Show list of all migrations"
|
115
|
+
option :limit, :aliases => "-l", :desc => "Limit results"
|
116
|
+
option :select, :aliases => "-s", :desc => "Columns to select"
|
117
|
+
def list()
|
118
|
+
@migrator.list(options[:select], options[:limit])
|
119
|
+
end
|
120
|
+
|
121
|
+
desc "delete [VERSION]", "Will delete migration data"
|
122
|
+
def delete(version)
|
123
|
+
@migrator.delete(version.to_i)
|
124
|
+
rescue VersionNotFound
|
125
|
+
Log.error("Version not found.")
|
126
|
+
rescue Exception => e
|
127
|
+
Log.error("Error while removing migration.", e)
|
128
|
+
end
|
129
|
+
|
130
|
+
desc "version", "Show current version"
|
131
|
+
def version()
|
132
|
+
Log.version(@migrator.current_version())
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
CLI.start
|
data/lib/migrate.rb
ADDED
@@ -0,0 +1,104 @@
|
|
1
|
+
require "parseconfig"
|
2
|
+
|
3
|
+
module Migrate
|
4
|
+
class Config
|
5
|
+
attr_reader :root
|
6
|
+
|
7
|
+
def initialize(root, file)
|
8
|
+
@root = root
|
9
|
+
@file=file
|
10
|
+
@file_path = "#{root}/#{file}"
|
11
|
+
@loaded = false
|
12
|
+
end
|
13
|
+
|
14
|
+
def exists?
|
15
|
+
File.exist? @file_path
|
16
|
+
end
|
17
|
+
|
18
|
+
def init(config)
|
19
|
+
if not Dir.exist? @root
|
20
|
+
Dir.mkdir @root
|
21
|
+
end
|
22
|
+
|
23
|
+
File.open(@file_path, "w") do |f|
|
24
|
+
config.map do |key, value|
|
25
|
+
f.puts "#{key}=#{value}\n"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Log.success("Configuration file created. Location: `#{@file_path}`")
|
30
|
+
end
|
31
|
+
|
32
|
+
def load!
|
33
|
+
Log.info("Loading configuration...")
|
34
|
+
config = ParseConfig.new(@file_path)
|
35
|
+
|
36
|
+
config.get_params.map do |param|
|
37
|
+
self.class.send(:attr_reader, param)
|
38
|
+
instance_variable_set("@#{param}", config[param])
|
39
|
+
end
|
40
|
+
|
41
|
+
@loaded = true
|
42
|
+
Log.success("Configuration loaded.")
|
43
|
+
end
|
44
|
+
|
45
|
+
def delete
|
46
|
+
File.delete @file_path
|
47
|
+
rescue Exception => e
|
48
|
+
Log.error("Error while removing configuration file.", e)
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
def get_db
|
53
|
+
case @storage
|
54
|
+
when "pg"
|
55
|
+
if @pg == nil
|
56
|
+
@pg = Storage::Postgres.new(self)
|
57
|
+
end
|
58
|
+
|
59
|
+
@pg
|
60
|
+
when "mysql"
|
61
|
+
if @mysql == nil
|
62
|
+
@mysql = Storage::Mysql.new(self)
|
63
|
+
end
|
64
|
+
|
65
|
+
@mysql
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_lang
|
70
|
+
case @lang
|
71
|
+
when "sql"
|
72
|
+
if @sql == nil
|
73
|
+
@sql = Lang::Sql.new(get_db)
|
74
|
+
end
|
75
|
+
|
76
|
+
@sql
|
77
|
+
when "javascript"
|
78
|
+
if @javascript == nil
|
79
|
+
@javascript = Lang::Javascript.new
|
80
|
+
end
|
81
|
+
|
82
|
+
@javascript
|
83
|
+
when "ruby"
|
84
|
+
if @ruby == nil
|
85
|
+
@ruby = Lang::Ruby.new
|
86
|
+
end
|
87
|
+
|
88
|
+
@ruby
|
89
|
+
when "go"
|
90
|
+
if @go == nil
|
91
|
+
@go = Lang::Go.new
|
92
|
+
end
|
93
|
+
|
94
|
+
@go
|
95
|
+
when "python"
|
96
|
+
if @python == nil
|
97
|
+
@python = Lang::Python.new
|
98
|
+
end
|
99
|
+
|
100
|
+
@python
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
data/lib/migrate/lang.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
module Migrate
|
2
|
+
module Lang
|
3
|
+
class Go < Lang
|
4
|
+
def initialize
|
5
|
+
@ext = "go"
|
6
|
+
end
|
7
|
+
|
8
|
+
def create_migration(dir)
|
9
|
+
File.open("#{dir}/up.#{@ext}", "w") do |f|
|
10
|
+
f.puts <<-eot
|
11
|
+
package main
|
12
|
+
|
13
|
+
func main() {
|
14
|
+
// Here goes your Go migration forward
|
15
|
+
}
|
16
|
+
eot
|
17
|
+
end
|
18
|
+
|
19
|
+
File.open("#{dir}/down.#{@ext}", "w") do |f|
|
20
|
+
f.puts <<-eot
|
21
|
+
package main
|
22
|
+
|
23
|
+
func main() {
|
24
|
+
// Here goes your Go migration backward
|
25
|
+
}
|
26
|
+
eot
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def exec_migration(dir, is_up)
|
31
|
+
script = "#{dir}/#{is_up ? "up" : "down"}.#{@ext}"
|
32
|
+
Log.info("Executing #{script}...")
|
33
|
+
`go run #{script}`
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|