mina 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.
- data/.gitignore +4 -0
- data/.rspec +1 -0
- data/.travis.yml +13 -0
- data/Gemfile +10 -0
- data/HISTORY.md +148 -0
- data/LICENSE +23 -0
- data/README.md +620 -0
- data/Rakefile +33 -0
- data/bin/mina +49 -0
- data/data/deploy.rb +30 -0
- data/data/deploy.sh.erb +98 -0
- data/lib/mina.rb +20 -0
- data/lib/mina/bundler.rb +23 -0
- data/lib/mina/default.rb +97 -0
- data/lib/mina/deploy.rb +57 -0
- data/lib/mina/deploy_helpers.rb +25 -0
- data/lib/mina/git.rb +14 -0
- data/lib/mina/helpers.rb +278 -0
- data/lib/mina/rails.rb +69 -0
- data/lib/mina/rake.rb +6 -0
- data/lib/mina/settings.rb +32 -0
- data/lib/mina/tools.rb +14 -0
- data/lib/mina/version.rb +5 -0
- data/mina.gemspec +17 -0
- data/spec/command_helper.rb +52 -0
- data/spec/commands/command_spec.rb +65 -0
- data/spec/commands/deploy_spec.rb +36 -0
- data/spec/commands/outside_project_spec.rb +35 -0
- data/spec/commands/real_deploy_spec.rb +53 -0
- data/spec/commands/verbose_spec.rb +20 -0
- data/spec/dsl/queue_spec.rb +49 -0
- data/spec/dsl/settings_in_rake_spec.rb +42 -0
- data/spec/dsl/settings_spec.rb +60 -0
- data/spec/dsl/to_spec.rb +20 -0
- data/spec/spec_helper.rb +20 -0
- data/test_env/config/deploy.rb +54 -0
- metadata +117 -0
data/Rakefile
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
|
4
|
+
# Do these:
|
5
|
+
#
|
6
|
+
# *do `gem install reacco`
|
7
|
+
# * install http://github.com/rstacruz/git-update-ghpages
|
8
|
+
|
9
|
+
ENV['github'] ||= 'nadarei/mina'
|
10
|
+
|
11
|
+
namespace :doc do
|
12
|
+
|
13
|
+
task :build do
|
14
|
+
cmd = "reacco --literate --toc --github #{ENV['github']}"
|
15
|
+
cmd << " --analytics=#{ENV['analytics_id']}" if ENV['analytics_id']
|
16
|
+
|
17
|
+
system cmd
|
18
|
+
raise "Failed" unless $?.to_i == 0
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
desc "Updates online documentation"
|
23
|
+
task :deploy => :build do
|
24
|
+
system "git update-ghpages #{ENV['github']} -i doc"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
task :spec do
|
29
|
+
system "rm Gemfile.lock; sh -c 'rake=0.8 bundle exec rspec'"
|
30
|
+
system "rm Gemfile.lock; sh -c 'rake=0.9 bundle exec rspec'"
|
31
|
+
end
|
32
|
+
|
33
|
+
task :default => :spec
|
data/bin/mina
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
3
|
+
|
4
|
+
require 'rubygems' unless Object.const_defined?(:Gem)
|
5
|
+
require 'mina'
|
6
|
+
require 'rake'
|
7
|
+
|
8
|
+
# Intercept: if invoked as 'mina --help', don't let it pass through Rake, or else
|
9
|
+
# we'll see the Rake help screen. Redirect it to 'mina help'.
|
10
|
+
if ARGV.delete('--help') || ARGV.delete('-h')
|
11
|
+
ARGV << 'help'
|
12
|
+
end
|
13
|
+
|
14
|
+
if ARGV.delete('--version') || ARGV.delete('-V')
|
15
|
+
puts "Mina, version v#{Mina.version}"
|
16
|
+
exit
|
17
|
+
end
|
18
|
+
|
19
|
+
if ARGV.delete('--simulate') || ARGV.delete('-S')
|
20
|
+
ENV['simulate'] = '1'
|
21
|
+
end
|
22
|
+
|
23
|
+
scope = self
|
24
|
+
|
25
|
+
Rake.application.instance_eval do
|
26
|
+
standard_exception_handling do
|
27
|
+
# Initialize Rake and make it think it's Mina.
|
28
|
+
init 'mina'
|
29
|
+
@rakefiles = ['Minafile', 'config/deploy.rb']
|
30
|
+
|
31
|
+
# Workaround: Rake 0.9+ doesn't record task descriptions unless it's needed.
|
32
|
+
# Need it for 'mina help'
|
33
|
+
if Rake::TaskManager.respond_to?(:record_task_metadata)
|
34
|
+
Rake::TaskManager.record_task_metadata = true
|
35
|
+
end
|
36
|
+
|
37
|
+
# Load the Mina Rake DSL.
|
38
|
+
require 'mina/rake'
|
39
|
+
|
40
|
+
# Allow running without a Rakefile
|
41
|
+
load_rakefile if have_rakefile
|
42
|
+
|
43
|
+
# Run tasks
|
44
|
+
top_level
|
45
|
+
|
46
|
+
scope.mina_cleanup! if top_level_tasks.any?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
data/data/deploy.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'mina/bundler'
|
2
|
+
require 'mina/rails'
|
3
|
+
require 'mina/git'
|
4
|
+
|
5
|
+
# Basic settings:
|
6
|
+
# host - The hostname to SSH to
|
7
|
+
# deploy_to - Path to deploy into
|
8
|
+
# repository - Git repo to clone from (needed by mina/git)
|
9
|
+
# user - Username in the server to SSH to (optional)
|
10
|
+
|
11
|
+
set :host, 'foobar.com'
|
12
|
+
set :deploy_to, '/var/www/foobar.com'
|
13
|
+
set :repository, 'git://...'
|
14
|
+
# set :user, 'foobar.com'
|
15
|
+
|
16
|
+
desc "Deploys the current version to the server."
|
17
|
+
task :deploy do
|
18
|
+
deploy do
|
19
|
+
# Put things that will set up an empty directory into a fully set-up
|
20
|
+
# instance of your project.
|
21
|
+
invoke :'git:checkout'
|
22
|
+
invoke :'bundle:install'
|
23
|
+
invoke :'rails:db_migrate'
|
24
|
+
invoke :'rails:assets_precompile'
|
25
|
+
|
26
|
+
to :launch do
|
27
|
+
queue 'touch tmp/restart.txt'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/data/deploy.sh.erb
ADDED
@@ -0,0 +1,98 @@
|
|
1
|
+
<%
|
2
|
+
prepare = commands(:default).map { |s| "(\n\n#{indent 2, s}\n\n)" }.join(" && ")
|
3
|
+
launch = commands(:launch).map { |s| "(\n\n#{indent 2, s}\n\n)" }.join(" && ")
|
4
|
+
clean = commands(:clean).map { |s| "(\n\n#{indent 2, s}\n\n)" }.join(" && ")
|
5
|
+
%>
|
6
|
+
#!/usr/bin/env bash
|
7
|
+
|
8
|
+
# Go to the deploy path
|
9
|
+
cd "<%= deploy_to %>" || (
|
10
|
+
echo "=====> ERROR: not set up."
|
11
|
+
echo "The path '<%= deploy_to %>' is not accessible on the server."
|
12
|
+
echo "You may need to run 'mina setup' first."
|
13
|
+
false
|
14
|
+
) || exit 16
|
15
|
+
|
16
|
+
# Check lockfile
|
17
|
+
if [ -e "<%= lock_file %>" ]; then
|
18
|
+
echo "=====> ERROR: another deployment is ongoing."
|
19
|
+
echo "The file '<%= lock_file %>' was found."
|
20
|
+
echo "If no other deployment is ongoing, delete the file to continue."
|
21
|
+
exit 17
|
22
|
+
fi
|
23
|
+
|
24
|
+
# Determine $previous_path and other variables
|
25
|
+
[ -h "<%= current_path %>" ] && [ -d "<%= current_path %>" ] && previous_path=$(cd "<%= current_path %>" >/dev/null && pwd -LP)
|
26
|
+
build_path="./tmp/build-`date +%s`$RANDOM"
|
27
|
+
version=$((`cat "<%= deploy_to %>/last_version" 2>/dev/null`+1))
|
28
|
+
release_path="<%= releases_path %>/$version"
|
29
|
+
|
30
|
+
# Sanity check
|
31
|
+
if [ -e "$build_path" ]; then
|
32
|
+
echo "=====> ERROR: Path already exists"
|
33
|
+
exit 18
|
34
|
+
fi
|
35
|
+
|
36
|
+
# Bootstrap script (in deployer)
|
37
|
+
(
|
38
|
+
echo "-----> Creating a temporary build path"
|
39
|
+
<%= echo_cmd %[touch "#{lock_file}"] %> &&
|
40
|
+
<%= echo_cmd %[mkdir -p "$build_path"] %> &&
|
41
|
+
<%= echo_cmd %[cd "$build_path"] %> &&
|
42
|
+
(
|
43
|
+
<%= indent 4, (prepare.empty? ? "true" : prepare) %>
|
44
|
+
)
|
45
|
+
) &&
|
46
|
+
|
47
|
+
#
|
48
|
+
# Rename to the real release path, then symlink 'current'
|
49
|
+
(
|
50
|
+
echo "-----> Build finished"
|
51
|
+
echo "-----> Moving build to $release_path"
|
52
|
+
<%= echo_cmd %[mv "$build_path" "$release_path"] %> &&
|
53
|
+
|
54
|
+
echo "-----> Updating the <%= current_path %> symlink" &&
|
55
|
+
<%= echo_cmd %[ln -nfs "$release_path" "#{current_path}"] %>
|
56
|
+
) &&
|
57
|
+
|
58
|
+
# ============================
|
59
|
+
# === Start up serve => (in deployer)
|
60
|
+
(
|
61
|
+
echo "-----> Launching"
|
62
|
+
<%= echo_cmd %[cd "$release_path"] %>
|
63
|
+
<%= indent 2, (launch.empty? ? "true" : launch) %>
|
64
|
+
) &&
|
65
|
+
|
66
|
+
# ============================
|
67
|
+
# === Complete & unlock
|
68
|
+
(
|
69
|
+
rm -f "<%= lock_file %>"
|
70
|
+
echo "$version" > "./last_version"
|
71
|
+
echo "-----> Done. Deployed v$version"
|
72
|
+
) ||
|
73
|
+
|
74
|
+
# ============================
|
75
|
+
# === Failed deployment
|
76
|
+
(
|
77
|
+
echo "=====> ERROR: Deploy failed."
|
78
|
+
|
79
|
+
<%= indent 2, clean %>
|
80
|
+
|
81
|
+
echo "-----> Cleaning up build"
|
82
|
+
[ -e "$build_path" ] && (
|
83
|
+
<%= echo_cmd %[rm -rf "$build_path"] %>
|
84
|
+
)
|
85
|
+
[ -e "$release_path" ] && (
|
86
|
+
echo "Deleting release"
|
87
|
+
<%= echo_cmd %[rm -rf "$release_path"] %>
|
88
|
+
)
|
89
|
+
(
|
90
|
+
echo "Unlinking current"
|
91
|
+
[ -n "$previous_path" ] && <%= echo_cmd %[ln -nfs "$previous_path" "#{current_path}"] %>
|
92
|
+
)
|
93
|
+
|
94
|
+
# Unlock
|
95
|
+
<%= echo_cmd %[rm -f "#{lock_file}"] %>
|
96
|
+
echo "OK"
|
97
|
+
exit 8
|
98
|
+
)
|
data/lib/mina.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Mina
|
2
|
+
PREFIX = File.dirname(__FILE__)
|
3
|
+
ROOT = File.expand_path('../../', __FILE__)
|
4
|
+
|
5
|
+
require 'mina/version'
|
6
|
+
|
7
|
+
autoload :DeployHelpers, 'mina/deploy_helpers'
|
8
|
+
autoload :Helpers, 'mina/helpers'
|
9
|
+
autoload :Settings, 'mina/settings'
|
10
|
+
autoload :Tools, 'mina/tools'
|
11
|
+
|
12
|
+
Error = Class.new(Exception)
|
13
|
+
class Failed < Error
|
14
|
+
attr_accessor :exitstatus
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.root_path(*a)
|
18
|
+
File.join ROOT, *a
|
19
|
+
end
|
20
|
+
end
|
data/lib/mina/bundler.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
|
2
|
+
settings.bundle_path ||= './vendor/bundle'
|
3
|
+
settings.bundle_options ||= lambda { %{--without development:test --path "#{bundle_path}" --binstubs bin/ --deployment} }
|
4
|
+
|
5
|
+
namespace :bundle do
|
6
|
+
desc "Install gem dependencies using Bundler."
|
7
|
+
task :install do
|
8
|
+
if bundle_path.nil?
|
9
|
+
queue %{
|
10
|
+
echo "-----> Installing gem dependencies using Bundler"
|
11
|
+
#{echo_cmd %[bundle install #{bundle_options}]}
|
12
|
+
}
|
13
|
+
else
|
14
|
+
queue %{
|
15
|
+
echo "-----> Installing gem dependencies using Bundler"
|
16
|
+
#{echo_cmd %[mkdir -p "#{deploy_to}/#{shared_path}/bundle"]}
|
17
|
+
#{echo_cmd %[mkdir -p "#{File.dirname bundle_path}"]}
|
18
|
+
#{echo_cmd %[ln -s "#{deploy_to}/#{shared_path}/bundle" "#{bundle_path}"]}
|
19
|
+
#{echo_cmd %[bundle install #{bundle_options}]}
|
20
|
+
}
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/mina/default.rb
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
set_default :term_mode, nil
|
2
|
+
|
3
|
+
# Default tasks here
|
4
|
+
desc "Creates a sample config file."
|
5
|
+
task :init do
|
6
|
+
name = Rake.application.name
|
7
|
+
config_file = Rake.application.rakefile
|
8
|
+
|
9
|
+
unless config_file.to_s.empty?
|
10
|
+
error "You already have #{config_file}."
|
11
|
+
exit 8
|
12
|
+
end
|
13
|
+
|
14
|
+
require 'fileutils'
|
15
|
+
FileUtils.mkdir_p './config'
|
16
|
+
FileUtils.cp Mina.root_path('data/deploy.rb'), './config/deploy.rb'
|
17
|
+
|
18
|
+
puts 'Created deploy.rb.'
|
19
|
+
puts 'Edit it, then run `#{name} setup` after.'
|
20
|
+
end
|
21
|
+
|
22
|
+
task :default => :help
|
23
|
+
|
24
|
+
module HelpHelpers
|
25
|
+
def get_tasks(&blk)
|
26
|
+
Rake.application.tasks.select &blk
|
27
|
+
end
|
28
|
+
|
29
|
+
def print_tasks(tasks, width=nil)
|
30
|
+
name = Rake.application.name
|
31
|
+
|
32
|
+
width ||= tasks.map { |t| t.name_with_args.length }.max || 10
|
33
|
+
tasks.each do |t|
|
34
|
+
if t.comment
|
35
|
+
puts " #{name} %-#{width}s # %s" % [ t.name_with_args, t.comment ]
|
36
|
+
else
|
37
|
+
puts " #{name} %s" % [ t.name_with_args ]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
SYSTEM_TASKS = %w[help tasks init]
|
43
|
+
def system_tasks() get_tasks { |t| SYSTEM_TASKS.include? t.name }; end
|
44
|
+
def top_tasks() get_tasks { |t| ! t.name.include?(':') && t.comment && !system_tasks.include?(t) }; end
|
45
|
+
def sub_tasks() get_tasks { |t| t.name.include?(':') }; end
|
46
|
+
|
47
|
+
def show_task_help(options={})
|
48
|
+
puts "Basic usage:"
|
49
|
+
print_tasks system_tasks
|
50
|
+
|
51
|
+
if top_tasks.any?
|
52
|
+
puts "\nServer tasks:"
|
53
|
+
print_tasks top_tasks
|
54
|
+
end
|
55
|
+
|
56
|
+
if sub_tasks.any? && options[:full]
|
57
|
+
puts "\nMore tasks:"
|
58
|
+
print_tasks sub_tasks
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
extend HelpHelpers
|
64
|
+
|
65
|
+
desc "Show help."
|
66
|
+
task :help do
|
67
|
+
name = Rake.application.name
|
68
|
+
|
69
|
+
puts "#{name} - Really fast server deployment and automation tool\n\n"
|
70
|
+
puts "Options:"
|
71
|
+
|
72
|
+
opts = [
|
73
|
+
[ "-h, --help", "Show help" ],
|
74
|
+
[ "-V, --version", "Show program version" ],
|
75
|
+
[ "-v, --verbose", "Show commands as they happen" ],
|
76
|
+
[ "-S, --simulate", "Run in simulation mode" ],
|
77
|
+
[ "-t, --trace", "Show backtraces when errors occur" ]
|
78
|
+
]
|
79
|
+
opts.each { |args| puts " %-17s %s" % args }
|
80
|
+
puts ""
|
81
|
+
|
82
|
+
show_task_help
|
83
|
+
|
84
|
+
unless Rake.application.have_rakefile
|
85
|
+
puts ""
|
86
|
+
puts "Run this command in a project with a 'config/deploy.rb' file to see more options."
|
87
|
+
end
|
88
|
+
|
89
|
+
puts ""
|
90
|
+
puts "All of Rake's options are also available as '#{name}' options. See 'rake --help'"
|
91
|
+
puts "for more information."
|
92
|
+
end
|
93
|
+
|
94
|
+
desc "Show all tasks."
|
95
|
+
task :tasks do
|
96
|
+
show_task_help :full => true
|
97
|
+
end
|
data/lib/mina/deploy.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
set_default :releases_path, "releases"
|
2
|
+
set_default :shared_path, "shared"
|
3
|
+
set_default :current_path, "current"
|
4
|
+
set_default :lock_file, "deploy.lock"
|
5
|
+
|
6
|
+
namespace :deploy do
|
7
|
+
desc "Forces a deploy unlock."
|
8
|
+
task :force_unlock do
|
9
|
+
queue %{echo "-----> Unlocking"}
|
10
|
+
queue echo_cmd %{rm -f "#{deploy_to}/#{lock_file}"}
|
11
|
+
end
|
12
|
+
|
13
|
+
desc "Links paths set in :shared_paths."
|
14
|
+
task :link_shared_paths do
|
15
|
+
dirs = settings.shared_paths!.map { |file| File.dirname("./#{file}") }.uniq
|
16
|
+
|
17
|
+
cmds = dirs.map do |dir|
|
18
|
+
echo_cmd %{mkdir -p "#{dir}"}
|
19
|
+
end
|
20
|
+
|
21
|
+
cmds += shared_paths.map do |file|
|
22
|
+
echo_cmd %{ln -s "#{shared_path}/#{file}" "./#{file}"}
|
23
|
+
end
|
24
|
+
|
25
|
+
queue %{
|
26
|
+
echo "-----> Symlinking shared paths"
|
27
|
+
#{cmds.join(" &&\n")}
|
28
|
+
}
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Sets up a site."
|
33
|
+
task :setup do
|
34
|
+
settings.deploy_to!
|
35
|
+
|
36
|
+
queue %{echo "-----> Setting up #{deploy_to}"}
|
37
|
+
queue echo_cmd %{mkdir -p "#{deploy_to}"}
|
38
|
+
queue echo_cmd %{chown -R `whoami` "#{deploy_to}"}
|
39
|
+
queue echo_cmd %{chmod g+rx,u+rwx "#{deploy_to}"}
|
40
|
+
queue echo_cmd %{cd "#{deploy_to}"}
|
41
|
+
queue echo_cmd %{mkdir -p "#{releases_path}"}
|
42
|
+
queue echo_cmd %{chmod g+rx,u+rwx "#{releases_path}"}
|
43
|
+
queue echo_cmd %{mkdir -p "#{shared_path}"}
|
44
|
+
queue echo_cmd %{chmod g+rx,u+rwx "#{shared_path}"}
|
45
|
+
queue %{echo "-----> Done"}
|
46
|
+
end
|
47
|
+
|
48
|
+
desc "Runs a command in the server."
|
49
|
+
task :run, :command do |t, args|
|
50
|
+
command = args[:command]
|
51
|
+
unless command
|
52
|
+
puts %[You need to provide a command. Try: mina "run[ls -la]"]
|
53
|
+
exit 1
|
54
|
+
end
|
55
|
+
|
56
|
+
queue %[cd #{deploy_to!} && #{command}]
|
57
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Mina
|
2
|
+
module DeployHelpers
|
3
|
+
# Wraps the things inside it in a deploy script, and queues it.
|
4
|
+
# This generates a script using deploy_script and queues it.
|
5
|
+
def deploy(&blk)
|
6
|
+
queue deploy_script(&blk)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Wraps the things inside it in a deploy script.
|
10
|
+
#
|
11
|
+
# script = deploy_script do
|
12
|
+
# invoke :'git:checkout'
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# queue script
|
16
|
+
#
|
17
|
+
def deploy_script(&blk)
|
18
|
+
set_default :term_mode, :pretty
|
19
|
+
code = isolate do
|
20
|
+
yield
|
21
|
+
erb Mina.root_path('data/deploy.sh.erb')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/mina/git.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
namespace :git do
|
2
|
+
desc "Clones the Git repository to the release path."
|
3
|
+
task :clone do
|
4
|
+
settings.revision ||= `git rev-parse HEAD`.strip
|
5
|
+
|
6
|
+
queue %{
|
7
|
+
echo "-----> Cloning the Git repository"
|
8
|
+
#{echo_cmd %[git clone "#{repository!}" . -n --recursive]} &&
|
9
|
+
echo "-----> Using revision #{revision}" &&
|
10
|
+
#{echo_cmd %[git checkout "#{revision}" -b current_release 1>/dev/null]} &&
|
11
|
+
#{echo_cmd %[rm -rf .git]}
|
12
|
+
}
|
13
|
+
end
|
14
|
+
end
|