caplets 1.0.0 → 1.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,2 +1,7 @@
1
+ == 1.0.1
2
+ * bundle:install now uses `bundle check` to short-circuit if possible
3
+ * Add deploy:passenger:reload
4
+ * Add ssh, ssh:app, and ssh:web
5
+
1
6
  == 1.0.0
2
7
  * Initial public release
data/MODULES.md CHANGED
@@ -1,10 +1,9 @@
1
1
  Caplets Modules
2
2
  ===============
3
3
 
4
- caplets/deploy
5
- --------------
4
+ ## caplets/deploy
6
5
 
7
- #### Variables
6
+ ### Variables
8
7
 
9
8
  `:bin_cmd` - Command used to execute binaries within the context of the app.
10
9
  For instance, `caplets/bundle` sets this to `gem exec`. (default: `nil`)
@@ -24,12 +23,12 @@ caplets/deploy
24
23
 
25
24
  `:user` - UNIX user as which to login and run deploys. (default: `deploy`)
26
25
 
27
- ### caplets/bundle
26
+ ## caplets/bundle
28
27
 
29
28
  Bundler 0.9+ support. By default, run after every code update, this `bundle
30
29
  install`s gems into the project (not into system gems to avoid using `sudo`).
31
30
 
32
- #### Variables
31
+ ### Variables
33
32
 
34
33
  `:bundle_exclude` - Bundler groups to exclude from installation. Passed to
35
34
  bundler's `--without` switch. (default: `%w[development test]`)
@@ -39,16 +38,16 @@ install`s gems into the project (not into system gems to avoid using `sudo`).
39
38
  `:bundle_to` - Subdirectory of the application in which to put installed gems.
40
39
  Passed as an argument to `bundle install`. (default: `vendor/bundled_gems`)
41
40
 
42
- #### Tasks
41
+ ### Tasks
43
42
 
44
43
  `deploy:bundle:install` - Runs a `bundle install` to install needed gems from
45
44
  the application's Gemfile.
46
45
 
47
- #### Hooks
46
+ ### Hooks
48
47
 
49
48
  `deploy:bundle:install` after `deploy:update_code`
50
49
 
51
- ### caplets/db
50
+ ## caplets/db
52
51
 
53
52
  Tasks to support using ActiveRecord within your applications. This module
54
53
  adds functionality to write out your `database.yml` file and provides a
@@ -59,7 +58,7 @@ deployed to your DB server. This means you don't even have to list it in your
59
58
  deploy file. Instead, it expects to run your migrations from your `:primary
60
59
  :app` server.
61
60
 
62
- #### Variables
61
+ ### Variables
63
62
 
64
63
  `:db_host` - default: `localhost`
65
64
  `:db_adapter` - default: `mysql`
@@ -77,7 +76,7 @@ for your current `:environment`. If you'd rather, you can specify the entire
77
76
  environment key. Useful for adding access to slaves or other DBs.
78
77
  (default: {})
79
78
 
80
- #### Tasks
79
+ ### Tasks
81
80
 
82
81
  `deploy:db:config` - Write a generated `database.yml` to your project's config
83
82
  directory.
@@ -87,26 +86,26 @@ for your current `:environment`. If you'd rather, you can specify the entire
87
86
  `deploy:migrations` - Do a deploy with migrations, including doing a
88
87
  `web:disable` first and restarting (not reloading) the backends
89
88
 
90
- #### Hooks
89
+ ### Hooks
91
90
 
92
91
  `deploy:db:config` after `deploy:setup`
93
92
 
94
- ### caplets/git-tag
93
+ ## caplets/git-tag
95
94
 
96
95
  Automatically tag a revision on deploy.
97
96
 
98
- #### Tasks
97
+ ### Tasks
99
98
 
100
99
  `git:tag_current_release` - Tag the `:current_revision` with a tag like
101
100
  `deploy-<environment>-<timestamp>` and push it to the origin.
102
101
 
103
- #### Hooks
102
+ ### Hooks
104
103
 
105
104
  `git:tag_current_release` after `deploy:migrations`
106
105
  `git:tag_current_release` after `deploy:quick`
107
106
  `git:tag_current_release` after `deploy:rebuild`
108
107
 
109
- ### caplets/memcached
108
+ ## caplets/memcached
110
109
 
111
110
  Support for keeping track of memcached nodes and writing a `memcached.yml`
112
111
  config file based on the `:memcached` role.
@@ -121,18 +120,30 @@ dynamically based on those servers' `:private_ip`s. Otherwise:
121
120
  ### Tasks
122
121
 
123
122
  `deploy:memcached:config` - Write a generated `memcached.yml` to your
124
- projet's config directory.
123
+ project's config directory.
125
124
 
126
125
  ### Hooks
127
126
 
128
127
  `deploy:memcached:config` after `deploy:setup`
129
128
 
130
- ### caplets/mongrel
129
+ ## caplets/mongrel
131
130
 
132
- ### caplets/networkfs
131
+ ## caplets/networkfs
133
132
 
134
133
  ## caplets/passenger
135
134
 
135
+ ## caplets/ssh
136
+
137
+ Tasks that present a list of your configured servers, and provide quick SSH
138
+ access to any of them. The server list can optionally be narrowed down by
139
+ role.
140
+
141
+ ### Tasks
142
+
143
+ `ssh` - Connects to any configured server. (Usage: `cap <environment> ssh`)
144
+ `ssh:app` - Connects to any configured app server.
145
+ `ssh:web` - Connects to any configured web server.
146
+
136
147
  ## caplets/thinking-sphinx
137
148
 
138
149
  ## caplets/unicorn
data/lib/caplets/basic.rb CHANGED
@@ -9,3 +9,4 @@ config.instance_eval do
9
9
  end
10
10
 
11
11
  config.load 'caplets/deploy'
12
+ config.load 'caplets/ssh'
@@ -10,7 +10,7 @@ namespace :deploy do
10
10
  task :install, :roles => lambda { fetch(:bundle_roles) },
11
11
  :except => {:no_release => true} do
12
12
  without = fetch(:bundle_exclude).map{|g| "--without #{g}"}.join(' ')
13
- run_current "bundle install #{fetch(:bundle_to)} #{without}"
13
+ run_current "bundle check || bundle install #{fetch(:bundle_to)} #{without}"
14
14
  end
15
15
  end
16
16
  end
@@ -56,16 +56,13 @@ namespace :deploy do
56
56
 
57
57
  desc "Setup a Git-based deploy"
58
58
  task :setup, :except => {:no_release => true} do
59
- run_multi(
60
- "if [ -d #{fetch(:current_path)}/.git ]",
61
- "then cd #{fetch(:current_path)}",
62
- "#{try_sudo} git fetch",
63
- "else #{try_sudo} git clone #{fetch(:repository)} #{fetch(:current_path)}",
64
- "fi",
65
- "mkdir -p " + fetch(:required_children,[]).
66
- map {|dir| "#{fetch(:current_path)}/#{dir}" }.
67
- join(' ')
68
- )
59
+ run "if [ -d #{fetch(:current_path)}/.git ] ; "+
60
+ "then cd #{fetch(:current_path)} && #{try_sudo} git fetch ; "+
61
+ "else #{try_sudo} git clone #{fetch(:repository)} #{fetch(:current_path)} ; "+
62
+ "fi && "+
63
+ "mkdir -p " + fetch(:required_children,[]).
64
+ map {|dir| "#{fetch(:current_path)}/#{dir}" }.
65
+ join(' ')
69
66
  end
70
67
 
71
68
  desc <<-DESC
@@ -95,15 +92,15 @@ namespace :deploy do
95
92
 
96
93
  # Just timestamps, please
97
94
  task :finalize_update, :except => { :no_release => true } do
98
- if fetch(:normalize_asset_timestamps, false)
99
- stamp = Time.now.utc.strftime("%Y%m%d%H%M.%S")
100
- asset_paths = %w(images stylesheets javascripts).map {|p|
101
- "#{latest_release}/public/#{p}"
102
- }.join(" ")
103
- run "find #{asset_paths} -exec touch -t #{stamp} {} ';'; true",
104
- :env => { "TZ" => "UTC" }
95
+ if fetch(:normalize_asset_timestamps, false)
96
+ stamp = Time.now.utc.strftime("%Y%m%d%H%M.%S")
97
+ asset_paths = %w(images stylesheets javascripts).map {|p|
98
+ "#{latest_release}/public/#{p}"
99
+ }.join(" ")
100
+ run "find #{asset_paths} -exec touch -t #{stamp} {} ';'; true",
101
+ :env => { "TZ" => "UTC" }
102
+ end
105
103
  end
106
- end
107
104
 
108
105
  %w[start stop restart reload].each do |taskname|
109
106
  desc "#{taskname.capitalize} the application server(s)"
@@ -20,19 +20,22 @@ namespace :deploy do
20
20
  desc "Start the mongrel_cluster"
21
21
  task :start, :roles => :app do
22
22
  run "cd #{current_path} && " +
23
- "mongrel_rails cluster::start -C #{shared_path}/config/cluster.yml --clean"
23
+ fetch(:bin_cmd,'') +
24
+ " mongrel_rails cluster::start -C #{shared_path}/config/cluster.yml --clean"
24
25
  end
25
26
 
26
27
  desc "Stop the mongrel_cluster"
27
28
  task :stop, :roles => :app do
28
29
  run "cd #{current_path} && " +
29
- "mongrel_rails cluster::stop -C #{shared_path}/config/cluster.yml --clean"
30
+ fetch(:bin_cmd,'') +
31
+ " mongrel_rails cluster::stop -C #{shared_path}/config/cluster.yml --clean"
30
32
  end
31
33
 
32
34
  desc "Restart the mongrel_cluster"
33
35
  task :restart, :roles => :app do
34
36
  run "cd #{current_path} && " +
35
- "mongrel_rails cluster::restart -C #{shared_path}/config/cluster.yml --clean"
37
+ fetch(:bin_cmd,'') +
38
+ " mongrel_rails cluster::restart -C #{shared_path}/config/cluster.yml --clean"
36
39
  end
37
40
 
38
41
  desc "Restart the mongrel_cluster, as mongrel does not support reloading"
@@ -6,14 +6,11 @@ namespace :deploy do
6
6
  task :start, :roles => :app, :except => {:no_release => true} do; end
7
7
  task :stop, :roles => :app, :except => {:no_release => true} do; end
8
8
 
9
- desc 'Restart the Passenger processes by touching tmp/restart.txt'
10
- task :restart, :roles => :app, :except => {:no_release => true} do
11
- run "touch #{current_path}/tmp/restart.txt"
12
- end
13
-
14
- desc 'Restart the Passenger process by touching tmp/restart.txt'
15
- task :restart, :roles => :app, :except => {:no_release => true} do
16
- run "touch #{current_path}/tmp/restart.txt"
9
+ [:restart, :reload].each do |action|
10
+ desc 'Restart the Passenger processes by touching tmp/restart.txt'
11
+ task action, :roles => :app, :except => {:no_release => true} do
12
+ run "touch #{current_path}/tmp/restart.txt"
13
+ end
17
14
  end
18
15
  end # namespace :passenger
19
16
  end # namespace :deploy
@@ -0,0 +1,54 @@
1
+ module Caplets::SSH
2
+ def ssh_to_server(opts={})
3
+ servers = []
4
+ selected_role = opts[:role] ? opts[:role].to_sym : nil
5
+ task_roles = selected_role ? {selected_role => roles[selected_role]} :
6
+ roles.sort_by(&:to_s)
7
+
8
+ # Convert from an array of roles (i.e., servers grouped by role) to an
9
+ # array of server data hashes (i.e., roles grouped by server)
10
+ task_roles.each do |role_name, role|
11
+ role.servers.each do |role_server|
12
+ role_server_data = servers.detect { |s| s[:host] == role_server.host }
13
+ if role_server_data
14
+ role_server_data[:role_names] << role_name
15
+ else
16
+ servers << {:host => role_server.host, :role_names => [role_name]}
17
+ end
18
+ end
19
+ end
20
+
21
+ # Prompt for a server if needed
22
+ if servers.size > 1
23
+ env_desc = "#{fetch(:environment)} #{selected_role}".strip
24
+ puts "\nWhich #{env_desc} server?"
25
+ servers.each_with_index do |server, i|
26
+ server_desc = server[:host].dup
27
+ unless selected_role
28
+ server_desc << " (#{server[:role_names].join(', ')})"
29
+ end
30
+ puts " #{(i+1).to_s.rjust(2)}. #{server_desc}"
31
+ end
32
+ input = Capistrano::CLI.ui.
33
+ ask('> ', Integer) { |q| q.in = 1..servers.size }
34
+ host = servers[input - 1][:host]
35
+ else
36
+ host = servers.first[:host]
37
+ end
38
+
39
+ cmd = %|ssh -t #{fetch(:user)}@#{host} "cd #{fetch(:current_path)}; bash"|
40
+ puts "Connecting to #{host}..."
41
+ exec(cmd)
42
+ end
43
+ end
44
+ Capistrano::Configuration.send :include, Caplets::SSH
45
+
46
+ namespace :ssh do
47
+ desc 'SSH into any configured server'
48
+ task(:default) { ssh_to_server } # Usage: `cap production ssh`, etc.
49
+
50
+ [:app, :web].each do |role|
51
+ desc "SSH into any configured #{role} server"
52
+ task(role.to_sym) { ssh_to_server(:role => role) }
53
+ end
54
+ end
@@ -4,7 +4,8 @@ namespace :deploy do
4
4
  namespace :unicorn do
5
5
 
6
6
  def start_cmd
7
- "#{fetch(:_unicorn_cmd,'unicorn')} -D" +
7
+ fetch(:bin_cmd,'') +
8
+ " #{fetch(:_unicorn_cmd,'unicorn')} -D" +
8
9
  " -c config/unicorn.rb" +
9
10
  " -E #{fetch(:environment)}"
10
11
  end
data/lib/caplets/utils.rb CHANGED
@@ -1,7 +1,12 @@
1
1
  # This is just a collection of handy methods to use while writing tasks
2
2
  module Caplets::Utils
3
3
  def rake(cmd)
4
- run_current "RAILS_ENV=#{fetch(:environment)} rake #{cmd}"
4
+ run_current [
5
+ "RAILS_ENV=#{fetch(:environment)}",
6
+ fetch(:bin_cmd,''),
7
+ fetch(:rake, 'rake'),
8
+ cmd
9
+ ].join(' ')
5
10
  end
6
11
 
7
12
  def run_current(*cmds)
@@ -2,7 +2,7 @@ module Caplets
2
2
  module Version
3
3
  MAJOR = 1
4
4
  MINOR = 0
5
- TINY = 0
5
+ TINY = 2
6
6
  BUILD = nil
7
7
  STRING = [MAJOR,MINOR,TINY,BUILD].compact.join('.')
8
8
  end
@@ -9,7 +9,7 @@ namespace :deploy do
9
9
  load_file = "config/whenever/#{fetch(:environment)}.#{role}.rb"
10
10
  [ "cd #{fetch(:current_path)} &&",
11
11
  "if [ -f #{load_file} ] ; then",
12
- "#{fetch(:bin_cmd)} whenever",
12
+ "#{fetch(:bin_cmd,'')} whenever",
13
13
  "--update-crontab #{fetch(:application)}.#{fetch(:environment)}.#{role}",
14
14
  "--load-file #{load_file}",
15
15
  "--set environment=#{fetch(:environment)}",
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: caplets
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 19
4
5
  prerelease: false
5
6
  segments:
6
7
  - 1
7
8
  - 0
8
- - 0
9
- version: 1.0.0
9
+ - 2
10
+ version: 1.0.2
10
11
  platform: ruby
11
12
  authors:
12
13
  - Dean Strelau
@@ -14,16 +15,18 @@ autorequire:
14
15
  bindir: bin
15
16
  cert_chain: []
16
17
 
17
- date: 2010-06-08 00:00:00 -04:00
18
+ date: 2010-10-27 00:00:00 -04:00
18
19
  default_executable:
19
20
  dependencies:
20
21
  - !ruby/object:Gem::Dependency
21
22
  name: capistrano
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 27
27
30
  segments:
28
31
  - 2
29
32
  - 5
@@ -51,6 +54,7 @@ files:
51
54
  - lib/caplets/mongrel.rb
52
55
  - lib/caplets/networkfs.rb
53
56
  - lib/caplets/passenger.rb
57
+ - lib/caplets/ssh.rb
54
58
  - lib/caplets/thinking-sphinx.rb
55
59
  - lib/caplets/unicorn.rb
56
60
  - lib/caplets/unicorn_rails.rb
@@ -74,23 +78,27 @@ rdoc_options: []
74
78
  require_paths:
75
79
  - lib
76
80
  required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
77
82
  requirements:
78
83
  - - ">="
79
84
  - !ruby/object:Gem::Version
85
+ hash: 3
80
86
  segments:
81
87
  - 0
82
88
  version: "0"
83
89
  required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
84
91
  requirements:
85
92
  - - ">="
86
93
  - !ruby/object:Gem::Version
94
+ hash: 3
87
95
  segments:
88
96
  - 0
89
97
  version: "0"
90
98
  requirements: []
91
99
 
92
100
  rubyforge_project:
93
- rubygems_version: 1.3.6
101
+ rubygems_version: 1.3.7
94
102
  signing_key:
95
103
  specification_version: 3
96
104
  summary: Capistrano super powers