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.
Files changed (54) hide show
  1. checksums.yaml +4 -4
  2. data/example/.gitignore +5 -0
  3. data/example/Procfile +1 -1
  4. data/example/README.md +83 -0
  5. data/example/config.agent.rb +40 -0
  6. data/example/config.rb +20 -6
  7. data/example/deploy.rb +27 -11
  8. data/example/source/README.md +1 -0
  9. data/lib/mamiya/agent/actions.rb +8 -3
  10. data/lib/mamiya/agent/task_queue.rb +9 -0
  11. data/lib/mamiya/agent/tasks/abstract.rb +13 -0
  12. data/lib/mamiya/agent/tasks/clean.rb +36 -4
  13. data/lib/mamiya/agent/tasks/fetch.rb +1 -0
  14. data/lib/mamiya/agent/tasks/notifyable.rb +0 -1
  15. data/lib/mamiya/agent/tasks/prepare.rb +103 -0
  16. data/lib/mamiya/agent.rb +46 -12
  17. data/lib/mamiya/cli/client.rb +35 -7
  18. data/lib/mamiya/cli.rb +44 -5
  19. data/lib/mamiya/configuration.rb +12 -0
  20. data/lib/mamiya/dsl.rb +6 -2
  21. data/lib/mamiya/helpers/git.rb +24 -0
  22. data/lib/mamiya/master/agent_monitor.rb +22 -2
  23. data/lib/mamiya/master/agent_monitor_handlers.rb +17 -0
  24. data/lib/mamiya/master/web.rb +42 -3
  25. data/lib/mamiya/master.rb +4 -0
  26. data/lib/mamiya/script.rb +28 -8
  27. data/lib/mamiya/steps/abstract.rb +1 -0
  28. data/lib/mamiya/steps/build.rb +107 -19
  29. data/lib/mamiya/steps/extract.rb +1 -0
  30. data/lib/mamiya/steps/prepare.rb +60 -0
  31. data/lib/mamiya/steps/switch.rb +76 -0
  32. data/lib/mamiya/storages/filesystem.rb +92 -0
  33. data/lib/mamiya/storages/mock.rb +1 -0
  34. data/lib/mamiya/util/label_matcher.rb +7 -3
  35. data/lib/mamiya/version.rb +1 -1
  36. data/mamiya.gemspec +1 -1
  37. data/spec/agent/actions_spec.rb +25 -0
  38. data/spec/agent/task_queue_spec.rb +42 -6
  39. data/spec/agent/tasks/abstract_spec.rb +35 -0
  40. data/spec/agent/tasks/clean_spec.rb +94 -45
  41. data/spec/agent/tasks/fetch_spec.rb +1 -0
  42. data/spec/agent/tasks/prepare_spec.rb +127 -0
  43. data/spec/agent_spec.rb +75 -27
  44. data/spec/dsl_spec.rb +6 -8
  45. data/spec/master/agent_monitor_spec.rb +142 -4
  46. data/spec/master/web_spec.rb +43 -1
  47. data/spec/steps/build_spec.rb +101 -0
  48. data/spec/steps/prepare_spec.rb +125 -0
  49. data/spec/steps/switch_spec.rb +146 -0
  50. data/spec/storages/filesystem_spec.rb +305 -0
  51. data/spec/util/label_matcher_spec.rb +32 -0
  52. metadata +20 -6
  53. data/config.example.yml +0 -11
  54. data/example.rb +0 -74
@@ -8,11 +8,18 @@ describe Mamiya::Agent::Tasks::Clean do
8
8
  let!(:tmpdir) { Dir.mktmpdir('mamiya-agent-tasks-clean-spec') }
9
9
  after { FileUtils.remove_entry_secure(tmpdir) if File.exist?(tmpdir) }
10
10
 
11
- let(:config) { {packages_dir: tmpdir, keep_packages: 2} }
11
+ let(:packages_dir) { Pathname.new(tmpdir).join('packages').tap(&:mkdir) }
12
+ let(:prereleases_dir) { Pathname.new(tmpdir).join('prereleases').tap(&:mkdir) }
13
+
14
+ let(:config) do
15
+ {packages_dir: packages_dir, keep_packages: 2,
16
+ prereleases_dir: prereleases_dir, keep_prereleases: 2,}
17
+ end
12
18
 
13
19
  let(:agent) { double('agent', config: config) }
14
20
  let(:task_queue) { double('task_queue') }
15
21
 
22
+
16
23
  subject(:task) { described_class.new(task_queue, {}, agent: agent, raise_error: true) }
17
24
 
18
25
  it 'inherits abstract task' do
@@ -21,52 +28,94 @@ describe Mamiya::Agent::Tasks::Clean do
21
28
 
22
29
 
23
30
  describe "#execute" do
24
- before do
25
- path = Pathname.new(tmpdir)
26
-
27
- path.join('a').mkdir
28
- File.write path.join('a', "a.tar.gz"), "\n"
29
- File.write path.join('a', "a.json"), "\n"
30
- File.write path.join('a', "b.json"), "\n"
31
- File.write path.join('a', "b.tar.gz"), "\n"
32
- File.write path.join('a', "c.json"), "\n"
33
- File.write path.join('a', "c.tar.gz"), "\n"
34
- path.join('b').mkdir
35
- File.write path.join('b', "a.tar.gz"), "\n"
36
- File.write path.join('b', "a.json"), "\n"
37
-
38
- path.join('c').mkdir
39
- File.write path.join('c', "a.tar.gz"), "\n"
40
- File.write path.join('c', "b.json"), "\n"
31
+ describe "packages" do
32
+ before do
33
+ path = packages_dir
34
+
35
+ path.join('a').mkdir
36
+ File.write path.join('a', "a.tar.gz"), "\n"
37
+ File.write path.join('a', "a.json"), "\n"
38
+ File.write path.join('a', "b.json"), "\n"
39
+ File.write path.join('a', "b.tar.gz"), "\n"
40
+ File.write path.join('a', "c.json"), "\n"
41
+ File.write path.join('a', "c.tar.gz"), "\n"
42
+ path.join('b').mkdir
43
+ File.write path.join('b', "a.tar.gz"), "\n"
44
+ File.write path.join('b', "a.json"), "\n"
45
+
46
+ path.join('c').mkdir
47
+ File.write path.join('c', "a.tar.gz"), "\n"
48
+ File.write path.join('c', "b.json"), "\n"
49
+ end
50
+
51
+ it "cleans up" do
52
+ expect(agent).to receive(:trigger).with('pkg', action: 'remove', application: 'a', package: 'a', coalesce: false)
53
+
54
+ task.execute
55
+
56
+ existences = Hash[
57
+ [
58
+ packages_dir.join('a', 'a.tar.gz'),
59
+ packages_dir.join('a', 'a.json'),
60
+ packages_dir.join('a', 'b.tar.gz'),
61
+ packages_dir.join('a', 'b.json'),
62
+ packages_dir.join('a', 'c.tar.gz'),
63
+ packages_dir.join('a', 'c.json'),
64
+ ].map { |file|
65
+ [file, file.exist?]
66
+ }
67
+ ]
68
+
69
+ expect(existences).to eq(
70
+ packages_dir.join('a', 'a.tar.gz') => false,
71
+ packages_dir.join('a', 'a.json') => false,
72
+ packages_dir.join('a', 'b.tar.gz') => true,
73
+ packages_dir.join('a', 'b.json') => true,
74
+ packages_dir.join('a', 'c.tar.gz') => true,
75
+ packages_dir.join('a', 'c.json') => true,
76
+ )
77
+ end
41
78
  end
42
79
 
43
- it "cleans up" do
44
- expect(agent).to receive(:trigger).with('pkg', action: 'remove', application: 'a', package: 'a', coalesce: false)
45
-
46
- task.execute
47
-
48
- path = Pathname.new(tmpdir)
49
- existences = Hash[
50
- [
51
- path.join('a', 'a.tar.gz'),
52
- path.join('a', 'a.json'),
53
- path.join('a', 'b.tar.gz'),
54
- path.join('a', 'b.json'),
55
- path.join('a', 'c.tar.gz'),
56
- path.join('a', 'c.json'),
57
- ].map { |file|
58
- [file, file.exist?]
59
- }
60
- ]
61
-
62
- expect(existences).to eq(
63
- path.join('a', 'a.tar.gz') => false,
64
- path.join('a', 'a.json') => false,
65
- path.join('a', 'b.tar.gz') => true,
66
- path.join('a', 'b.json') => true,
67
- path.join('a', 'c.tar.gz') => true,
68
- path.join('a', 'c.json') => true,
69
- )
80
+ describe "prereleases_dir" do
81
+ before do
82
+ path = prereleases_dir
83
+
84
+ # TODO: XXX: this may remove ongoing preparing somewhat
85
+ path.join('a').mkdir
86
+ path.join('a', '1').mkdir
87
+ path.join('a', '2').mkdir
88
+ path.join('a', '3').mkdir
89
+ path.join('b').mkdir
90
+ path.join('b', '1').mkdir
91
+ path.join('b', '2').mkdir
92
+ end
93
+
94
+ it "cleans up" do
95
+ expect(agent).to receive(:trigger).with('prerelease', action: 'remove', app: 'a', pkg: '1', coalesce: false)
96
+
97
+ task.execute
98
+
99
+ existences = Hash[
100
+ [
101
+ prereleases_dir.join('a', '1'),
102
+ prereleases_dir.join('a', '2'),
103
+ prereleases_dir.join('a', '3'),
104
+ prereleases_dir.join('b', '1'),
105
+ prereleases_dir.join('b', '2'),
106
+ ].map { |file|
107
+ [file, file.exist?]
108
+ }
109
+ ]
110
+
111
+ expect(existences).to eq(
112
+ prereleases_dir.join('a', '1') => false,
113
+ prereleases_dir.join('a', '2') => true,
114
+ prereleases_dir.join('a', '3') => true,
115
+ prereleases_dir.join('b', '1') => true,
116
+ prereleases_dir.join('b', '2') => true,
117
+ )
118
+ end
70
119
  end
71
120
  end
72
121
  end
@@ -36,6 +36,7 @@ describe Mamiya::Agent::Tasks::Fetch do
36
36
  package: 'mypkg',
37
37
  destination: app_destination,
38
38
  config: config,
39
+ logger: task.logger,
39
40
  ).and_return(step)
40
41
 
41
42
  allow(agent).to receive(:trigger)
@@ -0,0 +1,127 @@
1
+ require 'spec_helper'
2
+ require 'tmpdir'
3
+ require 'pathname'
4
+
5
+ require 'mamiya/agent/tasks/notifyable'
6
+ require 'mamiya/agent/tasks/prepare'
7
+
8
+ require 'mamiya/steps/extract'
9
+ require 'mamiya/steps/prepare'
10
+
11
+ describe Mamiya::Agent::Tasks::Prepare do
12
+ let!(:tmpdir) { Pathname.new Dir.mktmpdir("mamiya-agent-tasks-prepare-spec") }
13
+ after { FileUtils.remove_entry_secure tmpdir }
14
+
15
+ let(:packages_dir) { tmpdir.join('packages').tap(&:mkdir) }
16
+ let(:prereleases_dir) { tmpdir.join('prereleases').tap(&:mkdir) }
17
+
18
+ let(:config) do
19
+ _pkg, _pre = packages_dir, prereleases_dir
20
+ Mamiya::Configuration.new.evaluate! do
21
+ set :packages_dir, _pkg
22
+ set :prereleases_dir, _pre
23
+ end
24
+ end
25
+
26
+ let(:agent) { double('agent', config: config, trigger: nil, labels: [:foo, :bar]) }
27
+ let(:task_queue) { double('task_queue', enqueue: nil) }
28
+
29
+ let(:extract_step) { double('extract step', run!: nil) }
30
+ let(:prepare_step) { double('prepare step', run!: nil) }
31
+
32
+ let(:job) { {'app' => 'myapp', 'pkg' => 'mypkg'} }
33
+
34
+ subject(:task) { described_class.new(task_queue, job, agent: agent, raise_error: true) }
35
+
36
+ it 'inherits notifyable task' do
37
+ expect(described_class.ancestors).to include(Mamiya::Agent::Tasks::Notifyable)
38
+ end
39
+
40
+ describe "#execute" do
41
+ context "when package not fetched" do
42
+ before do
43
+ expect(Mamiya::Steps::Extract).not_to receive(:new)
44
+ expect(Mamiya::Steps::Prepare).not_to receive(:new)
45
+ end
46
+
47
+ it "enqueues fetch task and finish" do
48
+ expect(task_queue).to receive(:enqueue).with(
49
+ :fetch, job.merge('task' => 'prepare', '_chain' => ['prepare'])
50
+ )
51
+
52
+ task.execute
53
+ end
54
+
55
+ context "with _chain-ed job" do
56
+ let(:job) { {'app' => 'myapp', 'pkg' => 'mypkg', '_chain' => ['next']} }
57
+
58
+ it "enqueues fetch task and finish" do
59
+ expect(task_queue).to receive(:enqueue).with(
60
+ :fetch, job.merge('task' => 'prepare', '_chain' => ['prepare', 'next'])
61
+ )
62
+
63
+ task.execute
64
+ end
65
+ end
66
+ end
67
+
68
+ context "when package fetched" do
69
+ before do
70
+ packages_dir.join('myapp').mkdir
71
+ File.write packages_dir.join('myapp', 'mypkg.tar.gz'), "\n"
72
+
73
+ allow(Mamiya::Steps::Extract).to receive(:new).with(
74
+ package: packages_dir.join('myapp', 'mypkg.tar.gz'),
75
+ destination: prereleases_dir.join('myapp', 'mypkg'),
76
+ config: config,
77
+ logger: task.logger,
78
+ ).and_return(extract_step)
79
+
80
+ allow(Mamiya::Steps::Prepare).to receive(:new).with(
81
+ target: prereleases_dir.join('myapp', 'mypkg'),
82
+ labels: [:foo, :bar],
83
+ config: config,
84
+ script: nil,
85
+ logger: task.logger,
86
+ ).and_return(prepare_step)
87
+ end
88
+
89
+ it "prepares extracted release" do
90
+ expect(extract_step).to receive(:run!).ordered
91
+ expect(prepare_step).to receive(:run!).ordered
92
+
93
+ task.execute
94
+ end
95
+
96
+ context "when prepared package exists" do
97
+ before do
98
+ prereleases_dir.join('myapp', 'mypkg').mkpath
99
+ File.write prereleases_dir.join('myapp', 'mypkg', '.mamiya.prepared'),
100
+ "#{Time.now.to_i}\n"
101
+ end
102
+
103
+ it "does nothing" do
104
+ expect(extract_step).not_to receive(:run!)
105
+ expect(prepare_step).not_to receive(:run!)
106
+
107
+ task.execute
108
+ end
109
+ end
110
+
111
+ context "when extracted but non-prepared release exists" do
112
+ before do
113
+ prereleases_dir.join('myapp', 'mypkg').mkpath
114
+ end
115
+
116
+ it "removes existing release then prepare" do
117
+ expect(extract_step).to receive(:run!).ordered do
118
+ expect(prereleases_dir.join('myapp', 'mypkg')).not_to be_exist
119
+ end
120
+ expect(prepare_step).to receive(:run!).ordered
121
+
122
+ task.execute
123
+ end
124
+ end
125
+ end
126
+ end
127
+ end
data/spec/agent_spec.rb CHANGED
@@ -10,6 +10,8 @@ require 'mamiya/agent'
10
10
  require 'mamiya/agent/task_queue'
11
11
  require 'mamiya/agent/actions'
12
12
 
13
+ require 'mamiya/configuration'
14
+
13
15
  require_relative './support/dummy_serf.rb'
14
16
 
15
17
  describe Mamiya::Agent do
@@ -21,7 +23,9 @@ describe Mamiya::Agent do
21
23
  end
22
24
 
23
25
  let(:config) do
24
- {serf: {agent: {rpc_addr: '127.0.0.1:17373', bind: '127.0.0.1:17946'}}}
26
+ Mamiya::Configuration.new.evaluate! do
27
+ set :serf, {agent: {rpc_addr: '127.0.0.1:17373', bind: '127.0.0.1:17946'}}
28
+ end
25
29
  end
26
30
 
27
31
  before do
@@ -84,33 +88,11 @@ describe Mamiya::Agent do
84
88
  end
85
89
  end
86
90
 
87
- describe "#update_tags!" do
88
- describe "(status)" do
89
- context "when it is not busy" do
90
- it "shows ready" do
91
- agent.update_tags!
92
-
93
- expect(serf.tags['mamiya']).to eq ',ready,'
94
- end
95
- end
96
-
97
- context "when it is running multiple jobs" do
98
- pending
99
- end
100
- end
101
-
102
- describe "(prepared)" do
103
- pending
104
- end
105
-
106
- describe "(current)" do
107
- pending
108
- end
109
- end
110
-
111
91
  describe "#status" do
112
92
  before do
113
93
  allow(agent).to receive(:existing_packages).and_return("app" => ["pkg"])
94
+ allow(agent).to receive(:existing_prereleases).and_return("app" => ["pkg"])
95
+ allow(agent).to receive(:labels).and_return([:foo,:bar])
114
96
 
115
97
  allow(task_queue).to receive(:status).and_return({a: {working: nil, queue: []}})
116
98
  end
@@ -133,12 +115,24 @@ describe Mamiya::Agent do
133
115
  expect(status[:packages]).to eq agent.existing_packages
134
116
  end
135
117
 
118
+ it "includes prereleases" do
119
+ expect(status[:prereleases]).to eq agent.existing_prereleases
120
+ end
121
+
122
+ it "includes status" do
123
+ expect(status[:labels]).to eq agent.labels
124
+ end
125
+
136
126
  context "with packages=false" do
137
127
  subject(:status) { agent.status(packages: false) }
138
128
 
139
129
  it "doesn't include existing packages" do
140
130
  expect(status.has_key?(:packages)).to be_false
141
131
  end
132
+
133
+ it "doesn't include existing packages" do
134
+ expect(status.has_key?(:prereleases)).to be_false
135
+ end
142
136
  end
143
137
 
144
138
  describe "(task queue)" do
@@ -176,6 +170,51 @@ describe Mamiya::Agent do
176
170
  end
177
171
  end
178
172
 
173
+ describe "#existing_prereleases" do
174
+ let!(:prereleases_dir) { Pathname.new Dir.mktmpdir('mamiya-agent-spec') }
175
+ after { FileUtils.remove_entry_secure(prereleases_dir) }
176
+
177
+ let(:config) { {prereleases_dir: prereleases_dir} }
178
+
179
+ subject(:existing_prereleases) { agent.existing_prereleases }
180
+
181
+ before do
182
+ prereleases_dir.join('a').mkdir
183
+ prereleases_dir.join('a', '1').mkdir
184
+ File.write prereleases_dir.join('a', '1', '.mamiya.prepared'), "#{Time.now.to_s}\n"
185
+ prereleases_dir.join('a', '2').mkdir
186
+ File.write prereleases_dir.join('a', '2', '.mamiya.prepared'), "#{Time.now.to_s}\n"
187
+ prereleases_dir.join('a', '3').mkdir
188
+ end
189
+
190
+ it "returns prepared prereleases" do
191
+ expect(existing_prereleases).to eq('a' => ['1', '2'])
192
+ end
193
+ end
194
+
195
+
196
+ describe "#labels" do
197
+ subject(:labels) { agent.labels }
198
+
199
+ context "with config.labels" do
200
+ before do
201
+ config.evaluate! do
202
+ labels { [:foo, :bar, :baz] }
203
+ end
204
+ end
205
+
206
+ it "retrieves label from configuration" do
207
+ expect(labels).to eq [:foo, :bar, :baz]
208
+ end
209
+ end
210
+
211
+ context "without config.labels" do
212
+ it "returns []" do
213
+ expect(labels).to eq []
214
+ end
215
+ end
216
+ end
217
+
179
218
  describe "query responder" do
180
219
  it "responds to 'mamiya:status'" do
181
220
  allow(agent).to receive(:status).with(packages: false).and_return("my" => "status")
@@ -185,10 +224,19 @@ describe Mamiya::Agent do
185
224
  end
186
225
 
187
226
  it "responds to 'mamiya:packages'" do
188
- allow(agent).to receive(:existing_packages).and_return(%w(pkg1 pkg2))
227
+ allow(agent).to receive(:existing_packages).and_return("app" => %w(pkg1 pkg2))
228
+ allow(agent).to receive(:existing_prereleases).and_return("app" => %w(pkg2))
189
229
 
190
230
  response = serf.trigger_query('mamiya:packages', '')
191
- expect(JSON.parse(response)).to eq(%w(pkg1 pkg2))
231
+
232
+ expect(JSON.parse(response)).to eq(
233
+ "packages" => {
234
+ "app" => %w(pkg1 pkg2)
235
+ },
236
+ "prereleases" => {
237
+ "app" => %w(pkg2)
238
+ },
239
+ )
192
240
  end
193
241
  end
194
242
 
data/spec/dsl_spec.rb CHANGED
@@ -50,6 +50,12 @@ describe Mamiya::DSL do
50
50
  dsl.load! "#{__dir__}/fixtures/dsl_test_load.rb"
51
51
  }.to change { dsl.foo }.from(42).to(72)
52
52
  end
53
+
54
+ it "sets _file" do
55
+ expect {
56
+ dsl.load! "#{__dir__}/fixtures/dsl_test_load.rb"
57
+ }.to change { dsl._file }.from(nil).to(Pathname.new("#{__dir__}/fixtures/dsl_test_load.rb"))
58
+ end
53
59
  end
54
60
 
55
61
  describe "#use" do
@@ -284,12 +290,4 @@ describe Mamiya::DSL do
284
290
  end
285
291
  end
286
292
  end
287
-
288
- describe "#servers" do
289
- pending "Hey!"
290
- end
291
-
292
- describe "#use_servers" do
293
- pending "Hey!"
294
- end
295
293
  end
@@ -3,6 +3,8 @@ require 'json'
3
3
 
4
4
  require 'villein/event'
5
5
 
6
+ require 'mamiya/util/label_matcher'
7
+
6
8
  require 'mamiya/master/agent_monitor'
7
9
 
8
10
  describe Mamiya::Master::AgentMonitor do
@@ -30,7 +32,7 @@ describe Mamiya::Master::AgentMonitor do
30
32
  {
31
33
  "Acks" => ['a'],
32
34
  "Responses" => {
33
- 'a' => {"foo" => "bar", 'packages' => ['pkg1']}.to_json,
35
+ 'a' => {"foo" => "bar", 'packages' => {"app" => ['pkg1']}, 'prereleases' => {"app" => ['pkg2']}}.to_json,
34
36
  },
35
37
  }
36
38
  end
@@ -39,11 +41,50 @@ describe Mamiya::Master::AgentMonitor do
39
41
  {
40
42
  "Acks" => ['a'],
41
43
  "Responses" => {
42
- 'a' => ['pkg1','pkg2'].to_json,
44
+ 'a' => {"packages" => {"app" => ['pkg1','pkg2']}, "prereleases" => {"app" => ['pkg2']}}.to_json,
43
45
  },
44
46
  }
45
47
  end
46
48
 
49
+ describe "#statuses" do
50
+ let(:members) do
51
+ [
52
+ {
53
+ "name"=>"a", "status"=>"alive",
54
+ "addr"=>"x.x.x.x:7676", "port"=>7676,
55
+ "protocol"=>{"max"=>4, "min"=>2, "version"=>4},
56
+ "tags"=>{},
57
+ },
58
+ ]
59
+ end
60
+
61
+ let(:status_query_response) do
62
+ {
63
+ "Acks" => ['a','b'],
64
+ "Responses" => {
65
+ 'a' => {'packages' => {}, 'prereleases' => {}, "labels" => ['foo','bar']}.to_json,
66
+ 'b' => {'packages' => {}, 'prereleases' => {}, "labels" => ['baz']}.to_json,
67
+ },
68
+ }
69
+ end
70
+
71
+ before do
72
+ stub_serf_queries()
73
+ allow(serf).to receive(:members).and_return(members)
74
+
75
+ agent_monitor.refresh
76
+ end
77
+
78
+ context "with labels" do
79
+ it "can filter agents by label" do
80
+ # FIXME: stub label matcher
81
+ expect(agent_monitor.statuses.keys.sort).to eq ['a', 'b']
82
+ expect(agent_monitor.statuses(labels: ['foo']).keys.sort).to eq ['a']
83
+ expect(agent_monitor.statuses(labels: ['baz']).keys.sort).to eq ['b']
84
+ end
85
+ end
86
+ end
87
+
47
88
  describe "#refresh" do
48
89
  let(:members) do
49
90
  [
@@ -69,12 +110,32 @@ describe Mamiya::Master::AgentMonitor do
69
110
  }.to('bar')
70
111
  end
71
112
 
113
+ it "updates #last_refresh_at" do
114
+ agent_monitor.refresh
115
+ expect(agent_monitor.last_refresh_at).to be_a_kind_of(Time)
116
+
117
+ expect {
118
+ agent_monitor.refresh
119
+ }.to change {
120
+ agent_monitor.last_refresh_at
121
+ }
122
+ end
123
+
124
+
72
125
  it "updates status .packages by packages query" do
73
126
  expect {
74
127
  agent_monitor.refresh
75
128
  }.to change {
76
129
  agent_monitor.statuses["a"] && agent_monitor.statuses["a"]['packages']
77
- }.to(%w(pkg1 pkg2))
130
+ }.to("app" => %w(pkg1 pkg2))
131
+ end
132
+
133
+ it "updates status .prereleases by packages query" do
134
+ expect {
135
+ agent_monitor.refresh
136
+ }.to change {
137
+ agent_monitor.statuses["a"] && agent_monitor.statuses["a"]['prereleases']
138
+ }.to("app" => %w(pkg2))
78
139
  end
79
140
 
80
141
  context "when packages query unavailable, but available in status query" do
@@ -91,7 +152,15 @@ describe Mamiya::Master::AgentMonitor do
91
152
  agent_monitor.refresh
92
153
  }.to change {
93
154
  agent_monitor.statuses["a"] && agent_monitor.statuses["a"]['packages']
94
- }.to(%w(pkg1))
155
+ }.to("app" => %w(pkg1))
156
+ end
157
+
158
+ it "updates status .prereleases from status" do
159
+ expect {
160
+ agent_monitor.refresh
161
+ }.to change {
162
+ agent_monitor.statuses["a"] && agent_monitor.statuses["a"]['prereleases']
163
+ }.to("app" => %w(pkg2))
95
164
  end
96
165
  end
97
166
 
@@ -393,6 +462,47 @@ describe Mamiya::Master::AgentMonitor do
393
462
  end
394
463
  end
395
464
 
465
+ describe "prerelease" do
466
+ describe ":remove" do
467
+ let(:status) do
468
+ {prereleases: {'myapp' => ['pkg1']}}
469
+ end
470
+
471
+ it "removes removed release from prereleases" do
472
+ commit('mamiya:prerelease:remove',
473
+ app: 'myapp', pkg: 'pkg1')
474
+
475
+ expect(new_status["prereleases"]['myapp']).to eq []
476
+ end
477
+
478
+ context "with existing packages" do
479
+ let(:status) do
480
+ {prereleases: {'myapp' => ['pkg1', 'pkg2']}}
481
+ end
482
+
483
+ it "removes removed release from prereleases" do
484
+ commit('mamiya:prerelease:remove',
485
+ app: 'myapp', pkg: 'pkg1')
486
+
487
+ expect(new_status["prereleases"]['myapp']).to eq ['pkg2']
488
+ end
489
+ end
490
+
491
+ context "with inexist package" do
492
+ let(:status) do
493
+ {prereleases: {'myapp' => ['pkg1', 'pkg3']}}
494
+ end
495
+
496
+ it "removes removed release from packages" do
497
+ commit('mamiya:prerelease:remove',
498
+ app: 'myapp', pkg: 'pkg2')
499
+
500
+ expect(new_status["prereleases"]['myapp']).to eq ['pkg1', 'pkg3']
501
+ end
502
+ end
503
+ end
504
+ end
505
+
396
506
  describe "fetch" do
397
507
  describe "success" do
398
508
  let(:status) do
@@ -420,6 +530,34 @@ describe Mamiya::Master::AgentMonitor do
420
530
  end
421
531
  end
422
532
  end
533
+
534
+ describe "prepare" do
535
+ describe "success" do
536
+ let(:status) do
537
+ {prereleases: {}}
538
+ end
539
+
540
+ it "updates prereleases" do
541
+ commit('mamiya:task:finish',
542
+ task: {task: 'prepare', app: 'myapp', pkg: 'pkg'})
543
+
544
+ expect(new_status["prereleases"]['myapp']).to eq ["pkg"]
545
+ end
546
+
547
+ context "with existing prerelease" do
548
+ let(:status) do
549
+ {prereleases: {'myapp' => ['pkg1']}}
550
+ end
551
+
552
+ it "updates prereleases" do
553
+ commit('mamiya:task:finish',
554
+ task: {task: 'prepare', app: 'myapp', pkg: 'pkg2'})
555
+
556
+ expect(new_status["prereleases"]['myapp']).to eq %w(pkg1 pkg2)
557
+ end
558
+ end
559
+ end
560
+ end
423
561
  end
424
562
  end
425
563
  end