migrake 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGES +12 -0
- data/README.md +30 -8
- data/lib/migrake.rb +19 -71
- data/lib/migrake/dsl.rb +9 -20
- data/lib/migrake/file_system_store.rb +55 -0
- data/lib/migrake/version.rb +1 -1
- data/test/{store_test.rb → file_system_store_test.rb} +5 -5
- data/test/{runner_test.rb → migrake_test.rb} +4 -4
- metadata +9 -7
data/CHANGES
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
0.2.0 - April 15, 2012
|
2
|
+
----------------------
|
3
|
+
|
4
|
+
- Refactored Store into FileSystemStore, make it swappable
|
5
|
+
- Added FileSystemStore#prepare
|
6
|
+
- Clean up the generated Rake tasks.
|
7
|
+
- Change Migrake::Runner.run to Migrake.run.
|
8
|
+
|
9
|
+
0.1.0 - April 15, 2012
|
10
|
+
----------------------
|
11
|
+
|
12
|
+
Initial release! :party:
|
data/README.md
CHANGED
@@ -45,26 +45,37 @@ check that file, see which tasks in the set aren't in it, and will run those
|
|
45
45
|
tasks (no order is guaranteed, if you need tasks to run in order, define the
|
46
46
|
dependencies in the task themselves.)
|
47
47
|
|
48
|
-
## Overriding
|
48
|
+
## Overriding the file where tasks are stored
|
49
49
|
|
50
50
|
The file will be located, by default, at whichever directory `rake` is invoked
|
51
|
-
from. In order to change
|
52
|
-
directory), do either of the following:
|
51
|
+
from. In order to change the path to the file, you can do this:
|
53
52
|
|
54
|
-
|
55
|
-
|
53
|
+
``` ruby
|
54
|
+
Migrake.store = Migrake::FileSystemStore.new("./config/migrake")
|
55
|
+
```
|
56
|
+
|
57
|
+
This *must* be called in your Rakefile before you define the tasks to be run by
|
58
|
+
`migrake`. Like this:
|
56
59
|
|
57
60
|
``` ruby
|
58
|
-
|
61
|
+
require "migrake"
|
62
|
+
|
63
|
+
Migrake.store = Migrake::FileSystemStore.new("./config/migrake")
|
64
|
+
|
65
|
+
migrake Set.new([
|
66
|
+
# ...
|
67
|
+
])
|
59
68
|
```
|
60
69
|
|
61
|
-
|
70
|
+
As an alternative, you can make `MIGRAKE_STATUS_DIR` available to your
|
71
|
+
environment, and migrake will use a `MIGRAKE_STATUS` file in that directory.
|
62
72
|
|
63
73
|
``` shell
|
64
74
|
MIGRAKE_STATUS_DIR=./some/path bundle exec rake migrake
|
65
75
|
```
|
66
76
|
|
67
|
-
|
77
|
+
This is particularly useful to use with capistrano, since you probably want to
|
78
|
+
use cap's `shared` directory to store your migrake file. For example:
|
68
79
|
|
69
80
|
``` ruby
|
70
81
|
namespace :deploy do
|
@@ -76,6 +87,17 @@ end
|
|
76
87
|
after "deploy:migrations", "deploy:migrake"
|
77
88
|
```
|
78
89
|
|
90
|
+
## Heroku and other environments where you can't easily write to the filesystem
|
91
|
+
|
92
|
+
The `FileSystemStore` is easily swappable. For the particular case of Heroku and
|
93
|
+
similar servers we provide the [Migrake::SQLStore][sql-store] gem, that
|
94
|
+
implements the storage API using a database table.
|
95
|
+
|
96
|
+
Writing a new storage engine should be trivial. Use either `FileSystemStore` or
|
97
|
+
`SQLStore` as an example.
|
98
|
+
|
99
|
+
[sql-store]: http://github.com/foca/migrake-sql_store
|
100
|
+
|
79
101
|
## Bootstrapping a new environment
|
80
102
|
|
81
103
|
When you bootstrap a new environment you don't need to run migrake tasks that
|
data/lib/migrake.rb
CHANGED
@@ -1,82 +1,30 @@
|
|
1
|
+
require "set"
|
1
2
|
require "rake/task"
|
2
3
|
require "migrake/dsl"
|
3
4
|
require "migrake/version"
|
4
|
-
require "yaml"
|
5
|
-
require "set"
|
6
|
-
require "pathname"
|
7
5
|
|
8
6
|
module Migrake
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# Returns the directory path.
|
14
|
-
def self.status_file_directory=(dir)
|
15
|
-
@status_dir = Pathname(dir)
|
7
|
+
class << self
|
8
|
+
# Public: Get/Set the store where Migrake checks for which tasks shouldn't
|
9
|
+
# be run. This should implement Migrake::FileSystemStore's interface.
|
10
|
+
attr_accessor :store
|
16
11
|
end
|
17
12
|
|
18
|
-
# Public:
|
19
|
-
#
|
20
|
-
# MIGRAKE_STATUS_DIR environment variable. If that isn't set either, we
|
21
|
-
# default to the working directory.
|
13
|
+
# Public: Run all the rake tasks in `set` that haven't been stored in
|
14
|
+
# `store`.
|
22
15
|
#
|
23
|
-
#
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
# `store`.
|
33
|
-
#
|
34
|
-
# set - A Set with tasks to be run.
|
35
|
-
# store - A Migrake::Store with the tasks that have already been run.
|
36
|
-
#
|
37
|
-
# Returns the Set of tasks that were run.
|
38
|
-
def self.run(set, store)
|
39
|
-
(set - store.all).each do |task|
|
40
|
-
Rake::Task[task].invoke
|
41
|
-
store.put(task)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# The Store handles the file where tasks that have already been run are stored
|
47
|
-
# so they aren't run again.
|
48
|
-
class Store
|
49
|
-
# Public: Initialize the store.
|
50
|
-
#
|
51
|
-
# path - The path to the file where we store the information.
|
52
|
-
def initialize(path)
|
53
|
-
@path = path
|
54
|
-
end
|
55
|
-
|
56
|
-
# Public: Add one task to the store. This immediately writes the file to
|
57
|
-
# disk, to preserve consistency.
|
58
|
-
#
|
59
|
-
# task - A string with a task's name.
|
60
|
-
#
|
61
|
-
# Returns nil.
|
62
|
-
def put(task)
|
63
|
-
write(all << task)
|
64
|
-
end
|
65
|
-
|
66
|
-
# Public: Load all the tasks from the store.
|
67
|
-
#
|
68
|
-
# Returns a Set.
|
69
|
-
def all
|
70
|
-
@all ||= YAML.load(@path.read) || Set.new
|
71
|
-
end
|
72
|
-
|
73
|
-
# Public: Write a whole set of tasks to the store, replacing what is in it.
|
74
|
-
#
|
75
|
-
# set - A Set of tasks.
|
76
|
-
#
|
77
|
-
# Returns nil.
|
78
|
-
def write(set)
|
79
|
-
@path.open("w+") { |f| f.puts YAML.dump(set) }
|
16
|
+
# set - A Set with tasks to be run.
|
17
|
+
# store - A Store (such as Migrake::FileSystemStore), to know which tasks
|
18
|
+
# have already been run.
|
19
|
+
#
|
20
|
+
# Returns the Set of tasks that were run.
|
21
|
+
def self.run(set, store)
|
22
|
+
(set - store.all).each do |task|
|
23
|
+
Rake::Task[task].invoke
|
24
|
+
store.put(task)
|
80
25
|
end
|
81
26
|
end
|
82
27
|
end
|
28
|
+
|
29
|
+
# The FileSystemStore is the default store.
|
30
|
+
require "migrake/file_system_store"
|
data/lib/migrake/dsl.rb
CHANGED
@@ -1,43 +1,32 @@
|
|
1
|
-
require "migrake"
|
2
|
-
|
3
1
|
module Migrake
|
4
2
|
module DSL
|
5
3
|
# Public: Define the rake tasks required to run migrake. This defines the
|
6
4
|
# following tasks:
|
7
5
|
#
|
8
|
-
# - A task to
|
9
|
-
# - A task to create the MIGRAKE_STATUS file in the aforementioned
|
10
|
-
# directory, unless it exists.
|
6
|
+
# - A task to ensure we can use whatever is defined as `Migrake.store`.
|
11
7
|
# - A `migrake:ready` task to bootstrap new environments by writing all
|
12
8
|
# the tasks to the store.
|
13
9
|
# - The `migrake` task, that will run any tasks not run before.
|
14
10
|
#
|
15
11
|
# tasks - A Set of tasks to be run.
|
16
12
|
#
|
17
|
-
# Returns
|
13
|
+
# Returns nothing.
|
18
14
|
def migrake(tasks)
|
19
|
-
dir = Migrake.status_file_directory
|
20
|
-
status_file = dir.join("MIGRAKE_STATUS")
|
21
|
-
|
22
15
|
namespace :migrake do
|
23
|
-
|
24
|
-
|
25
|
-
file status_file.to_s => dir.to_s do
|
26
|
-
touch status_file
|
27
|
-
end
|
28
|
-
|
29
|
-
task :run_tasks => status_file.to_s do
|
30
|
-
Migrake::Runner.run(tasks, Migrake::Store.new(status_file))
|
16
|
+
task :check_store do
|
17
|
+
Migrake.store.prepare
|
31
18
|
end
|
32
19
|
|
33
20
|
desc "Tell migrake that all defined tasks have already been run"
|
34
|
-
task :
|
35
|
-
Migrake
|
21
|
+
task ready: :check_store do
|
22
|
+
Migrake.store.write(tasks)
|
36
23
|
end
|
37
24
|
end
|
38
25
|
|
39
26
|
desc "Run the tasks defined by migrake"
|
40
|
-
task migrake: "migrake:
|
27
|
+
task migrake: "migrake:check_store" do
|
28
|
+
Migrake.run(tasks, Migrake.store)
|
29
|
+
end
|
41
30
|
end
|
42
31
|
end
|
43
32
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require "yaml"
|
2
|
+
require "pathname"
|
3
|
+
require "fileutils"
|
4
|
+
|
5
|
+
# The FileSystemStore handles the file where tasks that have already been run
|
6
|
+
# are stored so they aren't run again.
|
7
|
+
class Migrake::FileSystemStore
|
8
|
+
# Public: Initialize the store.
|
9
|
+
#
|
10
|
+
# path - The path to the file where we store the information. A Pathname of
|
11
|
+
# String should be provided.
|
12
|
+
def initialize(path)
|
13
|
+
@path = Pathname(path)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Public: Ensure the file we use to store information exists.
|
17
|
+
#
|
18
|
+
# Returns nothing.
|
19
|
+
def prepare
|
20
|
+
FileUtils.mkdir_p @path.dirname
|
21
|
+
FileUtils.touch @path
|
22
|
+
end
|
23
|
+
|
24
|
+
# Public: Add one task to the store. This immediately writes the file to
|
25
|
+
# disk, to preserve consistency.
|
26
|
+
#
|
27
|
+
# task - A string with a task's name.
|
28
|
+
#
|
29
|
+
# Returns nothing.
|
30
|
+
def put(task)
|
31
|
+
write(all << task)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Public: Load all the tasks from the store.
|
35
|
+
#
|
36
|
+
# Returns a Set.
|
37
|
+
def all
|
38
|
+
@all ||= YAML.load(@path.read) || Set.new
|
39
|
+
end
|
40
|
+
|
41
|
+
# Public: Write a whole set of tasks to the store, replacing what is in it.
|
42
|
+
#
|
43
|
+
# set - A Set of tasks.
|
44
|
+
#
|
45
|
+
# Returns nothing.
|
46
|
+
def write(set)
|
47
|
+
@path.open("w+") { |f| f.puts YAML.dump(set) }
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Automagic configuration. If this environment has a MIGRAKE_STATUS_DIR, use it
|
52
|
+
# for the MIGRAKE_STATUS file. If not, default to the current directory.
|
53
|
+
Migrake.store = Migrake::FileSystemStore.new(
|
54
|
+
Pathname(ENV.fetch("MIGRAKE_STATUS_DIR", Dir.pwd)).join("MIGRAKE_STATUS")
|
55
|
+
)
|
data/lib/migrake/version.rb
CHANGED
@@ -1,22 +1,22 @@
|
|
1
1
|
require_relative "test_helper"
|
2
2
|
require "tempfile"
|
3
3
|
|
4
|
-
describe Migrake::
|
4
|
+
describe Migrake::FileSystemStore do
|
5
5
|
it "can read a stored set" do
|
6
6
|
set = Set.new(["a", "b", "c"])
|
7
7
|
save_in_source set
|
8
8
|
|
9
|
-
store = Migrake::
|
9
|
+
store = Migrake::FileSystemStore.new(source)
|
10
10
|
assert_equal set, store.all
|
11
11
|
end
|
12
12
|
|
13
13
|
it "an empty file means an empty set" do
|
14
|
-
store = Migrake::
|
14
|
+
store = Migrake::FileSystemStore.new(source)
|
15
15
|
assert_equal Set.new, store.all
|
16
16
|
end
|
17
17
|
|
18
18
|
it "can add an entry to the store" do
|
19
|
-
store = Migrake::
|
19
|
+
store = Migrake::FileSystemStore.new(source)
|
20
20
|
store.put("test")
|
21
21
|
|
22
22
|
assert_equal Set.new(["test"]), store.all
|
@@ -25,7 +25,7 @@ describe Migrake::Store do
|
|
25
25
|
it "can write a set replacing whatever is there on the file" do
|
26
26
|
save_in_source Set.new(["d", "e", "f", "g"])
|
27
27
|
|
28
|
-
store = Migrake::
|
28
|
+
store = Migrake::FileSystemStore.new(source)
|
29
29
|
store.write Set.new(["a", "b", "c"])
|
30
30
|
|
31
31
|
assert_equal Set.new(["a", "b", "c"]), store.all
|
@@ -1,14 +1,14 @@
|
|
1
1
|
require_relative "test_helper"
|
2
2
|
require "rake"
|
3
3
|
|
4
|
-
describe Migrake
|
4
|
+
describe Migrake do
|
5
5
|
it "runs tasks that aren't in the store" do
|
6
6
|
define_tasks "a", "b", "c"
|
7
7
|
define_store "a"
|
8
8
|
|
9
9
|
expect_tasks_ran "b", "c"
|
10
10
|
|
11
|
-
Migrake
|
11
|
+
Migrake.run(Set.new(["a", "b", "c"]), store)
|
12
12
|
|
13
13
|
store.verify
|
14
14
|
end
|
@@ -18,7 +18,7 @@ describe Migrake::Runner do
|
|
18
18
|
define_store "a", "b", "c"
|
19
19
|
# setting no expectation for tasks run passes only if no tasks are run
|
20
20
|
|
21
|
-
Migrake
|
21
|
+
Migrake.run(Set.new(["a", "b", "c"]), store)
|
22
22
|
|
23
23
|
store.verify
|
24
24
|
end
|
@@ -29,7 +29,7 @@ describe Migrake::Runner do
|
|
29
29
|
|
30
30
|
expect_tasks_ran "a"
|
31
31
|
|
32
|
-
Migrake
|
32
|
+
Migrake.run(Set.new(["a", "b", "c"]), store)
|
33
33
|
|
34
34
|
store.verify
|
35
35
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: migrake
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-04-15 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
16
|
-
requirement: &
|
16
|
+
requirement: &70224747638560 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: 0.9.2
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70224747638560
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: minitest
|
27
|
-
requirement: &
|
27
|
+
requirement: &70224747638100 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :development
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70224747638100
|
36
36
|
description: Migrake allows you to run rake tasks that only need to be run once in
|
37
37
|
a given environment each time you deploy
|
38
38
|
email: hi@nicolassanguinetti.info
|
@@ -42,16 +42,18 @@ extra_rdoc_files: []
|
|
42
42
|
files:
|
43
43
|
- .gitignore
|
44
44
|
- .travis.yml
|
45
|
+
- CHANGES
|
45
46
|
- Gemfile
|
46
47
|
- README.md
|
47
48
|
- Rakefile
|
48
49
|
- examples/Rakefile
|
49
50
|
- lib/migrake.rb
|
50
51
|
- lib/migrake/dsl.rb
|
52
|
+
- lib/migrake/file_system_store.rb
|
51
53
|
- lib/migrake/version.rb
|
52
54
|
- migrake.gemspec
|
53
|
-
- test/
|
54
|
-
- test/
|
55
|
+
- test/file_system_store_test.rb
|
56
|
+
- test/migrake_test.rb
|
55
57
|
- test/test_helper.rb
|
56
58
|
homepage: http://github.com/foca/migrake
|
57
59
|
licenses: []
|