mina 0.2.0.pre2 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -3,3 +3,4 @@ test_env/deploy
3
3
  .rvmrc
4
4
  Gemfile.lock
5
5
  pkg/
6
+ docs
data/HISTORY.md CHANGED
@@ -1,5 +1,5 @@
1
- v0.2.0 - Unreleased
2
- -------------------
1
+ v0.2.0
2
+ ------
3
3
 
4
4
  This release had two pre releases:
5
5
 
@@ -7,6 +7,12 @@ This release had two pre releases:
7
7
  * v0.1.3.pre1 (Jul 13, 2012)
8
8
 
9
9
  ### Fixed:
10
+ * Allow changing `:term_mode` in the setup task. (#51, @alfuken)
11
+ * Prevent `git log` from using a pager. (#42, @tmak)
12
+ * `deploy:cleanup` can now be called in a deploy script. (#50, @dariocravero)
13
+ * Don't invoke bash anymore (!), assume that bash is the shell for the user.
14
+ Fixes Ubuntu 12, and many other things.
15
+ * Fixed `ssh(cmd, return: true)` that used to exit. (#53 from @jpascal)
10
16
  * [pre2] Call ssh with no double use `-t` parameter.
11
17
  * [pre2] Fix Ruby 1.8 compatibility.
12
18
  * [pre2] Fix the "undefined method > for Process::Status" error.
@@ -16,6 +22,13 @@ This release had two pre releases:
16
22
  * [pre1] Doing `rails:assets_precompile` now properly skips asset compilation if not needed. (#25)
17
23
 
18
24
  ### Added:
25
+ * __Added the 'queue!' helper.__
26
+ * Add support for __Whenever__. (#47, @jpascal)
27
+ * Add a new `:environment` task that gets loaded on setup/deploy.
28
+ * __Add explicit support for rbenv/rvm.__ (#5, #39)
29
+ * Implement :'rvm:use[...]'. (#5, #39)
30
+ * Implement :'rbenv:load'. (#5, #39)
31
+ * Revert `rails:optimize_for_3.2` from the pre2 release. (#32)
19
32
  * [pre2] __Optimize git:clone by caching the repository.__ This way, updates are
20
33
  faster because not the entire repo is cloned everytime. (#10)
21
34
  * [pre2] __Show elapsed time that a deploy takes.__
@@ -24,7 +37,7 @@ This release had two pre releases:
24
37
  * [pre2] New `die` helper.
25
38
  * [pre2] New `report_time` helper.
26
39
  * [pre2] New `to_directory` helper. (#35)
27
- * [pre2] Put optional optimizations for Rails 3.2 asset pipeline. (#32)
40
+ * [pre2] Put optional optimizations for Rails 3.2 asset pipeline. (#32) -- reverted
28
41
  * Update sample deploy script:
29
42
  - [pre2] Update default deploy.rb to note :branch.
30
43
  - [pre2] Add `link_shared_paths` to the sample deploy script.
@@ -33,6 +46,15 @@ This release had two pre releases:
33
46
  * [pre1] Make asset paths configurable using the `asset_paths` setting.
34
47
 
35
48
  ### Changed:
49
+ * Force removal of shared path destinations before linking with
50
+ `deploy:link_shared_paths`. Fixes symlinking of `log/` in Rails projects.
51
+ * __Rails: speed up default asset compilation a bit by invoking
52
+ `assets:precompile` with `RAILS_GROUPS=assets`.__
53
+ * Add helpful error message when there is a problem with
54
+ deploy.rb or a custom Rakefile. (#37, @sge-jesse-adams)
55
+ * Update the default deploy.rb to add notes about 'mina setup' customizations.
56
+ * Make `mina run`, `mina rake`, `mina console` use the new `:environment` task.
57
+ * Allow calling `die` without arguments.
36
58
  * [pre2] __Improve output of `mina init`.__
37
59
  * [pre2] Prettier output for `mina setup`. Also, show a better error message for it.
38
60
  * [pre1] Refactor pretty printing to be simpler, cleaner, and extensible.
data/Rakefile CHANGED
@@ -1,9 +1,20 @@
1
1
  require 'bundler'
2
2
  require 'bundler/gem_tasks'
3
3
 
4
+ github = ENV['github'] || 'nadarei/mina'
5
+
4
6
  task :spec do
5
7
  system "rm Gemfile.lock; sh -c 'rake=0.8 bundle exec rspec'"
6
8
  system "rm Gemfile.lock; sh -c 'rake=0.9 bundle exec rspec'"
7
9
  end
8
10
 
11
+ task :docs do
12
+ files = ['manual/index.md', 'manual/modules.md', 'HISTORY.md'] + Dir['lib/**/*.rb']
13
+ system "lidoc #{files.join ' '} -o docs --github #{github}"
14
+ end
15
+
16
+ task :'docs:deploy' => :docs do
17
+ system "git-update-ghpages #{github} -i docs -p docs"
18
+ end
19
+
9
20
  task :default => :spec
data/bin/mina CHANGED
@@ -42,7 +42,12 @@ Rake.application.instance_eval do
42
42
  require 'mina/rake'
43
43
 
44
44
  # Allow running without a Rakefile
45
- load_rakefile if have_rakefile || custom_rakefile
45
+ begin
46
+ load_rakefile if have_rakefile || custom_rakefile
47
+ rescue Exception
48
+ puts "Error loading Rakefile!"
49
+ raise "There may be a problem with config/deploy.rb and/or Rakefile"
50
+ end
46
51
 
47
52
  # Run tasks
48
53
  top_level
@@ -1,13 +1,8 @@
1
- # For help in making your deploy script, see the Mina documentation:
2
- #
3
- # - http://nadarei.co/mina
4
- # - http://nadarei.co/mina/tasks
5
- # - http://nadarei.co/mina/settings
6
- # - http://nadarei.co/mina/helpers
7
-
8
1
  require 'mina/bundler'
9
2
  require 'mina/rails'
10
3
  require 'mina/git'
4
+ # require 'mina/rbenv' # for rbenv support. (http://rbenv.org)
5
+ # require 'mina/rvm' # for rvm support. (http://rvm.io)
11
6
 
12
7
  # Basic settings:
13
8
  # domain - The hostname to SSH to.
@@ -22,19 +17,40 @@ set :branch, 'master'
22
17
 
23
18
  # Manually create these paths in shared/ (eg: shared/config/database.yml) in your server.
24
19
  # They will be linked in the 'deploy:link_shared_paths' step.
25
- set :shared_paths, ['config/database.yml']
20
+ set :shared_paths, ['config/database.yml', 'log']
26
21
 
27
22
  # Optional settings:
28
23
  # set :user, 'foobar' # Username in the server to SSH to.
29
24
  # set :port, '30000' # SSH port number.
30
25
 
26
+ # This task is the environment that is loaded for most commands, such as
27
+ # `mina deploy` or `mina rake`.
28
+ task :environment do
29
+ # If you're using rbenv, use this to load the rbenv environment.
30
+ # Be sure to commit your .rbenv-version to your repository.
31
+ # invoke :'rbenv:load'
32
+
33
+ # For those using RVM, use this to load an RVM version@gemset.
34
+ # invoke :'rvm:use[ruby-1.9.3-p125@default]'
35
+ end
36
+
37
+ # Put any custom mkdir's in here for when `mina setup` is ran.
38
+ # For Rails apps, we'll make some of the shared paths that are shared between
39
+ # all releases.
40
+ task :setup => :environment do
41
+ queue! %[mkdir -p "#{deploy_to}/shared/log"]
42
+ queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/log"]
43
+
44
+ queue! %[mkdir -p "#{deploy_to}/shared/config"]
45
+ queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"]
46
+
47
+ queue! %[touch "#{deploy_to}/shared/config/database.yml"]
48
+ queue %[-----> Be sure to edit 'shared/config/database.yml'.]
49
+ end
50
+
31
51
  desc "Deploys the current version to the server."
32
- task :deploy do
52
+ task :deploy => :environment do
33
53
  deploy do
34
- # This makes asset compilation faster in Rails 3.2 -- remove this for other
35
- # Rails versions.
36
- invoke :'rails:optimize_for_3.2'
37
-
38
54
  # Put things that will set up an empty directory into a fully set-up
39
55
  # instance of your project.
40
56
  invoke :'git:clone'
@@ -48,3 +64,11 @@ task :deploy do
48
64
  end
49
65
  end
50
66
  end
67
+
68
+ # For help in making your deploy script, see the Mina documentation:
69
+ #
70
+ # - http://nadarei.co/mina
71
+ # - http://nadarei.co/mina/tasks
72
+ # - http://nadarei.co/mina/settings
73
+ # - http://nadarei.co/mina/helpers
74
+
@@ -1,9 +1,36 @@
1
+ # # Modules: Bundler
2
+ # Adds settings and tasks for managing Ruby Bundler.
3
+ #
4
+ # require 'mina/bundler'
1
5
 
2
- settings.bundle_bin ||= 'bundle'
3
- settings.bundle_path ||= './vendor/bundle'
4
- settings.bundle_options ||= lambda { %{--without development:test --path "#{bundle_path}" --binstubs bin/ --deployment} }
6
+ # ## Settings
7
+ # Any and all of these settings can be overriden in your `deploy.rb`.
8
+
9
+ # ### bundle_bin
10
+ # Sets the bundle path.
11
+
12
+ set_default :bundle_bin, 'bundle'
13
+
14
+ # ### bundle_path
15
+ # Sets the path to where the gems are expected to be.
16
+ #
17
+ # This path will be symlinked to `./shared/bundle` so that the gems cache will
18
+ # be shared between all releases.
19
+
20
+ set_default :bundle_path, './vendor/bundle'
21
+
22
+ # ### bundle_options
23
+ # Sets the options for installing gems via Bundler.
24
+
25
+ set_default :bundle_options, lambda { %{--without development:test --path "#{bundle_path}" --binstubs bin/ --deployment} }
26
+
27
+ # ## Deploy tasks
28
+ # These tasks are meant to be invoked inside deploy scripts, not invoked on
29
+ # their own.
5
30
 
6
31
  namespace :bundle do
32
+ # ### bundle:install
33
+ # Installs gems.
7
34
  desc "Install gem dependencies using Bundler."
8
35
  task :install do
9
36
  queue %{
@@ -1,8 +1,25 @@
1
+ # # Modules: Default
2
+ # This module is loaded when invoking `mina` with or without a project.
3
+
1
4
  set_default :bash_options, '-i'
2
5
 
3
- # Default tasks here
6
+ # ## Tasks
7
+ # Any and all of these settings can be overriden in your `deploy.rb`.
8
+
9
+ # ### environment
10
+ # Make the `:environment` task exist by default. This is meant to be overridden
11
+ # by users.
12
+
13
+ task :environment do
14
+ end
15
+
16
+ # ### init
17
+ # Initializes a new Mina project.
18
+ #
19
+ # $ mina init
20
+
4
21
  desc "Creates a sample config file."
5
- task :init do
22
+ task :init => :environment do
6
23
  name = Rake.application.name
7
24
  config_file = Rake.application.rakefile
8
25
 
@@ -63,6 +80,9 @@ end
63
80
 
64
81
  extend HelpHelpers
65
82
 
83
+ # ### help
84
+ # Shows the help screen.
85
+
66
86
  desc "Show help."
67
87
  task :help do
68
88
  name = Rake.application.name
@@ -93,6 +113,11 @@ task :help do
93
113
  puts "for more information."
94
114
  end
95
115
 
116
+ # ### tasks
117
+ # Display all tasks in a nice table.
118
+ #
119
+ # $ mina tasks
120
+
96
121
  desc "Show all tasks."
97
122
  task :tasks do
98
123
  show_task_help :full => true
@@ -1,3 +1,9 @@
1
+ # # Modules: Deployment
2
+ # This module is automatically loaded for all Mina projects.
3
+
4
+ # ## Settings
5
+ # Any and all of these settings can be overriden in your `deploy.rb`.
6
+
1
7
  set_default :releases_path, "releases"
2
8
  set_default :shared_path, "shared"
3
9
  set_default :current_path, "current"
@@ -5,12 +11,26 @@ set_default :lock_file, "deploy.lock"
5
11
  set_default :keep_releases, 5
6
12
 
7
13
  namespace :deploy do
14
+ # ## Tasks
15
+
16
+ # ### deploy:force_unlock
17
+ # Forces a deploy unlock by deleting the lock file.
18
+ #
19
+ # $ mina deploy:force_unlock
20
+ #
21
+ # You can also combine that task with `deploy`:
22
+ #
23
+ # $ mina deploy:force_unlock deploy
24
+
8
25
  desc "Forces a deploy unlock."
9
26
  task :force_unlock do
10
27
  queue %{echo "-----> Unlocking"}
11
28
  queue echo_cmd %{rm -f "#{deploy_to}/#{lock_file}"}
12
29
  end
13
30
 
31
+ # ### deploy:link_shared_paths
32
+ # Links the shared paths in the `shared_paths` setting.
33
+
14
34
  desc "Links paths set in :shared_paths."
15
35
  task :link_shared_paths do
16
36
  dirs = settings.shared_paths!.map { |file| File.dirname("./#{file}") }.uniq
@@ -20,31 +40,43 @@ namespace :deploy do
20
40
  end
21
41
 
22
42
  cmds += shared_paths.map do |file|
23
- echo_cmd %{ln -s "#{deploy_to}/#{shared_path}/#{file}" "./#{file}"}
43
+ [
44
+ echo_cmd(%{rm -rf "./#{file}"}),
45
+ echo_cmd(%{ln -s "#{deploy_to}/#{shared_path}/#{file}" "./#{file}"})
46
+ ]
24
47
  end
25
48
 
26
49
  queue %{
27
50
  echo "-----> Symlinking shared paths"
28
- #{cmds.join(" &&\n")}
51
+ #{cmds.flatten.join(" &&\n")}
29
52
  }
30
53
  end
31
54
 
32
- desc "Clean up old releases. By default, the last 5 releases are kept on
33
- each server (though you can change this with the keep_releases setting).
34
- All other deployed revisions are removed from the servers."
55
+ # ### deploy:cleanup
56
+ # Cleans up old releases.
57
+ #
58
+ # By default, the last 5 releases are kept on each server (though you can
59
+ # change this with the keep_releases setting). All other deployed revisions
60
+ # are removed from the servers."
61
+
62
+ desc "Clean up old releases."
35
63
  task :cleanup do
36
- queue %{echo "-----> Cleaning up old releases (keeping #{keep_releases!})"}
37
- queue echo_cmd %{cd "#{deploy_to!}" || exit 15}
38
- queue echo_cmd %{cd "#{releases_path!}" || exit 16}
39
- queue echo_cmd %{count=`ls -1d [0-9]* | sort -rn | wc -l`}
40
- queue echo_cmd %{remove=$((count > 5 ? count - #{keep_releases} : 0))}
41
- queue echo_cmd %{ls -1d [0-9]* | sort -rn | tail -n $remove | xargs rm -rf {}}
64
+ queue %{
65
+ echo "-----> Cleaning up old releases (keeping #{keep_releases!})"
66
+ #{echo_cmd %{cd "#{deploy_to!}/#{releases_path!}" || exit 15}}
67
+ #{echo_cmd %{count=`ls -1d [0-9]* | sort -rn | wc -l`}}
68
+ #{echo_cmd %{remove=$((count > 5 ? count - #{keep_releases} : 0))}}
69
+ #{echo_cmd %{ls -1d [0-9]* | sort -rn | tail -n $remove | xargs rm -rf {}}}
70
+ }
42
71
  end
43
72
  end
44
73
 
74
+ # ### setup
75
+ # Sets up a site's directory structure.
76
+
45
77
  desc "Sets up a site."
46
78
  task :setup do
47
- set :term_mode, :pretty
79
+ set_default :term_mode, :pretty
48
80
 
49
81
  settings.deploy_to!
50
82
 
@@ -73,8 +105,13 @@ task :setup do
73
105
  }
74
106
  end
75
107
 
108
+ # ### run[]
109
+ # Runs a command on a server.
110
+ #
111
+ # $ mina run[tail -f logs.txt]
112
+
76
113
  desc "Runs a command in the server."
77
- task :run, :command do |t, args|
114
+ task :run, [:command] => [:environment] do |t, args|
78
115
  command = args[:command]
79
116
  unless command
80
117
  puts %[You need to provide a command. Try: mina "run[ls -la]"]
@@ -1,7 +1,9 @@
1
+ # # Helpers: Deploy helpers
2
+ # Helpers for deployment.
1
3
  module Mina
2
- # Helpers for deployment
3
4
  module DeployHelpers
4
- # Wraps the things inside it in a deploy script and queues it.
5
+ # ### deploy
6
+ # Wraps the things inside it in a deploy script and queues it.
5
7
  # This generates a script using deploy_script and queues it.
6
8
  #
7
9
  # Returns nothing.
@@ -10,6 +12,7 @@ module Mina
10
12
  queue deploy_script(&blk)
11
13
  end
12
14
 
15
+ # ### deploy_script
13
16
  # Wraps the things inside it in a deploy script.
14
17
  #
15
18
  # script = deploy_script do
@@ -1,6 +1,23 @@
1
- settings.branch ||= "master"
1
+ # # Modules: Git
2
+ # Adds settings and tasks related to managing Git.
3
+ #
4
+ # require 'mina/git'
5
+
6
+ # ## Settings
7
+ # Any and all of these settings can be overriden in your `deploy.rb`.
8
+
9
+ # ### branch
10
+ # Sets the branch to be deployed.
11
+
12
+ set_default :branch, "master"
2
13
 
3
14
  namespace :git do
15
+ # ## Deploy tasks
16
+ # These tasks are meant to be invoked inside deploy scripts, not invoked on
17
+ # their own.
18
+
19
+ # ### git:clone
20
+ # Clones the Git repository. Meant to be used inside a deploy script.
4
21
  desc "Clones the Git repository to the release path."
5
22
  task :clone do
6
23
  if revision?
@@ -32,7 +49,7 @@ namespace :git do
32
49
  status = %[
33
50
  echo "-----> Using this git commit" &&
34
51
  echo &&
35
- #{echo_cmd %[git log --format="%aN (%h):%n> %s" -n 1]} &&
52
+ #{echo_cmd %[git --no-pager log --format="%aN (%h):%n> %s" -n 1]} &&
36
53
  #{echo_cmd %[rm -rf .git]} &&
37
54
  echo
38
55
  ]
@@ -1,7 +1,8 @@
1
+ # # Helpers: Default helpers
1
2
  module Mina
2
- # Helpers
3
3
  module Helpers
4
4
 
5
+ # ### invoke
5
6
  # Invokes another Rake task.
6
7
  #
7
8
  # Invokes the task given in `task`. Returns nothing.
@@ -13,6 +14,7 @@ module Mina
13
14
  Rake.application.invoke_task task
14
15
  end
15
16
 
17
+ # ### erb
16
18
  # Evaluates an ERB block in the current scope and returns a string.
17
19
  #
18
20
  # a = 1
@@ -31,6 +33,7 @@ module Mina
31
33
  erb.result b
32
34
  end
33
35
 
36
+ # ### run!
34
37
  # SSHs into the host and runs the code that has been queued.
35
38
  #
36
39
  # This is already automatically invoked before Rake exits to run all
@@ -45,6 +48,7 @@ module Mina
45
48
  report_time { ssh commands(:default) }
46
49
  end
47
50
 
51
+ # ### report_time
48
52
  # Report time elapsed in the block.
49
53
  # Returns the output of the block.
50
54
  def report_time(&blk)
@@ -53,6 +57,7 @@ module Mina
53
57
  output
54
58
  end
55
59
 
60
+ # ### measure
56
61
  # Measures the time (in ms) a block takes.
57
62
  # Returns a [time, output] tuple.
58
63
  def measure(&blk)
@@ -61,14 +66,19 @@ module Mina
61
66
  [(Time.now - t).to_i, output]
62
67
  end
63
68
 
69
+ # ## SSH helpers
70
+ # You don't need to invoke these helpers, they're already invoked automatically.
71
+
72
+ # ### ssh
64
73
  # Executes a command via SSH.
65
74
  #
66
75
  # Returns nothing usually, but if `{ return: true }` is given, returns the
67
76
  # STDOUT output of the SSH session.
68
77
  #
69
- # options - Hash of options.
70
- # :pretty - Prettify the output.
71
- # :return - If set to true, returns the output.
78
+ # `options` is a hash of options:
79
+ #
80
+ # - `:pretty` - Prettify the output if true.
81
+ # - `:return` - If set to true, returns the output.
72
82
  #
73
83
  # Example
74
84
  #
@@ -80,10 +90,10 @@ module Mina
80
90
  require 'shellwords'
81
91
 
82
92
  result = 0
83
- script = Shellwords.escape("true;"+cmd)
93
+ script = Shellwords.escape(cmd)
84
94
 
85
95
  if options[:return] == true
86
- result = `#{ssh_command} -- bash -c #{script}`
96
+ result = `#{ssh_command} -- #{script}`
87
97
 
88
98
  elsif simulate_mode?
89
99
  str = "Executing the following via '#{ssh_command}':"
@@ -94,7 +104,7 @@ module Mina
94
104
  puts cmd
95
105
 
96
106
  else
97
- code = "#{ssh_command} -- bash #{bash_options} -c #{script}"
107
+ code = "#{ssh_command} -- #{script}"
98
108
  if settings.term_mode == :pretty
99
109
  result = pretty_system(code)
100
110
  elsif settings.term_mode == :exec
@@ -105,24 +115,11 @@ module Mina
105
115
  end
106
116
  end
107
117
 
108
- die result if result > 0
118
+ die result if result.is_a? Fixnum && result > 0
109
119
  result
110
120
  end
111
121
 
112
- # Exits with a nice looking message.
113
- # Returns nothing.
114
- #
115
- # die 2
116
- # die 2, "Tests failed"
117
- #
118
- def die(code, msg=null)
119
- str = "Failed with status #{code}"
120
- str += " (#{msg})" if msg
121
- err = Failed.new(str)
122
- err.exitstatus = code
123
- raise err
124
- end
125
-
122
+ # ### ssh_command
126
123
  # Returns the SSH command to be executed.
127
124
  #
128
125
  # set :domain, 'foo.com'
@@ -140,6 +137,42 @@ module Mina
140
137
  "ssh #{args}"
141
138
  end
142
139
 
140
+ # ### mina_cleanup
141
+ # __Internal:__ Invoked when Rake exits.
142
+ #
143
+ # Returns nothing.
144
+ #
145
+ def mina_cleanup!
146
+ run! if commands.any?
147
+ end
148
+
149
+ # ## Errors
150
+
151
+ # ### die
152
+ # Exits with a nice looking message.
153
+ # Returns nothing.
154
+ #
155
+ # die 2
156
+ # die 2, "Tests failed"
157
+ #
158
+ def die(code=1, msg=null)
159
+ str = "Failed with status #{code}"
160
+ str += " (#{msg})" if msg
161
+ err = Failed.new(str)
162
+ err.exitstatus = code
163
+ raise err
164
+ end
165
+
166
+ # ### error
167
+ # __Internal:__ Prints to stdout.
168
+ # Consider using `print_error` instead.
169
+ def error(str)
170
+ $stderr.write "#{str}\n"
171
+ end
172
+
173
+ # ## Queueing
174
+
175
+ # ### queue
143
176
  # Queues code to be ran.
144
177
  #
145
178
  # This queues code to be ran to the current code bucket (defaults to `:default`).
@@ -157,30 +190,35 @@ module Mina
157
190
  commands(@to) << unindent(code)
158
191
  end
159
192
 
160
- # Internal: Normalizes indentation on a given string.
193
+ # ### queue!
194
+ # Shortcut for `queue`ing a command that shows up in verbose mode.
195
+
196
+ def queue!(code)
197
+ queue echo_cmd(code)
198
+ end
199
+
200
+ # ### echo_cmd
201
+ # Converts a bash command to a command that echoes before execution.
202
+ # Used to show commands in verbose mode. This does nothing unless verbose mode is on.
161
203
  #
162
- # Returns the normalized string without extraneous indentation.
204
+ # Returns a string of the compound bash command, typically in the format of
205
+ # `echo xx && xx`. However, if `verbose_mode?` is false, it returns the
206
+ # input string unharmed.
163
207
  #
164
- # puts unindent %{
165
- # Hello
166
- # There
167
- # }
168
- # # Output:
169
- # # Hello
170
- # # There
208
+ # echo_cmd("ln -nfs releases/2 current")
209
+ # #=> echo "$ ln -nfs releases/2 current" && ln -nfs releases/2 current
171
210
  #
172
- def unindent(code)
173
- if code =~ /^\n([ \t]+)/
174
- code = code.gsub(/^#{$1}/, '')
211
+ def echo_cmd(str)
212
+ if verbose_mode?
213
+ "echo #{Shellwords.escape("$ " + str)} &&\n#{str}"
214
+ else
215
+ str
175
216
  end
176
-
177
- code.strip
178
217
  end
179
218
 
180
- def reindent(n, code)
181
- indent n, unindent(code)
182
- end
219
+ # ## Commands
183
220
 
221
+ # ### commands
184
222
  # Returns an array of queued code strings.
185
223
  #
186
224
  # You may give an optional `aspect`.
@@ -204,20 +242,21 @@ module Mina
204
242
  end)[aspect]
205
243
  end
206
244
 
207
- # Starts a new block where new #commands are collected.
245
+ # ### isolate
246
+ # Starts a new block where new `commands` are collected.
208
247
  #
209
248
  # Returns nothing.
210
249
  #
211
- # queue "sudo restart"
212
- # queue "true"
213
- # commands.should == ['sudo restart', 'true']
250
+ # queue "sudo restart"
251
+ # queue "true"
252
+ # commands.should == ['sudo restart', 'true']
214
253
  #
215
- # isolate do
216
- # queue "reload"
217
- # commands.should == ['reload']
218
- # end
254
+ # isolate do
255
+ # queue "reload"
256
+ # commands.should == ['reload']
257
+ # end
219
258
  #
220
- # commands.should == ['sudo restart', 'true']
259
+ # commands.should == ['sudo restart', 'true']
221
260
  #
222
261
  def isolate(&blk)
223
262
  old, @commands = @commands, nil
@@ -226,6 +265,7 @@ module Mina
226
265
  result
227
266
  end
228
267
 
268
+ # ### in_directory
229
269
  # Starts a new block where #commands are collected, to be executed inside `path`.
230
270
  #
231
271
  # Returns nothing.
@@ -263,6 +303,9 @@ module Mina
263
303
  @to = old
264
304
  end
265
305
 
306
+ # ## Settings helpers
307
+
308
+ # ### set
266
309
  # Sets settings.
267
310
  # Sets given symbol `key` to value in `value`.
268
311
  #
@@ -274,6 +317,7 @@ module Mina
274
317
  settings.send :"#{key}=", value
275
318
  end
276
319
 
320
+ # ### set_default
277
321
  # Sets default settings.
278
322
  # Sets given symbol `key` to value in `value` only if the key isn't set yet.
279
323
  #
@@ -291,9 +335,11 @@ module Mina
291
335
  settings.send :"#{key}=", value unless settings.send(:"#{key}?")
292
336
  end
293
337
 
338
+ # ### settings
294
339
  # Accesses the settings hash.
295
340
  #
296
341
  # set :domain, 'kickflip.me'
342
+ #
297
343
  # settings.domain #=> 'kickflip.me'
298
344
  # domain #=> 'kickflip.me'
299
345
  #
@@ -301,6 +347,7 @@ module Mina
301
347
  @settings ||= Settings.new
302
348
  end
303
349
 
350
+ # ### method_missing
304
351
  # Hook to get settings.
305
352
  # See #settings for an explanation.
306
353
  #
@@ -310,40 +357,9 @@ module Mina
310
357
  settings.send meth, *args
311
358
  end
312
359
 
313
- def indent(count, str)
314
- str.gsub(/^/, " "*count)
315
- end
316
-
317
- def error(str)
318
- $stderr.write "#{str}\n"
319
- end
320
-
321
- # Converts a bash command to a command that echoes before execution.
322
- # Used to show commands in verbose mode. This does nothing unless verbose mode is on.
323
- #
324
- # Returns a string of the compound bash command, typically in the format of
325
- # `echo xx && xx`. However, if `verbose_mode?` is false, it returns the
326
- # input string unharmed.
327
- #
328
- # echo_cmd("ln -nfs releases/2 current")
329
- # #=> echo "$ ln -nfs releases/2 current" && ln -nfs releases/2 current
330
- #
331
- def echo_cmd(str)
332
- if verbose_mode?
333
- "echo #{("$ " + str).inspect} &&\n#{str}"
334
- else
335
- str
336
- end
337
- end
338
-
339
- # Internal: Invoked when Rake exits.
340
- #
341
- # Returns nothing.
342
- #
343
- def mina_cleanup!
344
- run! if commands.any?
345
- end
360
+ # ## Command line mode helpers
346
361
 
362
+ # ### verbose_mode?
347
363
  # Checks if Rake was invoked with --verbose.
348
364
  #
349
365
  # Returns true or false.
@@ -358,6 +374,7 @@ module Mina
358
374
  end
359
375
  end
360
376
 
377
+ # ### simulate_mode?
361
378
  # Checks if Rake was invoked with --simulate.
362
379
  #
363
380
  # Returns true or false.
@@ -365,5 +382,41 @@ module Mina
365
382
  def simulate_mode?
366
383
  !! ENV['simulate']
367
384
  end
385
+
386
+ # ## Internal helpers
387
+
388
+ # ### indent
389
+ # Indents a given code block with `count` spaces before it.
390
+ def indent(count, str)
391
+ str.gsub(/^/, " "*count)
392
+ end
393
+
394
+ # ### unindent
395
+ # __Internal:__ Normalizes indentation on a given string.
396
+ #
397
+ # Returns the normalized string without extraneous indentation.
398
+ #
399
+ # puts unindent %{
400
+ # Hello
401
+ # There
402
+ # }
403
+ # # Output:
404
+ # # Hello
405
+ # # There
406
+ #
407
+ def unindent(code)
408
+ if code =~ /^\n([ \t]+)/
409
+ code = code.gsub(/^#{$1}/, '')
410
+ end
411
+
412
+ code.strip
413
+ end
414
+
415
+ # ### reindent
416
+ # Resets the indentation on a given code block.
417
+ def reindent(n, code)
418
+ indent n, unindent(code)
419
+ end
420
+
368
421
  end
369
422
  end
@@ -1,35 +1,49 @@
1
+ # # Helpers: Output helpers
2
+ # Protip! make a module that overrides these settings, then use `extend YourModule`
3
+ # to make your own pretty printing thing.
1
4
  module Mina
2
5
  module OutputHelpers
3
- # Protip! make a module that overrides these settings, then use `extend YourModule`
4
- # to make your own pretty printing thing.
6
+
7
+ # ### print_status
8
+ # Prints a status message. (`----->`)
5
9
  def print_status(msg)
6
10
  puts "" if verbose_mode?
7
11
  puts "#{color('----->', 32)} #{msg}"
8
12
  end
9
13
 
14
+ # ### print_error
15
+ # Prints an error message (header).
10
16
  def print_error(msg)
11
17
  puts " #{color("!", 33)} #{color(msg, 31)}"
12
18
  end
13
19
 
20
+ # ### print_stderr
21
+ # Prints an error message (body), or prints stderr output.
14
22
  def print_stderr(msg)
15
23
  puts " #{color(msg, 31)}"
16
24
  end
17
25
 
26
+ # ### print_command
27
+ # Prints a command.
18
28
  def print_command(msg)
19
29
  puts " #{color("$", 32)} #{color(msg, 32)}"
20
30
  end
21
31
 
32
+ # ### print_stdout
33
+ # Prints a normal message.
22
34
  def print_stdout(msg)
23
35
  puts " #{msg}"
24
36
  end
25
37
 
26
- # Internal: Colorizes a string.
38
+ # ### color
39
+ # Colorizes a string.
27
40
  # Returns the string `str` with the color `c`.
28
41
  def color(str, c)
29
42
  ENV['NO_COLOR'] ? str : "\033[#{c}m#{str}\033[0m"
30
43
  end
31
44
 
32
- # Internal: Prints a string by delegating it to the proper output helper.
45
+ # ### print_str
46
+ # Prints a string by delegating it to the proper output helper.
33
47
  #
34
48
  # It takes an input with text and prints them nicely. The text block can
35
49
  # have statuses (prefixed with `-----> `), errors (prefixed with `! `),
@@ -55,7 +69,8 @@ module Mina
55
69
  end
56
70
  end
57
71
 
58
- # Internal: Works like `system`, but indents and puts color.
72
+ # ### pretty_system
73
+ # __Internal:__ Works like `system`, but indents and puts color.
59
74
  #
60
75
  # Returns the exit code in integer form.
61
76
  #
@@ -1,33 +1,65 @@
1
+ # # Modules: Rails
2
+ # Adds settings and tasks for managing Rails projects.
3
+ #
4
+ # require 'mina/rails'
5
+
1
6
  require 'mina/bundler'
2
7
 
3
- settings.rails_env ||= 'production'
8
+ # ## Settings
9
+ # Any and all of these settings can be overriden in your `deploy.rb`.
10
+
11
+ # ### rails_env
12
+ # Sets the Rails environment for `rake` and `rails` commands.
13
+ #
14
+ # Note that changing this will NOT change the environment that your application
15
+ # is ran in.
16
+ set_default :rails_env, 'production'
17
+
18
+ # ### bundle_prefix
19
+ # Prefix for Bundler commands.
4
20
  # TODO: This should be lambda
5
- settings.bundle_prefix ||= lambda { %{RAILS_ENV="#{rails_env}" #{bundle_bin} exec} }
6
- settings.rake ||= lambda { %{#{bundle_prefix} rake} }
7
- settings.rails ||= lambda { %{#{bundle_prefix} rails} }
8
- settings.asset_paths ||= ['vendor/assets/', 'app/assets/']
9
- settings.rake_assets_precompile ||= lambda { "#{rake} assets:precompile" }
10
-
11
- desc "Makes Rails 3.2 deploys faster."
12
- task :'rails:optimize_for_3.2' do
13
- # This is 100% faster in Rails 3.2 because it skips re-invoking the
14
- # Rake+Rails environment twice, and reuses the compilation cache for
15
- # generating digest and non-digest assets. See:
16
- # https://github.com/rails/rails/blob/3-2-stable/actionpack/lib/sprockets/assets.rake
17
- settings.rake_assets_precompile = lambda {
18
- "#{rake} assets:precompile:primary assets:precompile:nondigest RAILS_ENV=production RAILS_GROUPS=assets"
19
- }
20
-
21
- # A safer, but slower (and still faster than default) version would be the
22
- # one below. This will respect your config.assets.digest setting.
23
- # settings.rake_assets_precompile = lambda {
24
- # "#{rake} assets:precompile:all RAILS_ENV=production RAILS_GROUPS=assets"
25
- # }
26
- end
21
+
22
+ set_default :bundle_prefix, lambda { %{RAILS_ENV="#{rails_env}" #{bundle_bin} exec} }
23
+
24
+ # ### rake
25
+ # The prefix for `rake` commands. Use like so:
26
+ #
27
+ # queue "#{rake} db:migrate"
28
+
29
+ set_default :rake, lambda { %{#{bundle_prefix} rake} }
30
+
31
+ # ### rails
32
+ # The prefix for `rails` commands. Use like so:
33
+ #
34
+ # queue "#{rails} console"
35
+
36
+ set_default :rails, lambda { %{#{bundle_prefix} rails} }
37
+
38
+ # ### asset_paths
39
+ # The paths to be checked.
40
+ #
41
+ # Whenever assets are compiled, the asset files are checked if they have
42
+ # changed from the previous release.
43
+ #
44
+ # If they're unchanged, compiled assets will simply be copied over to the new
45
+ # release.
46
+ #
47
+ # Override this if you have custom asset paths declared in your Rails's
48
+ # `config.assets.paths` setting.
49
+
50
+ set_default :asset_paths, ['vendor/assets/', 'app/assets/']
51
+
52
+ # ### rake_assets_precompile
53
+ # The command to invoke when precompiling assets.
54
+ # Override me if you like.
55
+
56
+ settings.rake_assets_precompile ||= lambda { "#{rake} assets:precompile RAILS_GROUPS=assets" }
57
+
58
+ # ----
27
59
 
28
60
  # Macro used later by :rails, :rake, etc
29
61
  make_run_task = lambda { |name, sample_args|
30
- task name, :arguments do |t, args|
62
+ task name, [:arguments] => :environment do |t, args|
31
63
  arguments = args[:arguments]
32
64
  command = send name
33
65
  unless command
@@ -61,18 +93,41 @@ def check_for_changes_script(options={})
61
93
  ]
62
94
  end
63
95
 
96
+ # ## Command-line tasks
97
+ # These tasks can be invoked in the command line.
98
+
99
+ # ### rails[]
100
+ # Invokes a rails command.
101
+ #
102
+ # $ mina rails[console]
103
+
64
104
  desc "Execute a Rails command in the current deploy."
65
105
  make_run_task[:rails, 'console']
66
106
 
107
+ # ### rake[]
108
+ # Invokes a rake command.
109
+ #
110
+ # $ mina rake db:cleanup
111
+
67
112
  desc "Execute a Rake command in the current deploy."
68
113
  make_run_task[:rake, 'db:migrate']
69
114
 
115
+ # ### console
116
+ # Opens the Ruby console for the currently-deployed version.
117
+ #
118
+ # $ mina console
119
+
70
120
  desc "Starts an interactive console."
71
121
  task :console do
72
- queue echo_cmd %[cd "#{deploy_to!}/#{current_path!}" && #{rails} console]
122
+ queue echo_cmd %[cd "#{deploy_to!}/#{current_path!}" && #{rails} console && exit]
73
123
  end
74
124
 
125
+ # ## Deploy tasks
126
+ # These tasks are meant to be invoked inside deploy scripts, not invoked on
127
+ # their own.
128
+
75
129
  namespace :rails do
130
+ # ### rails:db_migrate
76
131
  desc "Migrates the Rails database (skips if nothing has changed since the last release)."
77
132
  task :db_migrate do
78
133
  if ENV['force_migrate']
@@ -99,6 +154,7 @@ namespace :rails do
99
154
  end
100
155
  end
101
156
 
157
+ # ### rails:db_migrate:force
102
158
  desc "Migrates the Rails database."
103
159
  task :'db_migrate:force' do
104
160
  queue %{
@@ -107,6 +163,7 @@ namespace :rails do
107
163
  }
108
164
  end
109
165
 
166
+ # ### rails:assets_precompile:force
110
167
  desc "Precompiles assets."
111
168
  task :'assets_precompile:force' do
112
169
  queue %{
@@ -115,6 +172,7 @@ namespace :rails do
115
172
  }
116
173
  end
117
174
 
175
+ # ### rails:assets_precompile
118
176
  desc "Precompiles assets (skips if nothing has changed since the last release)."
119
177
  task :'assets_precompile' do
120
178
  if ENV['force_assets']
@@ -0,0 +1,46 @@
1
+ # # Modules: rbenv
2
+ # Adds settings and tasks for managing [rbenv] installations.
3
+ #
4
+ # [rbenv]: https://github.com/sstephenson/rbenv
5
+ #
6
+ # require 'mina/rbenv'
7
+ #
8
+ # ## Common usage
9
+ #
10
+ # task :environment do
11
+ # invoke :'rbenv:load'
12
+ # end
13
+ #
14
+ # task :deploy => :environment do
15
+ # ...
16
+ # end
17
+
18
+ # ## Settings
19
+ # Any and all of these settings can be overriden in your `deploy.rb`.
20
+
21
+ # ### rbenv_path
22
+ # Sets the path where *rbenv* is installed.
23
+ #
24
+ # You may override this if rbenv is placed elsewhere in your setup.
25
+
26
+ set_default :rbenv_path, "$HOME/.rbenv"
27
+
28
+ # ## Tasks
29
+
30
+ # ### rbenv:load
31
+ # Loads the *rbenv* runtime.
32
+
33
+ task :'rbenv:load' do
34
+ queue %{
35
+ echo "-----> Loading rbenv"
36
+ #{echo_cmd %{export PATH="#{rbenv_path}/bin:$PATH"}}
37
+
38
+ if ! which -s rbenv >/dev/null; then
39
+ echo "! rbenv not found"
40
+ echo "! If rbenv is installed, check your :rbenv_path setting."
41
+ exit 1
42
+ fi
43
+
44
+ #{echo_cmd %{eval "$(rbenv init -)"}}
45
+ }
46
+ end
@@ -0,0 +1,58 @@
1
+ # # Modules: RVM
2
+ # Adds settings and tasks for managing [RVM] installations.
3
+ #
4
+ # [rvm]: http://rvm.io
5
+ #
6
+ # require 'mina/rvm'
7
+ #
8
+ # ## Common usage
9
+ #
10
+ # task :environment do
11
+ # invoke :'rvm:use[ruby-1.9.3-p125@gemset_name]'
12
+ # end
13
+ #
14
+ # task :deploy => :environment do
15
+ # ...
16
+ # end
17
+
18
+ # ## Settings
19
+ # Any and all of these settings can be overriden in your `deploy.rb`.
20
+
21
+ # ### rvm_path
22
+ # Sets the path to RVM.
23
+ #
24
+ # You can override this in your projects if RVM is installed in a different
25
+ # path, say, if you have a system-wide RVM install.
26
+
27
+ set_default :rvm_path, "$HOME/.rvm/scripts/rvm"
28
+
29
+ # ## Tasks
30
+
31
+ # ### rvm:use[]
32
+ # Uses a given RVM environment provided as an argument.
33
+ #
34
+ # This is usually placed in the `:environment` task.
35
+ #
36
+ # task :environment do
37
+ # invoke :'rvm:use[ruby-1.9.3-p125@gemset_name]'
38
+ # end
39
+ #
40
+ task :'rvm:use', :env do |t, args|
41
+ unless args[:env]
42
+ print_error "Task 'rvm:use' needs an RVM environment name as an argument."
43
+ print_error "Example: invoke :'rvm:use[ruby-1.9.2@default]'"
44
+ die
45
+ end
46
+
47
+ queue %{
48
+ echo "-----> Using RVM environment '#{args[:env]}'"
49
+ if [[ ! -s "#{rvm_path}" ]]; then
50
+ echo "! Ruby Version Manager not found"
51
+ echo "! If RVM is installed, check your :rvm_path setting."
52
+ exit 1
53
+ fi
54
+
55
+ source #{rvm_path}
56
+ #{echo_cmd %{rvm use "#{args[:env]}"}} || exit 1
57
+ }
58
+ end
@@ -1,5 +1,5 @@
1
1
  module Mina
2
2
  def self.version
3
- "0.2.0.pre2"
3
+ "0.2.0"
4
4
  end
5
5
  end
@@ -0,0 +1,28 @@
1
+ # # Modules: Whenever
2
+ # Adds settings and tasks for managing projects with [whenever}.
3
+ #
4
+ # [whenever]: http://rubygems.org/gems/whenever
5
+
6
+ namespace :whenever do
7
+ desc "Clear crontab"
8
+ task :clear do
9
+ queue %{
10
+ echo "-----> Clear crontab for #{domain}"
11
+ #{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; bundle exec whenever --clear-crontab #{domain} --set 'environment=production&path=#{deploy_to!}/#{current_path!}']}
12
+ }
13
+ end
14
+ desc "Update crontab"
15
+ task :update do
16
+ queue %{
17
+ echo "-----> Update crontab for #{domain}"
18
+ #{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; bundle exec whenever --update-crontab #{domain} --set 'environment=production&path=#{deploy_to!}/#{current_path!}']}
19
+ }
20
+ end
21
+ desc "Write crontab"
22
+ task :write do
23
+ queue %{
24
+ echo "-----> Update crontab for #{domain}"
25
+ #{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; bundle exec whenever --write-crontab #{domain} --set 'environment=production&path=#{deploy_to!}/#{current_path!}']}
26
+ }
27
+ end
28
+ end
@@ -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
+
@@ -0,0 +1,2 @@
1
+ Modules
2
+ =======
@@ -9,12 +9,12 @@ describe "Invoking the 'mina' command in a project" do
9
9
  it 'should echo commands in verbose mode' do
10
10
  mina 'deploy', '--verbose', '--simulate'
11
11
 
12
- stdout.should include %[echo "$ git]
12
+ stdout.should include %[echo #{Shellwords.escape('$ git')}]
13
13
  end
14
14
 
15
15
  it 'should not echo commands when not in verbose mode' do
16
16
  mina 'deploy', '--simulate'
17
17
 
18
- stdout.should_not include %[echo "$ git]
18
+ stdout.should_not include %[echo #{Shellwords.escape('$ git')}]
19
19
  end
20
20
  end
@@ -11,6 +11,8 @@
11
11
  # In fact, let's make that folder right now.
12
12
  require 'fileutils'
13
13
  FileUtils.mkdir_p "#{Dir.pwd}/deploy"
14
+ FileUtils.mkdir_p "#{Dir.pwd}/deploy/config"
15
+ File.open("#{Dir.pwd}/deploy/config/database.yml", 'w') { |f| f.write "Hello" }
14
16
 
15
17
  # -- Stubs end, deploy script begins! --------------
16
18
 
@@ -21,6 +23,11 @@ require 'mina/git'
21
23
  set :domain, 'localhost'
22
24
  set :deploy_to, "#{Dir.pwd}/deploy"
23
25
  set :repository, "#{Mina.root_path}"
26
+ set :shared_paths, ['config/database.yml']
27
+
28
+ task :environment do
29
+ queue %[echo "-----> Loading env"]
30
+ end
24
31
 
25
32
  desc "Deploys."
26
33
  task :deploy do
@@ -29,6 +36,7 @@ task :deploy do
29
36
  deploy do
30
37
  queue %[ruby -e "\\$stderr.write \\\"This is stdout output\n\\\""]
31
38
  invoke :'git:clone'
39
+ invoke :'deploy:link_shared_paths'
32
40
  invoke :'bundle:install'
33
41
  invoke :'rails:db_migrate'
34
42
 
metadata CHANGED
@@ -1,8 +1,8 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mina
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0.pre2
5
- prerelease: 6
4
+ version: 0.2.0
5
+ prerelease:
6
6
  platform: ruby
7
7
  authors:
8
8
  - Rico Sta. Cruz
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-08-02 00:00:00.000000000 Z
13
+ date: 2012-09-08 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: rake
@@ -90,9 +90,14 @@ files:
90
90
  - lib/mina/output_helpers.rb
91
91
  - lib/mina/rails.rb
92
92
  - lib/mina/rake.rb
93
+ - lib/mina/rbenv.rb
94
+ - lib/mina/rvm.rb
93
95
  - lib/mina/settings.rb
94
96
  - lib/mina/tools.rb
95
97
  - lib/mina/version.rb
98
+ - lib/mina/whenever.rb
99
+ - manual/index.md
100
+ - manual/modules.md
96
101
  - mina.gemspec
97
102
  - spec/command_helper.rb
98
103
  - spec/commands/command_spec.rb
@@ -124,9 +129,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
124
129
  required_rubygems_version: !ruby/object:Gem::Requirement
125
130
  none: false
126
131
  requirements:
127
- - - ! '>'
132
+ - - ! '>='
128
133
  - !ruby/object:Gem::Version
129
- version: 1.3.1
134
+ version: '0'
130
135
  requirements: []
131
136
  rubyforge_project:
132
137
  rubygems_version: 1.8.23