mamiya 0.0.1.beta3 → 0.1.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: feb2301bfc6bf520112e3606038d9c5387a3bd94
4
- data.tar.gz: b4f96200bd9d5d2495cfd62076f4a9e804f6ef61
3
+ metadata.gz: 8fa28dadde7c00c1165fb66de3fceee10b564577
4
+ data.tar.gz: 614971d0864612144dab18e4db4aee2c3c7a1126
5
5
  SHA512:
6
- metadata.gz: d18e32e3a5ee9ec3a46560337b810c254f1f51008eb1e3ec0be4ab8a3df3b774d73397e21bb6b341b317602b14ec47db5b3ef1281f9300c09f2b40faf81ba47f
7
- data.tar.gz: 2004514ee647cec743bcce5a0230f0ceb012157bcae4662a32ba82efda376e8307c0cbdd142c03334e836969ef5fc1feb3217a0f298370b315972a4a0c9ab8c8
6
+ metadata.gz: 494a8f6d5d1e171ec5f2a154a81c534780eb464e6bc30adff4df5e9393788a43eb57a6f2ffaea7e11ce0208c34b9f5a64547fed531149da478a083380ec18a96
7
+ data.tar.gz: 3cc97e2941f5a10f5ce67552ec1066431f08c1b6ffe4748a2563fa1f085229bc68074e702649529fa3492a682f36f516795b6b963c4f2dbebcf81136be52fd86
data/.travis.yml CHANGED
@@ -1,7 +1,8 @@
1
1
  language: ruby
2
2
  cache: bundler
3
3
  rvm:
4
- - "2.1.1"
4
+ - "2.2"
5
+ - "2.1"
5
6
  - "2.0.0"
6
7
  - "ruby-head"
7
8
 
data/README.md CHANGED
@@ -6,28 +6,22 @@ Mamiya allows you to deploy using without ssh -- using tarballs, some storages (
6
6
 
7
7
  ## Installation
8
8
 
9
- $ gem install mamiya
10
-
11
- or bundle it:
12
-
13
- ``` ruby
14
- gem 'mamiya'
15
- ```
16
-
17
- ## Usage
18
-
19
9
  (Detailed documentation coming soon)
20
10
 
21
- 1. Prepare master node for `mamiya master` process
11
+ 1. Install gem (`gem install mamiya`, or bundling by `gem 'mamiya'`)
12
+ 2. Prepare master node for `mamiya master` process
22
13
  - master has HTTP API to allow control the cluster via HTTP
23
14
  - master watches agents in the cluster
24
- 2. Then install `mamiya agent` in your deployment target hosts
25
- 3. Write deploy script for your own
15
+ 3. Then install `mamiya agent` in your deployment target hosts
16
+ 4. Write deploy script for your own
26
17
  - how to build package, how to prepare release, how to release, etc.
27
- 4. Build then push package
28
- 5. Time to deploy
18
+ 5. Build then push package
19
+ 6. Time to deploy
29
20
 
30
- [example](./example) directory contains configuration files that work out-of-the-box. Try Mamiya in your local machine: `foreman start`
21
+ ### Example configuration
22
+
23
+ [example](./example) directory contains configuration files that work out-of-the-box.
24
+ Try Mamiya in your local machine: `foreman start`
31
25
 
32
26
  ## Problems in existing deploy tool
33
27
 
@@ -39,30 +33,13 @@ This solves such problem by using [Serf](http://www.serfdom.io/) and tarball on
39
33
  Also, I'm planning to allow to distribute files before the deploy command. I guess this can skip or shorten
40
34
  file transferring phase in deploy.
41
35
 
36
+ ## Misc.
42
37
 
43
- ## Upgrade Notes
44
-
45
- ### 0.0.1.alpha21
46
-
47
- #### Configuration now written in Ruby
38
+ - [Scalable Deployments - How we deploy Rails app to 150+ hosts in a minute // Speaker Deck](https://speakerdeck.com/sorah/scalable-deployments-how-we-deploy-rails-app-to-150-plus-hosts-in-a-minute)
48
39
 
49
- You should rewrite your configuration yaml in Ruby. See examples/config.rb for example.
50
-
51
- ### 0.0.1.alpha20
52
-
53
- _tl;dr_ Don't mix alpha19 and alpha20.
54
-
55
- #### Internal component for distribution has been replaced completely
56
-
57
- alpha20 introduces new class `TaskQueue` and removes `Fetcher`. This changes way to distribute packages -- including internal serf events, job tracking that Distribution API does, etc.
58
- So basically there's no compatibility for distribution, between alpha19 and alpha20 and later. Distribute task from alpha20 doesn't effect to alpha19, and vice versa.
59
-
60
- Good new: There's no change in Distribution API.
61
-
62
- #### Agent status has changed
40
+ ## Upgrade Notes
63
41
 
64
- - Due to removal of `Fetcher`, alpha20 removes `.fetcher` object from agent status.
65
- - Added `.queues`, represents task queues that managed by `TaskQueue` class.
42
+ See [docs/upgrading.md](./docs/upgrading.md).
66
43
 
67
44
  ## Contributing
68
45
 
data/docs/upgrading.md ADDED
@@ -0,0 +1,25 @@
1
+ # Upgrade Notes
2
+
3
+ ## 0.0.1.alpha21
4
+
5
+ ### Configuration now written in Ruby
6
+
7
+ You should rewrite your configuration yaml in Ruby. See examples/config.rb for example.
8
+
9
+ ## 0.0.1.alpha20
10
+
11
+ _tl;dr_ Don't mix alpha19 and alpha20.
12
+
13
+ ### Internal component for distribution has been replaced completely
14
+
15
+ alpha20 introduces new class `TaskQueue` and removes `Fetcher`. This changes way to distribute packages -- including internal serf events, job tracking that Distribution API does, etc.
16
+ So basically there's no compatibility for distribution, between alpha19 and alpha20 and later. Distribute task from alpha20 doesn't effect to alpha19, and vice versa.
17
+
18
+ Good new: There's no change in Distribution API.
19
+
20
+ ### Agent status has changed
21
+
22
+ - Due to removal of `Fetcher`, alpha20 removes `.fetcher` object from agent status.
23
+ - Added `.queues`, represents task queues that managed by `TaskQueue` class.
24
+
25
+
@@ -42,6 +42,7 @@ set :keep_packages, 3
42
42
  set :keep_prereleases, 3
43
43
  set :fetch_sleep, 2
44
44
 
45
+ _labels = [rand(2) == 0 ? :a : :b]
45
46
  labels do
46
- [:"p#{ENV['PORT']}"]
47
+ [:"p#{ENV['PORT']}", *_labels]
47
48
  end
data/example/deploy.rb CHANGED
@@ -16,6 +16,28 @@ set :build_to, "#{File.dirname(__FILE__)}/builds"
16
16
  # to test it
17
17
  Dir.mkdir build_to unless File.exist?(build_to)
18
18
 
19
+ build("test") do
20
+ # build something...
21
+ File.write('built_at', "#{Time.now}\n")
22
+ end
23
+
24
+ prepare 'test' do
25
+ # run 'bundle', 'install'
26
+ sleep 5
27
+ File.write release_path.join('prepared_at'), Time.now
28
+ end
29
+
30
+ release 'test' do
31
+ # run '/etc/init.d/app', 'reload'
32
+ i = rand(10)
33
+ logger.info "SLEEP #{i} sec"
34
+ sleep i
35
+ File.write release_path.join('released_at'), Time.now
36
+ end
37
+
38
+
39
+
40
+
19
41
  #set :bundle_without, [:development, :test]
20
42
  #set :bundle_dir, "#{deploy_to}/shared/bundle"
21
43
 
@@ -25,10 +47,6 @@ Dir.mkdir build_to unless File.exist?(build_to)
25
47
  # run "bundle", "install"
26
48
  #end
27
49
 
28
- build("test") do
29
- File.write('built_at', "#{Time.now}\n")
30
- end
31
-
32
50
  #build("include assets and .bundle") do
33
51
  # exclude_from_package.reject! { |_| _ == 'public/assets/' }
34
52
  # exclude_from_package.reject! { |_| _ == '.bundle/' }
@@ -38,21 +56,4 @@ end
38
56
  # run "bundle", "exec", "rake", "assets:precompile"
39
57
  #end
40
58
 
41
- prepare 'test' do
42
- # run 'bundle', 'install'
43
- logger.info "- prep/deploy_to: #{deploy_to}"
44
- logger.info "- prep/release_path: #{release_path}"
45
- sleep 5
46
- File.write release_path.join('prepared_at'), Time.now
47
- end
48
-
49
- release 'test' do
50
- logger.info "- prep/deploy_to: #{deploy_to}"
51
- logger.info "- prep/release_path: #{release_path}"
52
- sl = rand(80)
53
- logger.info "!!!!!!!!!!!!!!! sleep #{sl} sec"
54
- sleep sl
55
- File.write release_path.join('released_at'), Time.now
56
- end
57
-
58
59
 
@@ -117,6 +117,8 @@ module Mamiya
117
117
  begin
118
118
  status[:lock].synchronize do
119
119
  status[:pending].delete task
120
+
121
+ task['start'] = Time.now.to_i
120
122
  status[:working] = task
121
123
  end
122
124
  task_logger = @logger.with_clean_progname
@@ -52,8 +52,10 @@ module Mamiya
52
52
  raise PrereleaseMissing, "Existing release is not prepared but prerelease doesn't exist"
53
53
  end
54
54
 
55
- logger.info "Copying #{prerelease_path} -> #{release_path}"
56
- FileUtils.cp_r prerelease_path, release_path
55
+ unless release_path.exist?
56
+ logger.info "Copying #{prerelease_path} -> #{release_path}"
57
+ FileUtils.cp_r prerelease_path, release_path
58
+ end
57
59
 
58
60
  logger.info "Switching"
59
61
  switch_step.run!
@@ -5,28 +5,18 @@ module Mamiya
5
5
  class Switch < Abstract
6
6
  def run!
7
7
  @exception = nil
8
- logger.info "Switching to #{target}"
9
-
10
- script.before_switch(labels)[]
11
-
12
- # TODO: link with relative if available?
13
- # TODO: Restore this if FAILED
14
- File.unlink script.current_path if script.current_path.symlink?
15
- script.current_path.make_symlink(target.realpath)
8
+ @switched = false
16
9
 
17
- if do_release?
18
- begin
19
- old_pwd = Dir.pwd
20
- Dir.chdir(target)
21
-
22
- logger.info "Releasing..."
10
+ if current_targets_release?
11
+ logger.info "Already switched"
12
+ else
13
+ switch
14
+ end
23
15
 
24
- script.release(labels)[@exception]
25
- ensure
26
- Dir.chdir old_pwd if old_pwd
27
- end
16
+ if @switched ? do_release? : force_release?
17
+ release
28
18
  else
29
- logger.warn "Skipping release (:no_release is set)"
19
+ logger.warn "Skipping release"
30
20
  end
31
21
 
32
22
  rescue Exception => e
@@ -35,11 +25,34 @@ module Mamiya
35
25
  ensure
36
26
  logger.warn "Exception occured, cleaning up..." if @exception
37
27
 
38
- script.after_switch(labels)[@exception]
28
+ script.after_switch(labels)[@exception] if @switched
39
29
 
40
30
  logger.info "DONE!" unless @exception
41
31
  end
42
32
 
33
+ def switch
34
+ logger.info "Switching to #{target}"
35
+ @switched = true
36
+ script.before_switch(labels)[]
37
+
38
+ File.unlink script.current_path if script.current_path.symlink?
39
+ script.current_path.make_symlink(target.realpath)
40
+ end
41
+
42
+ def release
43
+ # TODO: link with relative if available?
44
+ # TODO: Restore this if FAILED
45
+
46
+ old_pwd = Dir.pwd
47
+ Dir.chdir(target)
48
+
49
+ logger.info "Releasing..."
50
+
51
+ script.release(labels)[@exception]
52
+ ensure
53
+ Dir.chdir old_pwd if old_pwd
54
+ end
55
+
43
56
  # XXX: dupe with prepare step. modulize?
44
57
 
45
58
  # This class see target_dir's script
@@ -57,8 +70,20 @@ module Mamiya
57
70
 
58
71
  private
59
72
 
73
+ def current_targets_release?
74
+ script.current_path.exist? && script.current_path.realpath == target.realpath
75
+ end
76
+
60
77
  def do_release?
61
- !options[:no_release]
78
+ force_release? ? true : !no_release?
79
+ end
80
+
81
+ def force_release?
82
+ !!options[:do_release]
83
+ end
84
+
85
+ def no_release?
86
+ !!options[:no_release]
62
87
  end
63
88
 
64
89
  def target
@@ -1,3 +1,3 @@
1
1
  module Mamiya
2
- VERSION = "0.0.1.beta3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -41,7 +41,6 @@ describe Mamiya::Agent::TaskQueue do
41
41
  end
42
42
  end
43
43
 
44
-
45
44
  let(:task_class_a) do
46
45
  Class.new(task_class_root) do
47
46
  def self.identifier
@@ -62,6 +61,10 @@ describe Mamiya::Agent::TaskQueue do
62
61
  described_class.new(agent, task_classes: [task_class_a, task_class_b])
63
62
  end
64
63
 
64
+ before do
65
+ allow(Time).to receive(:now).and_return(Time.now)
66
+ end
67
+
65
68
  describe "lifecycle (#start!, #stop!)" do
66
69
  it "can start and stop" do
67
70
  expect(queue).not_to be_running
@@ -170,7 +173,7 @@ describe Mamiya::Agent::TaskQueue do
170
173
 
171
174
  100.times { break unless task_class_a.locks.empty?; sleep 0.01 }
172
175
  expect(task_class_a.locks).not_to be_empty
173
- expect(queue.status[:a][:working]).to eq('wait' => true, 'id' => 1, 'task' => :a)
176
+ expect(queue.status[:a][:working]).to eq('wait' => true, 'id' => 1, 'task' => :a, 'start' => Time.now.to_i)
174
177
 
175
178
  queue.enqueue(:a, 'id' => 2)
176
179
  100.times { break unless queue.status[:a][:queue].empty?; sleep 0.01 }
@@ -236,8 +239,8 @@ describe Mamiya::Agent::TaskQueue do
236
239
  expect(task_class_a.locks).not_to be_empty
237
240
  expect(task_class_b.locks).not_to be_empty
238
241
 
239
- expect(queue.status[:a][:working]).to eq('wait' => true, 'id' => 1, 'task' => :a)
240
- expect(queue.status[:b][:working]).to eq('wait' => true, 'id' => 2, 'task' => :b)
242
+ expect(queue.status[:a][:working]).to eq('wait' => true, 'id' => 1, 'task' => :a, 'start' => Time.now.to_i)
243
+ expect(queue.status[:b][:working]).to eq('wait' => true, 'id' => 2, 'task' => :b, 'start' => Time.now.to_i)
241
244
 
242
245
  queue.enqueue(:a, 'id' => 3)
243
246
  queue.enqueue(:b, 'id' => 4)
@@ -119,6 +119,42 @@ describe Mamiya::Steps::Switch do
119
119
  }.from(nil).to(release_path.realpath)
120
120
  end
121
121
 
122
+ context "when current targets the target" do
123
+ before do
124
+ current_path.make_symlink(release_path.realpath)
125
+ end
126
+
127
+ it "doesn't call hooks" do
128
+ called = false
129
+ allow(script).to receive(:release).and_return(proc { called = true })
130
+ allow(script).to receive(:before_switch).and_return(proc { called = true })
131
+ allow(script).to receive(:after_switch).and_return(proc { called = true })
132
+ step.run!
133
+
134
+ expect(called).to be_false
135
+ end
136
+
137
+ context "with do_release" do
138
+ let(:options) do
139
+ {target: release_path, do_release: true}
140
+ end
141
+
142
+ it "calls hooks" do
143
+ hooks = %i(release)
144
+
145
+ flags = []
146
+ hooks.each do |sym|
147
+ allow(script).to receive(sym).and_return(proc { flags << sym })
148
+ end
149
+
150
+ expect { step.run! }.
151
+ to change { flags }.
152
+ from([]).
153
+ to(hooks)
154
+ end
155
+ end
156
+ end
157
+
122
158
  context "when current already exists" do
123
159
  before do
124
160
  current_path.make_symlink('releases/20140515000707')
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mamiya
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.beta3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shota Fukumori (sora_h)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-17 00:00:00.000000000 Z
11
+ date: 2014-09-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -180,9 +180,7 @@ files:
180
180
  - README.md
181
181
  - Rakefile
182
182
  - bin/mamiya
183
- - docs/cli.md
184
- - docs/sequences/deploy.png
185
- - docs/sequences/deploy.uml
183
+ - docs/upgrading.md
186
184
  - example/.gitignore
187
185
  - example/Procfile
188
186
  - example/README.md
@@ -289,9 +287,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
289
287
  version: '0'
290
288
  required_rubygems_version: !ruby/object:Gem::Requirement
291
289
  requirements:
292
- - - ">"
290
+ - - ">="
293
291
  - !ruby/object:Gem::Version
294
- version: 1.3.1
292
+ version: '0'
295
293
  requirements: []
296
294
  rubyforge_project:
297
295
  rubygems_version: 2.2.2
data/docs/cli.md DELETED
@@ -1,78 +0,0 @@
1
- # Commands
2
-
3
- ## Global options
4
-
5
- - `-C`, `--config`: path to configuration file (default: `./config.yml`)
6
- - config file won't be required if a command don't need it.
7
- - `-S`, `--script`: path to script file (default: `./deploy.rb`)
8
- - script file won't be required if a command don't need it.
9
- - `-a`, `--app`: Specify application name to operate
10
- - `-d`, `--debug`: Enable debug mode
11
- - `--color`, `--no-color`: Enable or disable colored output. When the stdout is a terminal, it'll be enabled by default.
12
-
13
- ## Storage related commands
14
-
15
- ### `list-applications` - list application in storage
16
-
17
- ```
18
- $ mamiya list-applications -C ./config.yml
19
- ```
20
-
21
- ### `list-packages` - list packages for specified app in storage
22
-
23
- ```
24
- $ mamiya list-packages -C ./config.yml -a myapp
25
- ```
26
-
27
- - __Requires:__ configuration file, application name
28
- - application name will be retrieved from deploy script when not specified.
29
- - __Options:__
30
- - `-n`, `--name-only`: Show only names (without heading text)
31
-
32
- ### `show` - show package information
33
-
34
- ```
35
- $ mamiya list-packages -C ./config.yml -a myapp PACKAGE_NAME
36
- ```
37
-
38
- - __Requires:__ configuration file, application name, package name
39
- - application name will be retrieved from deploy script when not specified.
40
- - __Options:__
41
- - `-f`, `--format`: Choose output format from `pp`, `json`, or `yaml`. Default: `pp`.
42
-
43
- ## Build, pushing and fetching packages
44
-
45
- ### `build` - build package using script
46
-
47
- ```
48
- $ mamiya build --script ./deploy.rb --source source_dir --destination dest_dir
49
- ```
50
-
51
- - __Requires:__ application name, source, destination, deploy script
52
- - source, description, and app name will be taken from deploy script, if omitted
53
- - __Options:__
54
- - `-f`, `--source`, `--build-from`: directory for package source.
55
- - `-t`, `--destination`, `--build-to`: directory to save built packages.
56
- - `-P`, `--skip-prepare-build`: Skip prepare build phase of deploy script.
57
-
58
- ### `push` - push built package to the storage
59
-
60
- ### `fetch`
61
-
62
- ## Package related commands
63
-
64
- ### `extract`
65
-
66
- ## `client` - API client for `mamiya master`
67
-
68
- ### `list-applications`
69
-
70
- ### `list-packages`
71
-
72
- ### `show-package`
73
-
74
- ### `list-agents`
75
-
76
- ### `show-agent`
77
-
78
- ### `show-distribution`
Binary file
@@ -1,58 +0,0 @@
1
- @startuml
2
- == Building ==
3
- Master --> Master: Build package
4
- note right of Master: e.g. assets precompile
5
- Master --> Storage: Upload package
6
-
7
- == Distributing ==
8
- Master --> Client: Download request
9
- activate Master
10
- Master --> Master: Wait all clients to have package to deploy
11
-
12
- alt if doesn't have package
13
- activate Client
14
- Client --> Client: Set status serf tag
15
- Client --> Storage: HTTP request
16
- Storage --> Client: Response package
17
- Client --> Client: Set packages serf tag
18
- Client --> Master: Report download finish
19
- deactivate Client
20
- end
21
-
22
- deactivate Master
23
-
24
- == Preparing ==
25
-
26
- Master --> Client: Request to prepare package
27
- activate Master
28
- Master --> Master: Wait all clients to have package to deploy
29
- activate Client
30
- Client --> Client: Set status serf tag
31
- Client --> Client: Unpack package
32
- Client --> Client: Run prepare phase
33
- note left of Client: e.g. bundle install, config files
34
- Client --> Client: Set prepared serf tag
35
- Client --> Client: Set status serf tag
36
- Client --> Master: Report preparation finish
37
- deactivate Client
38
- deactivate Master
39
-
40
- == Finalize ==
41
-
42
- Master --> Client: Request finalize
43
- activate Master
44
- Master --> Master: Wait all clients restarted
45
- activate Client
46
- Client --> Client: Set status serf tag
47
- Client --> Client: Run finalize phase
48
- note left of Client: e.g. restart web server
49
- Client --> Master: Report finalize complete
50
- Client --> Client: Set status serf tag
51
- Client --> Client: Wait to be reloaded
52
- Client --> Client: Set status serf tag
53
- Client --> Client: Set deployed serf tag
54
- Client --> Master: Report deploy complete
55
- deactivate Client
56
- deactivate Master
57
-
58
- @enduml