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,122 @@
|
|
1
|
+
# # Helpers: SSH helpers
|
2
|
+
# You don't need to invoke these helpers, they're already invoked automatically.
|
3
|
+
|
4
|
+
module Mina
|
5
|
+
module SshHelpers
|
6
|
+
|
7
|
+
# ### ssh
|
8
|
+
# Executes a command via SSH.
|
9
|
+
#
|
10
|
+
# Returns nothing usually, but if `{ return: true }` is given, returns the
|
11
|
+
# STDOUT output of the SSH session.
|
12
|
+
#
|
13
|
+
# `options` is a hash of options:
|
14
|
+
#
|
15
|
+
# - `:pretty` - Prettify the output if true.
|
16
|
+
# - `:return` - If set to true, returns the output.
|
17
|
+
#
|
18
|
+
# Example
|
19
|
+
#
|
20
|
+
# ssh("ls", return: true)
|
21
|
+
|
22
|
+
def ssh(cmd, options={})
|
23
|
+
require 'shellwords'
|
24
|
+
|
25
|
+
cmd = cmd.join("\n") if cmd.is_a?(Array)
|
26
|
+
script = Shellwords.escape(cmd)
|
27
|
+
|
28
|
+
if options[:return] == true
|
29
|
+
`#{ssh_command} -- #{script}`
|
30
|
+
|
31
|
+
elsif simulate_mode?
|
32
|
+
Ssh.simulate(cmd, ssh_command)
|
33
|
+
|
34
|
+
else
|
35
|
+
result = Ssh.invoke(script, self)
|
36
|
+
Ssh.ensure_successful result, self
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# ### ssh_command
|
41
|
+
# Returns the SSH command to be executed.
|
42
|
+
#
|
43
|
+
# set :domain, 'foo.com'
|
44
|
+
# set :user, 'diggity'
|
45
|
+
#
|
46
|
+
# puts ssh_command
|
47
|
+
# #=> 'ssh diggity@foo.com'
|
48
|
+
|
49
|
+
def ssh_command
|
50
|
+
args = domain!.dup
|
51
|
+
args = "#{user}@#{args}" if user?
|
52
|
+
args << " -i #{identity_file}" if identity_file?
|
53
|
+
args << " -p #{port}" if port?
|
54
|
+
args << " -A" if forward_agent?
|
55
|
+
args << " #{ssh_options}" if ssh_options?
|
56
|
+
args << " -t"
|
57
|
+
"ssh #{args}"
|
58
|
+
end
|
59
|
+
|
60
|
+
# ## Private methods
|
61
|
+
# `ssh` delegates to these.
|
62
|
+
|
63
|
+
module Ssh
|
64
|
+
|
65
|
+
extend self
|
66
|
+
|
67
|
+
# ### Ssh.simulate
|
68
|
+
# __Internal:__ Prints SSH command. Called by `ssh`.
|
69
|
+
|
70
|
+
def simulate(cmd, ssh_command)
|
71
|
+
str = "Executing the following via '#{ssh_command}':"
|
72
|
+
puts "#!/usr/bin/env bash"
|
73
|
+
puts "# #{str}"
|
74
|
+
puts "#"
|
75
|
+
|
76
|
+
puts cmd
|
77
|
+
|
78
|
+
0
|
79
|
+
end
|
80
|
+
|
81
|
+
# ### Ssh.invoke
|
82
|
+
# __Internal:__ Initiates an SSH session with script `script` with given
|
83
|
+
# `term_mode`. Called by `ssh`.
|
84
|
+
|
85
|
+
def invoke(script, this)
|
86
|
+
term_mode = :"#{this.settings.term_mode}"
|
87
|
+
code = "#{this.ssh_command} -- #{script}"
|
88
|
+
|
89
|
+
# Certain environments can't do :pretty mode.
|
90
|
+
term_mode = :exec if term_mode == :pretty && !pretty_supported?
|
91
|
+
|
92
|
+
case term_mode
|
93
|
+
when :pretty
|
94
|
+
this.pretty_system(code)
|
95
|
+
when :exec
|
96
|
+
exec code
|
97
|
+
else
|
98
|
+
system code
|
99
|
+
$?.to_i
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def pretty_supported?
|
104
|
+
# open4 is not supported under Windows.
|
105
|
+
# https://github.com/nadarei/mina/issues/58
|
106
|
+
require 'rbconfig'
|
107
|
+
! (RbConfig::CONFIG['host_os'] =~ /mswin|mingw/)
|
108
|
+
end
|
109
|
+
|
110
|
+
# ### Ssh.ensure_successful
|
111
|
+
# __Internal:__ Halts the execution if the given result code is not
|
112
|
+
# successful (non-zero).
|
113
|
+
|
114
|
+
def ensure_successful(result, this)
|
115
|
+
this.die result if result.is_a?(Fixnum) && result > 0
|
116
|
+
result
|
117
|
+
end
|
118
|
+
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
data/lib/mina/tools.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mina
|
2
|
+
module Tools
|
3
|
+
if IO.respond_to?(:popen4)
|
4
|
+
def self.popen4(*cmd, &blk)
|
5
|
+
IO.popen4 *cmd, &blk
|
6
|
+
$?
|
7
|
+
end
|
8
|
+
else
|
9
|
+
def self.popen4(*cmd, &blk)
|
10
|
+
require 'open4'
|
11
|
+
Open4.popen4 *cmd, &blk
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.pfork4(*cmd, &blk)
|
16
|
+
require 'open4'
|
17
|
+
Open4.pfork4 *cmd, &blk
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
data/lib/mina/version.rb
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# # Modules: Whenever
|
2
|
+
# Adds settings and tasks for managing projects with [whenever].
|
3
|
+
# [whenever]: http://rubygems.org/gems/whenever
|
4
|
+
|
5
|
+
namespace :whenever do
|
6
|
+
desc "Clear crontab"
|
7
|
+
task :clear do
|
8
|
+
queue %{
|
9
|
+
echo "-----> Clear crontab for #{domain}_#{rails_env}"
|
10
|
+
#{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; bundle exec whenever --clear-crontab #{domain}_#{rails_env} --set 'environment=#{rails_env}&path=#{deploy_to!}/#{current_path!}']}
|
11
|
+
}
|
12
|
+
end
|
13
|
+
desc "Update crontab"
|
14
|
+
task :update do
|
15
|
+
queue %{
|
16
|
+
echo "-----> Update crontab for #{domain}_#{rails_env}"
|
17
|
+
#{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; bundle exec whenever --update-crontab #{domain}_#{rails_env} --set 'environment=#{rails_env}&path=#{deploy_to!}/#{current_path!}']}
|
18
|
+
}
|
19
|
+
end
|
20
|
+
desc "Write crontab"
|
21
|
+
task :write do
|
22
|
+
queue %{
|
23
|
+
echo "-----> Update crontab for #{domain}_#{rails_env}"
|
24
|
+
#{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; bundle exec whenever --write-crontab #{domain}_#{rails_env} --set 'environment=#{rails_env}&path=#{deploy_to!}/#{current_path!}']}
|
25
|
+
}
|
26
|
+
end
|
27
|
+
end
|
data/manual/index.md
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# Welcome to 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
|
+
|
data/manual/modules.md
ADDED
data/mina.gemspec
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require './lib/mina/version'
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = "mina-traackr"
|
5
|
+
s.version = Mina.version
|
6
|
+
s.summary = %{Really fast deployer and server automation tool.}
|
7
|
+
s.description = %Q{Really fast deployer and server automation tool.}
|
8
|
+
s.authors = ["Rico Sta. Cruz", "Michael Galero"]
|
9
|
+
s.email = ["rico@nadarei.co", "mikong@nadarei.co"]
|
10
|
+
s.homepage = "http://github.com/nadarei/mina"
|
11
|
+
s.files = `git ls-files`.strip.split("\n")
|
12
|
+
s.executables = Dir["bin/*"].map { |f| File.basename(f) }
|
13
|
+
|
14
|
+
s.add_dependency "rake"
|
15
|
+
s.add_dependency "open4"
|
16
|
+
s.add_development_dependency "rspec"
|
17
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
# Invokes the main 'mina' command.
|
2
|
+
def run_command(*args)
|
3
|
+
out = ''
|
4
|
+
err = ''
|
5
|
+
@result = nil
|
6
|
+
|
7
|
+
if ENV['rake']
|
8
|
+
rake_version = "~> #{ENV['rake'] || '0.9'}.0"
|
9
|
+
script = %[require 'rubygems' unless Object.const_defined?(:Gem);]
|
10
|
+
script += %[gem 'rake', '#{rake_version}';]
|
11
|
+
script += %[load '#{root('bin/mina')}']
|
12
|
+
cmd = ['ruby', '-e', "#{script}", "--", *args]
|
13
|
+
else
|
14
|
+
cmd = [root('bin/mina'), *args]
|
15
|
+
end
|
16
|
+
|
17
|
+
status =
|
18
|
+
Mina::Tools.popen4(*cmd) do |pid, i, o, e|
|
19
|
+
out = o.read
|
20
|
+
err = e.read
|
21
|
+
end
|
22
|
+
|
23
|
+
@result = status.exitstatus
|
24
|
+
|
25
|
+
@out = out
|
26
|
+
@err = err
|
27
|
+
|
28
|
+
@result
|
29
|
+
end
|
30
|
+
|
31
|
+
# Invokes the main 'mina' command and ensures the exit status is success.
|
32
|
+
def mina(*args)
|
33
|
+
run_command *args
|
34
|
+
if exitstatus != 0 && ENV['verbose']
|
35
|
+
puts stdout
|
36
|
+
puts stderr
|
37
|
+
end
|
38
|
+
|
39
|
+
exitstatus.should == 0
|
40
|
+
end
|
41
|
+
|
42
|
+
def stdout
|
43
|
+
@out
|
44
|
+
end
|
45
|
+
|
46
|
+
def stderr
|
47
|
+
@err
|
48
|
+
end
|
49
|
+
|
50
|
+
def exitstatus
|
51
|
+
@result
|
52
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_helper'
|
3
|
+
|
4
|
+
describe "Invoking the 'mina deploy:cleanup' command" do
|
5
|
+
before :each do
|
6
|
+
Dir.chdir root('test_env')
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should cleanup old deployments" do
|
10
|
+
3.times { mina 'deploy' }
|
11
|
+
|
12
|
+
mina 'deploy:cleanup'
|
13
|
+
|
14
|
+
Dir["deploy/releases/*"].length.should == 2
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_helper'
|
3
|
+
|
4
|
+
describe "Invoking the 'mina' command in a project" do
|
5
|
+
before :each do
|
6
|
+
Dir.chdir root('test_env')
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should think it's 'mina', not 'rake' (1)" do
|
10
|
+
run_command 'pinkledills'
|
11
|
+
exitstatus.should_not == 0
|
12
|
+
stderr.should include 'mina aborted'
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should think it's 'mina', not 'rake' (1)" do
|
16
|
+
mina '-T'
|
17
|
+
stdout.should include 'mina help'
|
18
|
+
stdout.should include 'mina git:clone'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'with --version should print the version' do
|
22
|
+
mina '--version'
|
23
|
+
stdout.should include Mina.version
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'with -V should print the version' do
|
27
|
+
mina '-V'
|
28
|
+
stdout.should include Mina.version
|
29
|
+
end
|
30
|
+
|
31
|
+
describe 'without arguments' do
|
32
|
+
before :each do
|
33
|
+
mina
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'should print standard help tasks' do
|
37
|
+
mina
|
38
|
+
stdout.should include 'mina help'
|
39
|
+
stdout.should include 'mina init'
|
40
|
+
stdout.should include 'mina tasks'
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should print project-specific tasks' do
|
44
|
+
mina
|
45
|
+
stdout.should include 'mina deploy'
|
46
|
+
stdout.should include 'mina restart'
|
47
|
+
stdout.should include 'mina setup'
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be the same as running 'help'" do
|
51
|
+
previous_out = stdout
|
52
|
+
|
53
|
+
mina 'help'
|
54
|
+
stdout.should == previous_out
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
it "with 'mina -f' on a non-existing file should fail" do
|
59
|
+
run_command '-f', 'foobar'
|
60
|
+
stderr.should include 'mina aborted'
|
61
|
+
stderr.should include 'No Rakefile found'
|
62
|
+
end
|
63
|
+
|
64
|
+
it "with 'mina tasks' should print tasks" do
|
65
|
+
mina 'tasks'
|
66
|
+
|
67
|
+
stdout.should include('bundle:install')
|
68
|
+
stdout.should include('Install gem dependencies using Bundler')
|
69
|
+
stdout.should include('passenger:restart')
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_helper'
|
3
|
+
|
4
|
+
describe "Invoking the 'mina' command in a project without a deploy.rb" do
|
5
|
+
before :each do
|
6
|
+
Dir.chdir root('spec/fixtures/custom_file_env')
|
7
|
+
FileUtils.rm_rf 'deploy'
|
8
|
+
end
|
9
|
+
|
10
|
+
it 'should fail' do
|
11
|
+
run_command 'deploy', '--simulate'
|
12
|
+
exitstatus.should be > 0
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'should pass if you provide a new rakefile' do
|
16
|
+
mina 'deploy', '--simulate', '-f', 'custom_deploy.rb'
|
17
|
+
stdout.should include 'Creating a temporary build path'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_helper'
|
3
|
+
|
4
|
+
describe "Invoking the 'mina' command in a project" do
|
5
|
+
before :each do
|
6
|
+
Dir.chdir root('test_env')
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "to do a simulated deploy" do
|
10
|
+
before :each do
|
11
|
+
mina 'deploy', 'simulate=1'
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should take care of the lockfile" do
|
15
|
+
stdout.should =~ /ERROR: another deployment is ongoing/
|
16
|
+
stdout.should =~ /touch ".*deploy\.lock"/
|
17
|
+
stdout.should =~ /rm -f ".*deploy\.lock"/
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should honor releases_path" do
|
21
|
+
stdout.should include "releases/"
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should symlink the current_path" do
|
25
|
+
stdout.should =~ /ln .*current/
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should include deploy directives" do
|
29
|
+
stdout.should include "bundle exec rake db:migrate"
|
30
|
+
end
|
31
|
+
|
32
|
+
it "should include 'to :build' directives" do
|
33
|
+
stdout.should include "touch build.txt"
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should include 'to :launch' directives" do
|
37
|
+
stdout.should include "touch tmp/restart.txt"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'command_helper'
|
3
|
+
|
4
|
+
describe "Invoking the 'mina' command outside a project" do
|
5
|
+
before :each do
|
6
|
+
Dir.chdir root
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "without arguments" do
|
10
|
+
before :each do
|
11
|
+
mina
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'should print standard help tasks' do
|
15
|
+
stdout.should include('mina help')
|
16
|
+
stdout.should include('mina init')
|
17
|
+
stdout.should include('mina tasks')
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should not print project-specific tasks" do
|
21
|
+
stdout.should_not include('mina deploy')
|
22
|
+
stdout.should_not include('mina restart')
|
23
|
+
stdout.should_not include('mina setup')
|
24
|
+
end
|
25
|
+
|
26
|
+
%w[-h --help].each do |arg|
|
27
|
+
it "should have the same output as 'mina #{arg}'" do
|
28
|
+
@previous_output = stdout
|
29
|
+
mina arg
|
30
|
+
stdout.should == @previous_output
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|