mina-traackr 0.3.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/.gitignore +10 -0
- data/.rspec +1 -0
- data/.travis.yml +12 -0
- data/CONTRIBUTING.md +124 -0
- data/Gemfile +10 -0
- data/HISTORY.md +304 -0
- data/LICENSE +23 -0
- data/Makefile +29 -0
- data/Notes.md +72 -0
- data/Rakefile +20 -0
- data/Readme.md +1009 -0
- data/bin/mina +65 -0
- data/data/deploy.rb +74 -0
- data/data/deploy.sh.erb +120 -0
- data/lib/mina.rb +23 -0
- data/lib/mina/bundler.rb +44 -0
- data/lib/mina/chruby.rb +49 -0
- data/lib/mina/default.rb +144 -0
- data/lib/mina/deploy.rb +138 -0
- data/lib/mina/deploy_helpers.rb +34 -0
- data/lib/mina/exec_helpers.rb +104 -0
- data/lib/mina/foreman.rb +78 -0
- data/lib/mina/git.rb +62 -0
- data/lib/mina/helpers.rb +383 -0
- data/lib/mina/output_helpers.rb +92 -0
- data/lib/mina/rails.rb +206 -0
- data/lib/mina/rake.rb +9 -0
- data/lib/mina/rbenv.rb +47 -0
- data/lib/mina/rvm.rb +88 -0
- data/lib/mina/settings.rb +32 -0
- data/lib/mina/ssh_helpers.rb +122 -0
- data/lib/mina/tools.rb +20 -0
- data/lib/mina/version.rb +5 -0
- data/lib/mina/whenever.rb +27 -0
- data/manual/index.md +15 -0
- data/manual/modules.md +2 -0
- data/mina.gemspec +17 -0
- data/spec/command_helper.rb +52 -0
- data/spec/commands/cleanup_spec.rb +16 -0
- data/spec/commands/command_spec.rb +71 -0
- data/spec/commands/custom_config_spec.rb +20 -0
- data/spec/commands/deploy_spec.rb +40 -0
- data/spec/commands/outside_project_spec.rb +35 -0
- data/spec/commands/real_deploy_spec.rb +54 -0
- data/spec/commands/ssh_spec.rb +14 -0
- data/spec/commands/verbose_spec.rb +21 -0
- data/spec/dsl/invoke_spec.rb +33 -0
- data/spec/dsl/queue_spec.rb +49 -0
- data/spec/dsl/settings_in_rake_spec.rb +39 -0
- data/spec/dsl/settings_spec.rb +55 -0
- data/spec/dsl/to_spec.rb +20 -0
- data/spec/fixtures/custom_file_env/custom_deploy.rb +15 -0
- data/spec/fixtures/empty_env/config/deploy.rb +15 -0
- data/spec/helpers/output_helper_spec.rb +38 -0
- data/spec/spec_helper.rb +21 -0
- data/support/Readme-footer.md +32 -0
- data/support/Readme-header.md +17 -0
- data/support/guide.md +297 -0
- data/support/index.html +53 -0
- data/support/to_md.rb +11 -0
- data/test_env/config/deploy.rb +72 -0
- metadata +157 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_helper'
|
3
|
+
require 'fileutils'
|
4
|
+
require 'tmpdir'
|
5
|
+
|
6
|
+
describe "Invoking the 'mina' command in a project", :ssh => true do
|
7
|
+
before :each do
|
8
|
+
@path = Dir.mktmpdir
|
9
|
+
Dir.chdir @path
|
10
|
+
|
11
|
+
FileUtils.mkdir_p './config'
|
12
|
+
FileUtils.cp root('test_env/config/deploy.rb'), './config/deploy.rb'
|
13
|
+
FileUtils.rm_rf './deploy'
|
14
|
+
FileUtils.mkdir_p './deploy'
|
15
|
+
end
|
16
|
+
|
17
|
+
# after :each do
|
18
|
+
# FileUtils.rm_rf @path
|
19
|
+
# end
|
20
|
+
|
21
|
+
it 'should set up and deploy fine' do
|
22
|
+
print "[setup]" if ENV['verbose']
|
23
|
+
mina 'setup', '--verbose'
|
24
|
+
File.directory?('deploy').should be_true
|
25
|
+
File.directory?('deploy/releases').should be_true
|
26
|
+
File.directory?('deploy/shared').should be_true
|
27
|
+
File.exists?('deploy/last_version').should be_false
|
28
|
+
File.exists?('deploy/deploy.lock').should be_false
|
29
|
+
|
30
|
+
print "[deploy 1]" if ENV['verbose']
|
31
|
+
mina 'deploy', '--verbose'
|
32
|
+
stdout.should include "-----> Creating a temporary build path"
|
33
|
+
stdout.should include "rm -rf .git"
|
34
|
+
stdout.should include "mkdir -p"
|
35
|
+
File.exists?('deploy/last_version').should be_true
|
36
|
+
File.exists?('deploy/deploy.lock').should be_false
|
37
|
+
File.directory?('deploy/releases').should be_true
|
38
|
+
File.directory?('deploy/releases/1').should be_true
|
39
|
+
File.exists?('deploy/releases/1/README.md').should be_true
|
40
|
+
File.directory?('deploy/releases/2').should be_false
|
41
|
+
File.exists?('deploy/current').should be_true
|
42
|
+
File.read('deploy/last_version').strip.should == '1'
|
43
|
+
File.exists?('deploy/current/build.txt').should be_true
|
44
|
+
File.exists?('deploy/current/tmp/restart.txt').should be_true
|
45
|
+
|
46
|
+
# And again, to test out sequential versions and stuff
|
47
|
+
print "[deploy 2]" if ENV['verbose']
|
48
|
+
mina 'deploy'
|
49
|
+
stdout.should_not include "rm -rf .git"
|
50
|
+
stdout.should_not include "mkdir -p"
|
51
|
+
File.directory?('deploy/releases/2').should be_true
|
52
|
+
File.read('deploy/last_version').strip.should == '2'
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_helper'
|
3
|
+
|
4
|
+
describe "Invoking the 'mina' command in a project" do
|
5
|
+
|
6
|
+
it "should build ssh command even with frozen String as a domain" do
|
7
|
+
ENV['simulate'] = 'true'
|
8
|
+
rake {
|
9
|
+
set :domain, 'localhost'.freeze
|
10
|
+
ssh("ls")
|
11
|
+
}
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_helper'
|
3
|
+
require 'shellwords'
|
4
|
+
|
5
|
+
describe "Invoking the 'mina' command in a project" do
|
6
|
+
before :each do
|
7
|
+
Dir.chdir root('test_env')
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should echo commands in verbose mode' do
|
11
|
+
mina 'deploy', '--verbose', '--simulate'
|
12
|
+
|
13
|
+
stdout.should include %[echo #{Shellwords.escape('$ git')}]
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'should not echo commands when not in verbose mode' do
|
17
|
+
mina 'deploy', '--simulate'
|
18
|
+
|
19
|
+
stdout.should_not include %[echo #{Shellwords.escape('$ git')}]
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Mina' do
|
4
|
+
it '#invoke should work' do
|
5
|
+
|
6
|
+
rake {
|
7
|
+
task :clone do
|
8
|
+
queue 'git clone'
|
9
|
+
end
|
10
|
+
}
|
11
|
+
|
12
|
+
2.times {
|
13
|
+
rake { invoke :clone }
|
14
|
+
}
|
15
|
+
|
16
|
+
rake.commands.should == ['git clone']
|
17
|
+
end
|
18
|
+
|
19
|
+
it '#invoke should work with :reenable option' do
|
20
|
+
|
21
|
+
rake {
|
22
|
+
task :pull do
|
23
|
+
queue 'git pull'
|
24
|
+
end
|
25
|
+
}
|
26
|
+
|
27
|
+
2.times {
|
28
|
+
rake { invoke :pull, :reenable => true }
|
29
|
+
}
|
30
|
+
|
31
|
+
rake.commands.should == ['git pull', 'git pull']
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Mina' do
|
4
|
+
it '#invoke should work' do
|
5
|
+
rake {
|
6
|
+
task :hello do
|
7
|
+
@hello = 'world'
|
8
|
+
end
|
9
|
+
invoke :hello
|
10
|
+
}
|
11
|
+
rake.instance_variable_get(:@hello).should == 'world'
|
12
|
+
end
|
13
|
+
|
14
|
+
it '#queue should work' do
|
15
|
+
rake {
|
16
|
+
queue 'sudo service nginx restart'
|
17
|
+
}
|
18
|
+
|
19
|
+
rake.commands.should == ['sudo service nginx restart']
|
20
|
+
end
|
21
|
+
|
22
|
+
it '#queue should work with multiple commands' do
|
23
|
+
rake {
|
24
|
+
queue 'echo Restarting'
|
25
|
+
queue 'sudo service nginx restart'
|
26
|
+
}
|
27
|
+
|
28
|
+
rake.commands.should == ['echo Restarting', 'sudo service nginx restart']
|
29
|
+
end
|
30
|
+
|
31
|
+
it '#queue should work inside tasks' do
|
32
|
+
rake {
|
33
|
+
task :restart do
|
34
|
+
queue 'echo Restarting'
|
35
|
+
invoke :'passenger:restart'
|
36
|
+
end
|
37
|
+
|
38
|
+
namespace :passenger do
|
39
|
+
task :restart do
|
40
|
+
queue 'touch tmp/restart.txt'
|
41
|
+
end
|
42
|
+
end
|
43
|
+
}
|
44
|
+
|
45
|
+
rake { invoke :restart }
|
46
|
+
|
47
|
+
rake.commands.should == ['echo Restarting', 'touch tmp/restart.txt']
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Settings in rake tasks' do
|
4
|
+
it '#set should work' do
|
5
|
+
rake { set :domain, 'localhost' }
|
6
|
+
|
7
|
+
rake.domain.should == 'localhost'
|
8
|
+
rake.settings.domain.should == 'localhost'
|
9
|
+
end
|
10
|
+
|
11
|
+
it '#settings ||= should work' do
|
12
|
+
rake {
|
13
|
+
set :version, '2'
|
14
|
+
settings.version ||= '3'
|
15
|
+
}
|
16
|
+
|
17
|
+
rake.settings.version.should == '2'
|
18
|
+
rake.version.should == '2'
|
19
|
+
end
|
20
|
+
|
21
|
+
it '#settings with lambdas should work' do
|
22
|
+
rake {
|
23
|
+
set :version, '42'
|
24
|
+
set :path, lambda { "/var/www/#{version}" }
|
25
|
+
}
|
26
|
+
|
27
|
+
rake.path.should == "/var/www/42"
|
28
|
+
rake.path?.should be_true
|
29
|
+
end
|
30
|
+
|
31
|
+
it '#settings with a bang should work' do
|
32
|
+
expect {
|
33
|
+
rake {
|
34
|
+
set :path, lambda { "/var/www/#{version!}" }
|
35
|
+
}
|
36
|
+
rake.path
|
37
|
+
}.to raise_error(Mina::Error, /version/)
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Settings' do
|
4
|
+
describe 'instances' do
|
5
|
+
before :each do
|
6
|
+
@settings = Mina::Settings.new
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'setting/getting should work' do
|
10
|
+
@settings.domain = '192.168.1.1'
|
11
|
+
@settings.domain.should == '192.168.1.1'
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'question mark should work' do
|
15
|
+
@settings.deploy_to = '/var/www/there'
|
16
|
+
@settings.deploy_to?.should be_true
|
17
|
+
@settings.foobar?.should be_false
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'question mark should work with nils' do
|
21
|
+
@settings.deploy_to = nil
|
22
|
+
@settings.deploy_to?.should be_true
|
23
|
+
@settings.foobar?.should be_false
|
24
|
+
end
|
25
|
+
|
26
|
+
it '||= should work (1)' do
|
27
|
+
@settings.x = 2
|
28
|
+
@settings.x ||= 3
|
29
|
+
@settings.x.should == 2
|
30
|
+
end
|
31
|
+
|
32
|
+
it '||= should work (2)' do
|
33
|
+
@settings.x ||= 3
|
34
|
+
@settings.x.should == 3
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'lambdas should work' do
|
38
|
+
@settings.path = lambda { "/var/www/#{@settings.version}" }
|
39
|
+
@settings.version = '3'
|
40
|
+
|
41
|
+
@settings.path?.should be_true
|
42
|
+
@settings.path.should == "/var/www/3"
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'bangs should check for settings' do
|
46
|
+
expect { @settings.non_existent_setting! }.to raise_error(Mina::Error, /non_existent_setting/)
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'bangs should return settings' do
|
50
|
+
@settings.version = 4
|
51
|
+
@settings.version!.should == 4
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
data/spec/dsl/to_spec.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Mina' do
|
4
|
+
it '#to should work' do
|
5
|
+
rake {
|
6
|
+
task :deploy do
|
7
|
+
queue 'git clone'
|
8
|
+
|
9
|
+
to :restart do
|
10
|
+
queue 'touch tmp/restart.txt'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
}
|
14
|
+
|
15
|
+
rake { invoke :deploy }
|
16
|
+
|
17
|
+
rake.commands.should == ['git clone']
|
18
|
+
rake.commands(:restart).should == ['touch tmp/restart.txt']
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
FileUtils.mkdir_p "#{Dir.pwd}/deploy"
|
3
|
+
|
4
|
+
require 'mina/git'
|
5
|
+
|
6
|
+
set :domain, 'localhost'
|
7
|
+
set :deploy_to, "#{Dir.pwd}/deploy"
|
8
|
+
set :repository, "#{Dir.pwd}"
|
9
|
+
|
10
|
+
desc "Deploys."
|
11
|
+
task :deploy do
|
12
|
+
deploy do
|
13
|
+
invoke :'git:clone'
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
FileUtils.mkdir_p "#{Dir.pwd}/deploy"
|
3
|
+
|
4
|
+
require 'mina/git'
|
5
|
+
|
6
|
+
set :domain, 'localhost'
|
7
|
+
set :deploy_to, "#{Dir.pwd}/deploy"
|
8
|
+
set :repository, "#{Dir.pwd}"
|
9
|
+
|
10
|
+
desc "Deploys."
|
11
|
+
task :deploy do
|
12
|
+
deploy do
|
13
|
+
invoke :'git:clone'
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Output Helpers' do
|
4
|
+
before :each do
|
5
|
+
@out = Object.new
|
6
|
+
@out.send :extend, Mina::OutputHelpers
|
7
|
+
|
8
|
+
allow(@out).to receive(:print_stdout)
|
9
|
+
allow(@out).to receive(:print_status)
|
10
|
+
allow(@out).to receive(:print_error)
|
11
|
+
allow(@out).to receive(:print_command)
|
12
|
+
allow(@out).to receive(:print_clear)
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'print_str to stdout' do
|
16
|
+
@out.print_str "Hello there\n"
|
17
|
+
|
18
|
+
expect(@out).to have_received(:print_stdout).with("Hello there\n")
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'print_str to status' do
|
22
|
+
@out.print_str "-----> Getting password"
|
23
|
+
|
24
|
+
expect(@out).to have_received(:print_status).with("Getting password")
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'print_str to status (2)' do
|
28
|
+
@out.print_str "-> Getting password"
|
29
|
+
|
30
|
+
expect(@out).to have_received(:print_status).with("Getting password")
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'print_str to error' do
|
34
|
+
@out.print_str "! Something went wrong"
|
35
|
+
|
36
|
+
expect(@out).to have_received(:print_error).with("Something went wrong")
|
37
|
+
end
|
38
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'mina'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
class RakeScope
|
5
|
+
include Rake::DSL if Rake.const_defined?(:DSL)
|
6
|
+
include Mina::Helpers
|
7
|
+
include Mina::SshHelpers
|
8
|
+
end
|
9
|
+
|
10
|
+
def rake(&blk)
|
11
|
+
if block_given?
|
12
|
+
@scope ||= RakeScope.new
|
13
|
+
@scope.instance_eval &blk
|
14
|
+
end
|
15
|
+
|
16
|
+
@scope
|
17
|
+
end
|
18
|
+
|
19
|
+
def root(*a)
|
20
|
+
File.join File.expand_path('../../', __FILE__), *a
|
21
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
|
2
|
+
Acknowledgements
|
3
|
+
----------------
|
4
|
+
|
5
|
+
© 2012-2013, Nadarei. Released under the [MIT
|
6
|
+
License](http://www.opensource.org/licenses/mit-license.php).
|
7
|
+
|
8
|
+
Mina is authored and maintained by [Rico Sta. Cruz][rsc] and [Michael
|
9
|
+
Galero][mg] with help from its [contributors][c]. It is sponsored by our
|
10
|
+
startup, [Nadarei][nd].
|
11
|
+
|
12
|
+
* [Nadarei](http://nadarei.co) (nadarei.co)
|
13
|
+
* [Github](http://github.com/nadarei) (@nadarei)
|
14
|
+
|
15
|
+
Rico:
|
16
|
+
|
17
|
+
* [My website](http://ricostacruz.com) (ricostacruz.com)
|
18
|
+
* [Github](http://github.com/rstacruz) (@rstacruz)
|
19
|
+
* [Twitter](http://twitter.com/rstacruz) (@rstacruz)
|
20
|
+
|
21
|
+
Michael:
|
22
|
+
|
23
|
+
* [My website][mg] (michaelgalero.com)
|
24
|
+
* [Github](http://github.com/mikong) (@mikong)
|
25
|
+
|
26
|
+
[rsc]: http://ricostacruz.com
|
27
|
+
[mg]: http://devblog.michaelgalero.com/
|
28
|
+
[c]: http://github.com/nadarei/mina/contributors
|
29
|
+
[nd]: http://nadarei.co
|
30
|
+
[issues]: https://github.com/nadarei/mina/issues
|
31
|
+
[trello]: https://trello.com/board/mina/4fc8b3023d9c9a4d72e573e6
|
32
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# Mina
|
2
|
+
|
3
|
+
Really fast deployer and server automation tool.
|
4
|
+
|
5
|
+
Mina works really fast because it's a deploy Bash script generator. It
|
6
|
+
generates an entire procedure as a Bash script and runs it remotely in the
|
7
|
+
server.
|
8
|
+
|
9
|
+
Compare this to the likes of Vlad or Capistrano, where each command
|
10
|
+
is ran separately on their own SSH sessions. Mina only creates *one* SSH
|
11
|
+
session per deploy, minimizing the SSH connection overhead.
|
12
|
+
|
13
|
+
$ gem install mina
|
14
|
+
$ mina
|
15
|
+
|
16
|
+
[](http://travis-ci.org/nadarei/mina) [](http://badge.fury.io/rb/mina)
|
17
|
+
|
data/support/guide.md
ADDED
@@ -0,0 +1,297 @@
|
|
1
|
+
|
2
|
+
User guide
|
3
|
+
==========
|
4
|
+
|
5
|
+
Setting up a project
|
6
|
+
--------------------
|
7
|
+
|
8
|
+
Let's deploy a project using Mina.
|
9
|
+
|
10
|
+
### Step 1: Create a config/deploy.rb
|
11
|
+
|
12
|
+
In your project, type `mina init` to create a sample of this file.
|
13
|
+
|
14
|
+
$ mina init
|
15
|
+
Created config/deploy.rb.
|
16
|
+
|
17
|
+
This is just a Rake file with tasks! See [About deploy.rb](#about-deployrb) for
|
18
|
+
more info on what *deploy.rb* is. You will want to at least configure your
|
19
|
+
server:
|
20
|
+
|
21
|
+
~~~ ruby
|
22
|
+
# config/deploy.rb
|
23
|
+
set :user, 'username'
|
24
|
+
set :domain, 'your.server.com'
|
25
|
+
set :deploy_to, '/var/www/flipstack.com'
|
26
|
+
...
|
27
|
+
~~~
|
28
|
+
|
29
|
+
### Step 2: Set up your server
|
30
|
+
|
31
|
+
Make a directory in your server called `/var/www/flipstack.com` (in *deploy_to*)
|
32
|
+
change it's ownership to the correct user.
|
33
|
+
|
34
|
+
$ ssh username@your.server.com
|
35
|
+
|
36
|
+
# Once in your server, create the deploy folder:
|
37
|
+
~@your.server.com$ mkdir /var/www/flipstack.com
|
38
|
+
~@your.server.com$ chown -R username /var/www/flipstack.com
|
39
|
+
|
40
|
+
### Step 3: Run 'mina setup'
|
41
|
+
|
42
|
+
Back at your computer, do `mina setup` to set up the [folder
|
43
|
+
structure](#directory_structure) in this path. This will connect to your server
|
44
|
+
via SSH and create the right directories.
|
45
|
+
|
46
|
+
$ mina setup
|
47
|
+
-----> Creating folders... done.
|
48
|
+
|
49
|
+
See [directory structure](#directory_structure) for more info.
|
50
|
+
|
51
|
+
### Step 4: Deploy!
|
52
|
+
|
53
|
+
Use `mina deploy` to run the `deploy` task defined in *config/deploy.rb*.
|
54
|
+
|
55
|
+
$ mina deploy
|
56
|
+
-----> Deploying to 2012-06-12-040248
|
57
|
+
...
|
58
|
+
Lots of things happening...
|
59
|
+
...
|
60
|
+
-----> Done.
|
61
|
+
|
62
|
+
About deploy.rb
|
63
|
+
---------------
|
64
|
+
|
65
|
+
The file `deploy.rb` is simply a Rakefile invoked by Rake. In fact, `mina` is
|
66
|
+
mostly an alias that invokes Rake to load `deploy.rb`.
|
67
|
+
|
68
|
+
~~~ ruby
|
69
|
+
# Sample config/deploy.rb
|
70
|
+
set :domain, 'your.server.com'
|
71
|
+
|
72
|
+
task :restart do
|
73
|
+
queue 'sudo service restart apache'
|
74
|
+
end
|
75
|
+
~~~
|
76
|
+
|
77
|
+
As it's all Rake, you can define tasks that you can invoke using `mina`. In this
|
78
|
+
example, it provides the `mina restart` command.
|
79
|
+
|
80
|
+
The magic of Mina is in the new commands it gives you.
|
81
|
+
|
82
|
+
The `queue` command queues up Bash commands to be ran on the remote server.
|
83
|
+
If you invoke `mina restart`, it will invoke the task above and run the queued
|
84
|
+
commands on the remote server `your.server.com` via SSH.
|
85
|
+
|
86
|
+
See [the command queue](#the-command-queue) for more information on the *queue*
|
87
|
+
command.
|
88
|
+
|
89
|
+
The command queue
|
90
|
+
-----------------
|
91
|
+
|
92
|
+
At the heart of it, Mina is merely sugar on top of Rake to queue commands
|
93
|
+
and execute them remotely at the end. Take a look at this minimal *deploy.rb*
|
94
|
+
configuration:
|
95
|
+
|
96
|
+
~~~ ruby
|
97
|
+
# config/deploy.rb
|
98
|
+
set :user, 'john'
|
99
|
+
set :domain, 'flipstack.com'
|
100
|
+
|
101
|
+
task :logs do
|
102
|
+
queue 'echo "Contents of the log file are as follows:"'
|
103
|
+
queue "tail -f /var/log/apache.log"
|
104
|
+
end
|
105
|
+
~~~
|
106
|
+
|
107
|
+
Once you type `mina logs` in your terminal, it invokes the *queue*d commands
|
108
|
+
remotely on the server using the command `ssh john@flipstack.com`.
|
109
|
+
|
110
|
+
~~~ sh
|
111
|
+
$ mina logs --simulate
|
112
|
+
# Execute the following commands via
|
113
|
+
# ssh john@flipstack.com:
|
114
|
+
#
|
115
|
+
echo "Contents of the log file are as follows:"
|
116
|
+
tail -f /var/log/apache.log
|
117
|
+
~~~
|
118
|
+
|
119
|
+
Subtasks
|
120
|
+
--------
|
121
|
+
|
122
|
+
Mina provides the helper `invoke` to invoke other tasks from a
|
123
|
+
task.
|
124
|
+
|
125
|
+
~~~ ruby
|
126
|
+
# config/deploy.rb
|
127
|
+
task :down do
|
128
|
+
invoke :maintenance_on
|
129
|
+
invoke :restart
|
130
|
+
end
|
131
|
+
|
132
|
+
task :maintenance_on
|
133
|
+
queue 'touch maintenance.txt'
|
134
|
+
end
|
135
|
+
|
136
|
+
task :restart
|
137
|
+
queue 'sudo service restart apache'
|
138
|
+
end
|
139
|
+
~~~
|
140
|
+
|
141
|
+
In this example above, if you type `mina down`, it simply invokes the other
|
142
|
+
subtasks which queues up their commands. The commands will be ran after
|
143
|
+
everything.
|
144
|
+
|
145
|
+
Directory structure
|
146
|
+
-------------------
|
147
|
+
|
148
|
+
The deploy procedures make the assumption that you have a folder like so:
|
149
|
+
|
150
|
+
/var/www/flipstack.com/ # The deploy_to path
|
151
|
+
|- releases/ # Holds releases, one subdir per release
|
152
|
+
| |- 1/
|
153
|
+
| |- 2/
|
154
|
+
| |- 3/
|
155
|
+
| '- ...
|
156
|
+
|- shared/ # Holds files shared between releases
|
157
|
+
| |- logs/ # Log files are usually stored here
|
158
|
+
| `- ...
|
159
|
+
'- current/ # A symlink to the current release in releases/
|
160
|
+
|
161
|
+
It also assumes that the `deploy_to` path is fully writeable/readable for the
|
162
|
+
user we're going to SSH with.
|
163
|
+
|
164
|
+
Deploying
|
165
|
+
---------
|
166
|
+
|
167
|
+
Mina provides the `deploy` command which *queue*s up a deploy script for
|
168
|
+
you.
|
169
|
+
|
170
|
+
~~~ ruby
|
171
|
+
# config/deploy.rb
|
172
|
+
set :domain, 'flipstack.com'
|
173
|
+
set :user, 'flipstack'
|
174
|
+
set :deploy_to, '/var/www/flipstack.com'
|
175
|
+
set :repository, 'http://github.com/flipstack/flipstack.git'
|
176
|
+
|
177
|
+
task :deploy do
|
178
|
+
deploy do
|
179
|
+
# Put things that prepare the empty release folder here.
|
180
|
+
# Commands queued here will be ran on a new release directory.
|
181
|
+
invoke :'git:clone'
|
182
|
+
invoke :'bundle:install'
|
183
|
+
|
184
|
+
# These are instructions to start the app after it's been prepared.
|
185
|
+
to :launch do
|
186
|
+
queue 'touch tmp/restart.txt'
|
187
|
+
end
|
188
|
+
|
189
|
+
# This optional block defines how a broken release should be cleaned up.
|
190
|
+
to :clean do
|
191
|
+
queue 'log "failed deployment"'
|
192
|
+
end
|
193
|
+
end
|
194
|
+
end
|
195
|
+
~~~
|
196
|
+
|
197
|
+
It works by capturing the *queue*d commands inside the block, wrapping them
|
198
|
+
in a deploy script, then *queue*ing them back in.
|
199
|
+
|
200
|
+
### How deploying works
|
201
|
+
|
202
|
+
Here is an example of a deploy! (Note that some commands have been simplified
|
203
|
+
to illustrate the point better.)
|
204
|
+
|
205
|
+
### Step 1: Build it
|
206
|
+
|
207
|
+
The deploy process builds a new temp folder with instructions you provide.
|
208
|
+
In this example, it will do `git:clone` and `bundle:install`.
|
209
|
+
|
210
|
+
$ mina deploy --verbose
|
211
|
+
-----> Creating the build path
|
212
|
+
$ mkdir tmp/build-128293482394
|
213
|
+
-----> Cloning the Git repository
|
214
|
+
$ git clone https://github.com/flipstack/flipstack.git . -n --recursive
|
215
|
+
Cloning... done.
|
216
|
+
-----> Installing gem dependencies using Bundler
|
217
|
+
$ bundle install --without development:test
|
218
|
+
Using i18n (0.6.0)
|
219
|
+
Using multi_json (1.0.4)
|
220
|
+
...
|
221
|
+
Your bundle is complete! It was installed to ./vendor/bundle
|
222
|
+
|
223
|
+
### Step 2: Move it to releases
|
224
|
+
|
225
|
+
Once the project has been built, it will be moved to `releases/`. A symlink
|
226
|
+
called `current/` will be created to point to the active release.
|
227
|
+
|
228
|
+
$
|
229
|
+
-----> Moving to releases/4
|
230
|
+
$ mv "./tmp/build-128293482394" "releases/4"
|
231
|
+
-----> Symlinking to current
|
232
|
+
$ ln -nfs releases/4 current
|
233
|
+
|
234
|
+
### Step 3: Launch it
|
235
|
+
|
236
|
+
Invoke the commands queued up in the `to :launch` block. These often
|
237
|
+
commands to restart the webserver process. Once this in complete, you're done!
|
238
|
+
|
239
|
+
$
|
240
|
+
-----> Launching
|
241
|
+
$ cd releases/4
|
242
|
+
$ sudo service nginx restart
|
243
|
+
-----> Done. Deployed v4
|
244
|
+
|
245
|
+
### What about failure?
|
246
|
+
|
247
|
+
If it fails at any point, the release path will be deleted. If any commands are
|
248
|
+
queued using the `to :clean` block, they will be ran. It will be as if nothing
|
249
|
+
happened. Lets see what happens if a build fails:
|
250
|
+
|
251
|
+
$
|
252
|
+
-----> Launching
|
253
|
+
$ cd releases/4
|
254
|
+
$ sudo service nginx restart
|
255
|
+
Starting nginx... error: can't start service
|
256
|
+
-----> ERROR: Deploy failed.
|
257
|
+
-----> Cleaning up build
|
258
|
+
$ rm -rf tmp/build-128293482394
|
259
|
+
-----> Unlinking current
|
260
|
+
$ ln -nfs releases/3 current
|
261
|
+
OK
|
262
|
+
|
263
|
+
Command line options
|
264
|
+
--------------------
|
265
|
+
|
266
|
+
Basic usage:
|
267
|
+
|
268
|
+
$ mina [OPTIONS] [TASKS] [VAR1=val VAR2=val ...]
|
269
|
+
|
270
|
+
### Options
|
271
|
+
|
272
|
+
* `-v` / `--verbose` - This will show commands being done on the server. Off by
|
273
|
+
default.
|
274
|
+
|
275
|
+
* `-S` / `--simulate` - This will not invoke any SSH connections; instead, it
|
276
|
+
will simply output the script it builds.
|
277
|
+
|
278
|
+
* `-t` / `--trace` - Show backtraces when errors occur.
|
279
|
+
|
280
|
+
* `-f FILE` - Use a custom deploy.rb configuration.
|
281
|
+
|
282
|
+
* `-V` / `--version` - Shows the current version.
|
283
|
+
|
284
|
+
### Tasks
|
285
|
+
|
286
|
+
There are many tasks available. See the [tasks reference](tasks/index.html), or
|
287
|
+
type `mina tasks`.
|
288
|
+
|
289
|
+
### Variables
|
290
|
+
|
291
|
+
You may specify additional variables in the `KEY=value` style, just like Rake.
|
292
|
+
You can add as many variables as needed.
|
293
|
+
|
294
|
+
$ mina restart on=staging
|
295
|
+
|
296
|
+
# This sets the ENV['on'] variable to 'staging'.
|
297
|
+
|