mamiya 0.0.1.alpha21 → 0.0.1.alpha22
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.
- checksums.yaml +4 -4
- data/example/.gitignore +5 -0
- data/example/Procfile +1 -1
- data/example/README.md +83 -0
- data/example/config.agent.rb +40 -0
- data/example/config.rb +20 -6
- data/example/deploy.rb +27 -11
- data/example/source/README.md +1 -0
- data/lib/mamiya/agent/actions.rb +8 -3
- data/lib/mamiya/agent/task_queue.rb +9 -0
- data/lib/mamiya/agent/tasks/abstract.rb +13 -0
- data/lib/mamiya/agent/tasks/clean.rb +36 -4
- data/lib/mamiya/agent/tasks/fetch.rb +1 -0
- data/lib/mamiya/agent/tasks/notifyable.rb +0 -1
- data/lib/mamiya/agent/tasks/prepare.rb +103 -0
- data/lib/mamiya/agent.rb +46 -12
- data/lib/mamiya/cli/client.rb +35 -7
- data/lib/mamiya/cli.rb +44 -5
- data/lib/mamiya/configuration.rb +12 -0
- data/lib/mamiya/dsl.rb +6 -2
- data/lib/mamiya/helpers/git.rb +24 -0
- data/lib/mamiya/master/agent_monitor.rb +22 -2
- data/lib/mamiya/master/agent_monitor_handlers.rb +17 -0
- data/lib/mamiya/master/web.rb +42 -3
- data/lib/mamiya/master.rb +4 -0
- data/lib/mamiya/script.rb +28 -8
- data/lib/mamiya/steps/abstract.rb +1 -0
- data/lib/mamiya/steps/build.rb +107 -19
- data/lib/mamiya/steps/extract.rb +1 -0
- data/lib/mamiya/steps/prepare.rb +60 -0
- data/lib/mamiya/steps/switch.rb +76 -0
- data/lib/mamiya/storages/filesystem.rb +92 -0
- data/lib/mamiya/storages/mock.rb +1 -0
- data/lib/mamiya/util/label_matcher.rb +7 -3
- data/lib/mamiya/version.rb +1 -1
- data/mamiya.gemspec +1 -1
- data/spec/agent/actions_spec.rb +25 -0
- data/spec/agent/task_queue_spec.rb +42 -6
- data/spec/agent/tasks/abstract_spec.rb +35 -0
- data/spec/agent/tasks/clean_spec.rb +94 -45
- data/spec/agent/tasks/fetch_spec.rb +1 -0
- data/spec/agent/tasks/prepare_spec.rb +127 -0
- data/spec/agent_spec.rb +75 -27
- data/spec/dsl_spec.rb +6 -8
- data/spec/master/agent_monitor_spec.rb +142 -4
- data/spec/master/web_spec.rb +43 -1
- data/spec/steps/build_spec.rb +101 -0
- data/spec/steps/prepare_spec.rb +125 -0
- data/spec/steps/switch_spec.rb +146 -0
- data/spec/storages/filesystem_spec.rb +305 -0
- data/spec/util/label_matcher_spec.rb +32 -0
- metadata +20 -6
- data/config.example.yml +0 -11
- data/example.rb +0 -74
data/spec/master/web_spec.rb
CHANGED
@@ -112,13 +112,25 @@ describe Mamiya::Master::Web do
|
|
112
112
|
|
113
113
|
describe "POST /packages/:application/:package/distribute" do
|
114
114
|
it "dispatchs distribute request" do
|
115
|
-
expect(master).to receive(:distribute).with('myapp', 'mypackage')
|
115
|
+
expect(master).to receive(:distribute).with('myapp', 'mypackage', labels: nil)
|
116
116
|
|
117
117
|
post '/packages/myapp/mypackage/distribute'
|
118
118
|
|
119
119
|
expect(last_response.status).to eq 204 # no content
|
120
120
|
end
|
121
121
|
|
122
|
+
context "with labels" do
|
123
|
+
it "dispatchs prepare request with labels" do
|
124
|
+
expect(master).to receive(:distribute).with('myapp', 'mypackage', labels: ['foo'])
|
125
|
+
|
126
|
+
post '/packages/myapp/mypackage/distribute',
|
127
|
+
{'labels' => ["foo"]}.to_json,
|
128
|
+
'CONTENT_TYPE' => 'application/json'
|
129
|
+
|
130
|
+
expect(last_response.status).to eq 204 # no content
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
122
134
|
context "when package not found" do
|
123
135
|
it "returns 404" do
|
124
136
|
post '/packages/myapp/noexist/distribute'
|
@@ -127,6 +139,36 @@ describe Mamiya::Master::Web do
|
|
127
139
|
end
|
128
140
|
end
|
129
141
|
|
142
|
+
describe "POST /packages/:application/:package/prepare" do
|
143
|
+
it "dispatchs prepare request" do
|
144
|
+
expect(master).to receive(:prepare).with('myapp', 'mypackage', labels: nil)
|
145
|
+
|
146
|
+
post '/packages/myapp/mypackage/prepare'
|
147
|
+
|
148
|
+
expect(last_response.status).to eq 204 # no content
|
149
|
+
end
|
150
|
+
|
151
|
+
context "with labels" do
|
152
|
+
it "dispatchs prepare request with labels" do
|
153
|
+
expect(master).to receive(:prepare).with('myapp', 'mypackage', labels: ['foo'])
|
154
|
+
|
155
|
+
post '/packages/myapp/mypackage/prepare',
|
156
|
+
{'labels' => ["foo"]}.to_json,
|
157
|
+
'CONTENT_TYPE' => 'application/json'
|
158
|
+
|
159
|
+
expect(last_response.status).to eq 204 # no content
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
context "when package not found" do
|
164
|
+
it "returns 404" do
|
165
|
+
post '/packages/myapp/noexist/prepare'
|
166
|
+
expect(last_response.status).to eq 404
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
|
130
172
|
describe "GET /package/:application/:package/distribution" do
|
131
173
|
subject(:distribution) do
|
132
174
|
res = get('/packages/myapp/mypackage/distribution')
|
data/spec/steps/build_spec.rb
CHANGED
@@ -14,6 +14,9 @@ describe Mamiya::Steps::Build do
|
|
14
14
|
let(:build_dir) { Pathname.new(tmpdir).join('build') }
|
15
15
|
let(:package_dir) { Pathname.new(tmpdir).join('pkg') }
|
16
16
|
let(:extract_dir) { Pathname.new(tmpdir).join('extract') }
|
17
|
+
let(:script_dir) { Pathname.new(tmpdir).join('script').tap(&:mkdir) }
|
18
|
+
|
19
|
+
let(:script_file) { script_dir.join('deploy.rb').tap { |_| File.write _, "p :script\n" } }
|
17
20
|
|
18
21
|
let(:exclude_from_package) { [] }
|
19
22
|
let(:package_under) { nil }
|
@@ -36,6 +39,9 @@ describe Mamiya::Steps::Build do
|
|
36
39
|
dereference_symlinks: dereference_symlinks,
|
37
40
|
exclude_from_package: exclude_from_package,
|
38
41
|
skip_prepare_build: skip_prepare_build,
|
42
|
+
script_file: script_file,
|
43
|
+
script_additionals: [],
|
44
|
+
_file: nil,
|
39
45
|
)
|
40
46
|
end
|
41
47
|
|
@@ -97,6 +103,7 @@ describe Mamiya::Steps::Build do
|
|
97
103
|
allow(script).to receive(:exclude_from_package).and_return(['test'])
|
98
104
|
allow(script).to receive(:dereference_symlinks).and_return(true)
|
99
105
|
allow(script).to receive(:package_under).and_return('foo')
|
106
|
+
build_dir.join('foo').mkdir
|
100
107
|
|
101
108
|
expect_any_instance_of(Mamiya::Package).to \
|
102
109
|
receive(:build!).with(
|
@@ -123,6 +130,100 @@ describe Mamiya::Steps::Build do
|
|
123
130
|
build_step.run!
|
124
131
|
end
|
125
132
|
|
133
|
+
it "packs script_file into .mamiya.script" do
|
134
|
+
expect_any_instance_of(Mamiya::Package).to receive(:build!) do
|
135
|
+
expect(build_dir.join('.mamiya.script')).to be_a_directory
|
136
|
+
expect(build_dir.join('.mamiya.script', 'deploy.rb').read).to match(/:script/)
|
137
|
+
end
|
138
|
+
|
139
|
+
build_step.run!
|
140
|
+
|
141
|
+
expect(build_dir.join('.mamiya.script')).not_to be_exist
|
142
|
+
end
|
143
|
+
|
144
|
+
it "writes script_file in meta" do
|
145
|
+
meta = {}
|
146
|
+
allow_any_instance_of(Mamiya::Package).to receive(:meta).and_return(meta)
|
147
|
+
expect_any_instance_of(Mamiya::Package).to receive(:build!) do
|
148
|
+
expect(meta[:script]).to eq 'deploy.rb'
|
149
|
+
end
|
150
|
+
|
151
|
+
build_step.run!
|
152
|
+
|
153
|
+
expect(build_dir.join('.mamiya.script')).not_to be_exist
|
154
|
+
end
|
155
|
+
|
156
|
+
context "when package_under is specified" do
|
157
|
+
let(:package_under) { 'hoge' }
|
158
|
+
|
159
|
+
before do
|
160
|
+
build_dir.join('hoge').mkdir
|
161
|
+
File.write build_dir.join('hoge', 'test'), "hello\n"
|
162
|
+
end
|
163
|
+
|
164
|
+
it "places .mamiya.script under :package_under" do
|
165
|
+
expect_any_instance_of(Mamiya::Package).to receive(:build!) do
|
166
|
+
expect(build_dir.join('hoge', '.mamiya.script')).to be_a_directory
|
167
|
+
expect(build_dir.join('hoge', '.mamiya.script', 'deploy.rb').read).to match(/:script/)
|
168
|
+
end
|
169
|
+
|
170
|
+
build_step.run!
|
171
|
+
|
172
|
+
expect(build_dir.join('.mamiya.script')).not_to be_exist
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
context "with :script_additionals" do
|
177
|
+
before do
|
178
|
+
allow(script).to receive(:script_additionals).and_return(%w(test))
|
179
|
+
end
|
180
|
+
|
181
|
+
it "packs them into .mamiya.script" do
|
182
|
+
File.write script_dir.join('test'), "this is test\n"
|
183
|
+
|
184
|
+
expect_any_instance_of(Mamiya::Package).to receive(:build!) do
|
185
|
+
expect(build_dir.join('.mamiya.script')).to be_a_directory
|
186
|
+
expect(build_dir.join('.mamiya.script', 'deploy.rb').read).to match(/:script/)
|
187
|
+
expect(build_dir.join('.mamiya.script', 'test').read).to match(/this is test/)
|
188
|
+
end
|
189
|
+
|
190
|
+
build_step.run!
|
191
|
+
|
192
|
+
expect(build_dir.join('.mamiya.script')).not_to be_exist
|
193
|
+
end
|
194
|
+
end
|
195
|
+
|
196
|
+
context "without script_file and when script is loaded from a file" do
|
197
|
+
before do
|
198
|
+
allow(script).to receive(:_file).and_return(script_file)
|
199
|
+
allow(script).to receive(:script_file).and_return(nil)
|
200
|
+
end
|
201
|
+
|
202
|
+
it "assumes loaded file's directory as script_dir and loaded file as script_file" do
|
203
|
+
expect_any_instance_of(Mamiya::Package).to receive(:build!) do
|
204
|
+
expect(build_dir.join('.mamiya.script')).to be_a_directory
|
205
|
+
expect(build_dir.join('.mamiya.script', 'deploy.rb').read).to match(/:script/)
|
206
|
+
end
|
207
|
+
|
208
|
+
build_step.run!
|
209
|
+
|
210
|
+
expect(build_dir.join('.mamiya.script')).not_to be_exist
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
context "without script_file and when script is not loaded from a file" do
|
215
|
+
before do
|
216
|
+
allow(script).to receive(:_file).and_return(nil)
|
217
|
+
allow(script).to receive(:script_file).and_return(nil)
|
218
|
+
end
|
219
|
+
|
220
|
+
it "raises an error" do
|
221
|
+
expect {
|
222
|
+
build_step.run!
|
223
|
+
}.to raise_error Mamiya::Steps::Build::ScriptFileNotSpecified
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
126
227
|
context "with package name determiner" do
|
127
228
|
it "calls package name determiner with current candidate" do
|
128
229
|
received = nil
|
@@ -0,0 +1,125 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'pathname'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
require 'mamiya/script'
|
8
|
+
|
9
|
+
require 'mamiya/package'
|
10
|
+
require 'mamiya/steps/prepare'
|
11
|
+
|
12
|
+
describe Mamiya::Steps::Prepare do
|
13
|
+
let!(:tmpdir) { Dir.mktmpdir("mamiya-steps-prepare-spec") }
|
14
|
+
after { FileUtils.remove_entry_secure tmpdir }
|
15
|
+
|
16
|
+
let(:target_dir) { Pathname.new(tmpdir).join('release').tap(&:mkdir) }
|
17
|
+
|
18
|
+
let(:target_meta) do
|
19
|
+
{
|
20
|
+
script: 'script.rb',
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
let(:script) do
|
25
|
+
double('script',
|
26
|
+
before_prepare: proc {},
|
27
|
+
prepare: proc {},
|
28
|
+
after_prepare: proc {},
|
29
|
+
)
|
30
|
+
end
|
31
|
+
|
32
|
+
let(:config) do
|
33
|
+
double('config')
|
34
|
+
end
|
35
|
+
|
36
|
+
let(:options) do
|
37
|
+
{target: target_dir, labels: [:foo, :bar]}
|
38
|
+
end
|
39
|
+
|
40
|
+
subject(:step) { described_class.new(script: nil, config: config, **options) }
|
41
|
+
|
42
|
+
before do
|
43
|
+
File.write target_dir.join('.mamiya.meta.json'), target_meta.to_json
|
44
|
+
allow(Mamiya::Script).to receive(:new).and_return(script)
|
45
|
+
allow(script).to receive(:load!).with(target_dir.realpath.join('.mamiya.script', 'script.rb')).and_return(script)
|
46
|
+
allow(script).to receive(:set).and_return(script)
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "#run!" do
|
50
|
+
it "calls hooks with proper order" do
|
51
|
+
hooks = %i(before_prepare prepare after_prepare)
|
52
|
+
|
53
|
+
flags = []
|
54
|
+
hooks.each do |sym|
|
55
|
+
allow(script).to receive(sym).and_return(proc { flags << sym })
|
56
|
+
end
|
57
|
+
|
58
|
+
expect { step.run! }.
|
59
|
+
to change { flags }.
|
60
|
+
from([]).
|
61
|
+
to(hooks)
|
62
|
+
end
|
63
|
+
|
64
|
+
context "if exception occured" do
|
65
|
+
let(:error) { Exception.new("Good bye, the cruel world") }
|
66
|
+
before do
|
67
|
+
e = error
|
68
|
+
allow(script).to receive(:prepare).and_return(proc { raise e })
|
69
|
+
end
|
70
|
+
|
71
|
+
it "calls after hook with error" do
|
72
|
+
received = nil
|
73
|
+
allow(script).to receive(:after_prepare).and_return(proc { |_| received = _ })
|
74
|
+
|
75
|
+
expect {
|
76
|
+
begin
|
77
|
+
step.run!
|
78
|
+
rescue Exception; end
|
79
|
+
}.
|
80
|
+
to change { received }.
|
81
|
+
from(nil).to(error)
|
82
|
+
end
|
83
|
+
|
84
|
+
it "does not create .mamiya.prepared" do
|
85
|
+
expect {
|
86
|
+
step.run!
|
87
|
+
}.to raise_error(error)
|
88
|
+
expect(target_dir.join('.mamiya.prepared')).not_to be_exist
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
it "creates .mamiya.prepared" do
|
93
|
+
expect {
|
94
|
+
step.run!
|
95
|
+
}.to change {
|
96
|
+
target_dir.join('.mamiya.prepared').exist?
|
97
|
+
}.from(false).to(true)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "calls hook in :target (pwd)" do
|
101
|
+
pwd = nil
|
102
|
+
script.stub(prepare: proc { pwd = Dir.pwd })
|
103
|
+
|
104
|
+
expect {
|
105
|
+
step.run!
|
106
|
+
}.not_to change { Dir.pwd }
|
107
|
+
|
108
|
+
expect(File.realpath(pwd)).to eq target_dir.realpath.to_s
|
109
|
+
end
|
110
|
+
|
111
|
+
it "sets release_path" do
|
112
|
+
expect(script).to receive(:set).with(:release_path, target_dir.realpath)
|
113
|
+
expect(script).to receive(:set).with(:logger, step.logger)
|
114
|
+
step.run!
|
115
|
+
end
|
116
|
+
|
117
|
+
it "calls hooks using labels" do
|
118
|
+
allow(script).to receive(:before_prepare).with(%i(foo bar)).and_return(proc {})
|
119
|
+
allow(script).to receive(:prepare).with(%i(foo bar)).and_return(proc {})
|
120
|
+
allow(script).to receive(:after_prepare).with(%i(foo bar)).and_return(proc {})
|
121
|
+
|
122
|
+
step.run!
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'tmpdir'
|
3
|
+
require 'pathname'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'json'
|
6
|
+
|
7
|
+
require 'mamiya/script'
|
8
|
+
|
9
|
+
require 'mamiya/package'
|
10
|
+
require 'mamiya/steps/switch'
|
11
|
+
|
12
|
+
describe Mamiya::Steps::Switch do
|
13
|
+
let!(:tmpdir) { Dir.mktmpdir("mamiya-steps-switch-spec") }
|
14
|
+
after { FileUtils.remove_entry_secure tmpdir }
|
15
|
+
|
16
|
+
let(:deploy_to) { Pathname.new(tmpdir) }
|
17
|
+
let(:releases_dir) { deploy_to.join('releases').tap(&:mkdir) }
|
18
|
+
|
19
|
+
let(:release_path) { releases_dir.join('20140907030907').tap(&:mkdir) }
|
20
|
+
let(:current_path) { deploy_to.join('current') }
|
21
|
+
|
22
|
+
let(:target_meta) do
|
23
|
+
{script: 'script.rb'}
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:script) do
|
27
|
+
double('script',
|
28
|
+
deploy_to: deploy_to,
|
29
|
+
before_switch: proc {},
|
30
|
+
release: proc {},
|
31
|
+
after_switch: proc {},
|
32
|
+
current_path: current_path,
|
33
|
+
)
|
34
|
+
end
|
35
|
+
|
36
|
+
let(:config) do
|
37
|
+
double('config')
|
38
|
+
end
|
39
|
+
|
40
|
+
let(:options) do
|
41
|
+
{target: release_path, labels: [:foo, :bar]}
|
42
|
+
end
|
43
|
+
|
44
|
+
subject(:step) { described_class.new(script: nil, config: config, **options) }
|
45
|
+
|
46
|
+
before do
|
47
|
+
File.write release_path.join('.mamiya.meta.json'), target_meta.to_json
|
48
|
+
allow(Mamiya::Script).to receive(:new).and_return(script)
|
49
|
+
|
50
|
+
allow(script).to receive(:load!).with(release_path.realpath.join('.mamiya.script', 'script.rb')).and_return(script)
|
51
|
+
allow(script).to receive(:set).and_return(script)
|
52
|
+
end
|
53
|
+
|
54
|
+
describe "#run!" do
|
55
|
+
it "calls hooks with proper order" do
|
56
|
+
hooks = %i(before_switch release after_switch)
|
57
|
+
|
58
|
+
flags = []
|
59
|
+
hooks.each do |sym|
|
60
|
+
allow(script).to receive(sym).and_return(proc { flags << sym })
|
61
|
+
end
|
62
|
+
|
63
|
+
expect { step.run! }.
|
64
|
+
to change { flags }.
|
65
|
+
from([]).
|
66
|
+
to(hooks)
|
67
|
+
end
|
68
|
+
|
69
|
+
it "calls after hook even if exception occured" do
|
70
|
+
e = Exception.new("Good bye, the cruel world")
|
71
|
+
allow(script).to receive(:release).and_return(proc { raise e })
|
72
|
+
|
73
|
+
received = nil
|
74
|
+
allow(script).to receive(:after_switch).and_return(proc { |_| received = _ })
|
75
|
+
|
76
|
+
expect {
|
77
|
+
begin
|
78
|
+
step.run!
|
79
|
+
rescue Exception; end
|
80
|
+
}.
|
81
|
+
to change { received }.
|
82
|
+
from(nil).to(e)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "calls hook in :target (pwd)" do
|
86
|
+
pwd = nil
|
87
|
+
script.stub(release: proc { pwd = Dir.pwd })
|
88
|
+
|
89
|
+
expect {
|
90
|
+
step.run!
|
91
|
+
}.not_to change { Dir.pwd }
|
92
|
+
|
93
|
+
expect(File.realpath(pwd)).to eq release_path.realpath.to_s
|
94
|
+
end
|
95
|
+
|
96
|
+
it "sets release_path" do
|
97
|
+
expect(script).to receive(:set).with(:release_path, release_path.realpath)
|
98
|
+
expect(script).to receive(:set).with(:logger, step.logger)
|
99
|
+
step.run!
|
100
|
+
end
|
101
|
+
|
102
|
+
it "calls hooks using labels" do
|
103
|
+
allow(script).to receive(:before_switch).with(%i(foo bar)).and_return(proc {})
|
104
|
+
allow(script).to receive(:release).with(%i(foo bar)).and_return(proc {})
|
105
|
+
allow(script).to receive(:after_switch).with(%i(foo bar)).and_return(proc {})
|
106
|
+
|
107
|
+
step.run!
|
108
|
+
end
|
109
|
+
|
110
|
+
it "links current to release_path" do
|
111
|
+
expect {
|
112
|
+
step.run!
|
113
|
+
}.to change {
|
114
|
+
current_path.exist? ? current_path.realpath : nil
|
115
|
+
}.from(nil).to(release_path.realpath)
|
116
|
+
end
|
117
|
+
|
118
|
+
context "when current already exists" do
|
119
|
+
before do
|
120
|
+
current_path.make_symlink('releases/20140515000707')
|
121
|
+
end
|
122
|
+
|
123
|
+
it "links current to release_path" do
|
124
|
+
expect {
|
125
|
+
step.run!
|
126
|
+
}.to change {
|
127
|
+
current_path.exist? ? current_path.realpath : nil
|
128
|
+
}.to(release_path.realpath)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context "with no_release" do
|
133
|
+
let(:options) do
|
134
|
+
{target: release_path, no_release: true}
|
135
|
+
end
|
136
|
+
|
137
|
+
it "doesn't call release" do
|
138
|
+
called = false
|
139
|
+
allow(script).to receive(:release).and_return(proc { called = true })
|
140
|
+
step.run!
|
141
|
+
|
142
|
+
expect(called).to be_false
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|