mina 0.2.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +2 -0
- data/.travis.yml +3 -3
- data/CONTRIBUTING.md +124 -0
- data/Gemfile +1 -1
- data/HISTORY.md +33 -0
- data/README.md +5 -1
- data/data/deploy.rb +2 -2
- data/lib/mina.rb +1 -0
- data/lib/mina/exec_helpers.rb +104 -0
- data/lib/mina/foreman.rb +78 -0
- data/lib/mina/git.rb +2 -0
- data/lib/mina/helpers.rb +13 -1
- data/lib/mina/output_helpers.rb +25 -59
- data/lib/mina/rake.rb +1 -0
- data/lib/mina/rvm.rb +33 -1
- data/lib/mina/ssh_helpers.rb +70 -24
- data/lib/mina/version.rb +1 -1
- data/spec/commands/ssh_spec.rb +14 -0
- data/spec/commands/verbose_spec.rb +1 -0
- data/spec/dsl/invoke_spec.rb +33 -0
- data/spec/helpers/output_helper_spec.rb +38 -0
- data/spec/spec_helper.rb +1 -0
- data/test_env/config/deploy.rb +3 -3
- metadata +19 -21
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 48b10c2f04fe8cd4a81515ad180b07e988e30315
|
4
|
+
data.tar.gz: a6eb8c996ad4128d29096ce7f7307f007e0bc207
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 58ff29681d74382796c04253d9d29d7af8eb4c10b13788d6e66004975cd1c520a1b764de1f21b9cfd62e57e59a521f30e3c948c6b8eccfb8a8397e9560d1bb70
|
7
|
+
data.tar.gz: e446b721204e02b30683df7f6bc785098bd809d83b7a0bf48b9c725d77666acaebd03138b877447096e9b355b0726effb661fe61cda7974e7342eb397591ece9
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CONTRIBUTING.md
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
# Contributing to Mina
|
2
|
+
|
3
|
+
Want to get involved? Thanks! There are plenty of ways to help!
|
4
|
+
|
5
|
+
## Reporting issues
|
6
|
+
|
7
|
+
A bug is a _demonstrable problem_ that is caused by the code in the
|
8
|
+
repository.
|
9
|
+
|
10
|
+
Please read the following guidelines before you [report an issue][issues]:
|
11
|
+
|
12
|
+
1. **Use the GitHub issue search** — check if the issue has already been
|
13
|
+
reported. If it has been, please comment on the existing issue.
|
14
|
+
|
15
|
+
2. **Check if the issue has been fixed** — the latest `master` or
|
16
|
+
development branch may already contain a fix.
|
17
|
+
|
18
|
+
3. **Isolate the demonstrable problem** — make sure that the code in the
|
19
|
+
project's repository is _definitely_ responsible for the issue. Create a
|
20
|
+
[reduced test case](http://css-tricks.com/6263-reduced-test-cases/) - an
|
21
|
+
extremely simple and immediately viewable example of the issue.
|
22
|
+
|
23
|
+
Please try to be as detailed as possible in your report too. What is your
|
24
|
+
environment? What steps will reproduce the issue? What would you expect to be
|
25
|
+
the outcome? All these details will help people to assess and fix any potential
|
26
|
+
bugs.
|
27
|
+
|
28
|
+
### Example of a good bug report:
|
29
|
+
|
30
|
+
> Short and descriptive title
|
31
|
+
>
|
32
|
+
> A summary of the issue and the OS environment in which it occurs. If
|
33
|
+
> suitable, include the steps required to reproduce the bug.
|
34
|
+
>
|
35
|
+
> 1. This is the first step
|
36
|
+
> 2. This is the second step
|
37
|
+
> 3. Further steps, etc.
|
38
|
+
>
|
39
|
+
> `<url>` (a link to the reduced test case)
|
40
|
+
>
|
41
|
+
> Any other information you want to share that is relevant to the issue being
|
42
|
+
> reported. This might include the lines of code that you have identified as
|
43
|
+
> causing the bug, and potential solutions (and your opinions on their
|
44
|
+
> merits).
|
45
|
+
|
46
|
+
A good bug report shouldn't leave people needing to chase you up to get further
|
47
|
+
information that is required to assess or fix the bug.
|
48
|
+
|
49
|
+
**[File a bug report][issues]**
|
50
|
+
|
51
|
+
## Responding to issues
|
52
|
+
|
53
|
+
Feel free to respond to other people's issues! Some people may be reporting
|
54
|
+
issues that can easily be solved even without modification to the project's
|
55
|
+
code.
|
56
|
+
|
57
|
+
You can also help by verifying issues reported.
|
58
|
+
|
59
|
+
**[View issues][issues]**
|
60
|
+
|
61
|
+
## The 'help wanted' tag
|
62
|
+
|
63
|
+
Some [issues] are tagged with the 'help wanted' tag. These issues often:
|
64
|
+
|
65
|
+
- are missing an actual implementation, or
|
66
|
+
- need people's help in verifying and replicating the issue, or
|
67
|
+
- need test cases.
|
68
|
+
|
69
|
+
If you would like to contribute code and don't have any specific issue you want
|
70
|
+
to fix, this would be a good place to start looking at!
|
71
|
+
|
72
|
+
**[View issues][issues]**
|
73
|
+
|
74
|
+
## Pull requests
|
75
|
+
|
76
|
+
Good pull requests — patches, improvements, new features — are a fantastic
|
77
|
+
help. They should remain focused in scope and avoid containing unrelated
|
78
|
+
commits.
|
79
|
+
|
80
|
+
If your contribution involves a significant amount of work or substantial
|
81
|
+
changes to any part of the project, please open an issue to discuss it first.
|
82
|
+
|
83
|
+
Please follow this process; it's the best way to get your work included in the
|
84
|
+
project:
|
85
|
+
|
86
|
+
1. [Fork](http://help.github.com/fork-a-repo/) the project.
|
87
|
+
|
88
|
+
2. Clone your fork (`git clone
|
89
|
+
https://github.com/<your-username>/html5-boilerplate.git`).
|
90
|
+
|
91
|
+
3. Add an `upstream` remote (`git remote add upstream
|
92
|
+
https://github.com/nadarei/mina.git`).
|
93
|
+
|
94
|
+
4. Get the latest changes from upstream (e.g. `git pull upstream
|
95
|
+
<dev-branch>`).
|
96
|
+
|
97
|
+
5. Create a new topic branch to contain your feature, change, or fix (`git
|
98
|
+
checkout -b <topic-branch-name>`).
|
99
|
+
|
100
|
+
6. Make sure that your changes adhere to the current coding conventions used
|
101
|
+
throughout the project - indentation, accurate comments, etc. Please update
|
102
|
+
any documentation that is relevant to the change you are making.
|
103
|
+
|
104
|
+
7. Commit your changes in logical chunks; use git's [interactive
|
105
|
+
rebase](https://help.github.com/articles/interactive-rebase) feature to tidy
|
106
|
+
up your commits before making them public. Please adhere to these [git commit
|
107
|
+
message
|
108
|
+
guidelines](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html)
|
109
|
+
or your pull request is unlikely be merged into the main project.
|
110
|
+
|
111
|
+
8. Locally merge (or rebase) the upstream branch into your topic branch.
|
112
|
+
|
113
|
+
9. Push your topic branch up to your fork (`git push origin
|
114
|
+
<topic-branch-name>`).
|
115
|
+
|
116
|
+
10. [Open a Pull Request](http://help.github.com/send-pull-requests/) with a
|
117
|
+
clear title and description. Please mention which browsers you tested in.
|
118
|
+
|
119
|
+
## Acknowledgements
|
120
|
+
|
121
|
+
This contributing guide has been adapted from [HTML5 boilerplate's guide][g].
|
122
|
+
|
123
|
+
[g]: https://github.com/h5bp/html5-boilerplate/blob/master/CONTRIBUTING.md
|
124
|
+
[issues]: https://github.com/nadarei/mina/issues/
|
data/Gemfile
CHANGED
data/HISTORY.md
CHANGED
@@ -1,3 +1,36 @@
|
|
1
|
+
v0.3.0 - July 10, 2013
|
2
|
+
----------------------
|
3
|
+
|
4
|
+
* **Stdin is now being passed, thereby making git prompts work.**
|
5
|
+
* Foreman: Add foreman support. (#71) [Dan Sosedoff]
|
6
|
+
* Foreman: Fix 'command not found' error. (#89, #101)
|
7
|
+
* Foreman: Fix forman stop. [Andrew Rosa]
|
8
|
+
* Fix `mina setup` showing an error. (#64) [Anthony Hristov]
|
9
|
+
* Fix "broken pipe" error after deploying. (#64) [Tomas Varneckas]
|
10
|
+
* Fix error regarding "open4" in Windows environments. (#58)
|
11
|
+
* Fix the default script's "touch tmp/restart.txt" to work for reliably. (#77)
|
12
|
+
[Eugene Diachkin]
|
13
|
+
* Fix errors that happen when the host string is frozen. [sonots]
|
14
|
+
* RVM: use 'rvm use --create'. (#81) [Marcos Beirigo]
|
15
|
+
* RVM: Add 'rvm:wrapper' task to create wrappers. (#81) [Marcos Beirigo]
|
16
|
+
* New helper method called 'capture' to capture SSH output. (#113) [Naoki
|
17
|
+
Ainoya]
|
18
|
+
* Fix encoding errors. (#68) [Faud Saud]
|
19
|
+
|
20
|
+
Special thanks to all the contributors who made this release happen.
|
21
|
+
|
22
|
+
https://github.com/nadarei/mina/compare/v0.2.1...v0.3.0
|
23
|
+
|
24
|
+
[sonots]: https://github.com/sonots
|
25
|
+
[Tomas Varneckas]: https://github.com/tomasv
|
26
|
+
[Anthony Hristov]: https://github.com/muxcmux
|
27
|
+
[Dan Sosedoff]: https://github.com/sosedoff
|
28
|
+
[Eugene Diachkin]: https://github.com/ineu
|
29
|
+
[Marcos Beirigo]: https://github.com/marcosbeirigo
|
30
|
+
[Andrew Rosa]: https://github.com/andrewhr
|
31
|
+
[Naoki Ainoya]: https://github.com/saketoba
|
32
|
+
[Faud Saud]: https://github.com/faudsaud
|
33
|
+
|
1
34
|
v0.2.1 - Sep 08, 2012
|
2
35
|
---------------------
|
3
36
|
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Mina
|
1
|
+
# Mina
|
2
2
|
|
3
3
|
Really fast deployer and server automation tool.
|
4
4
|
|
@@ -13,6 +13,8 @@ session per deploy, minimizing the SSH connection overhead.
|
|
13
13
|
$ gem install mina
|
14
14
|
$ mina
|
15
15
|
|
16
|
+
[![Status](https://secure.travis-ci.org/nadarei/mina.png?branch=master)](http://travis-ci.org/nadarei/mina) [![Version](https://badge.fury.io/rb/mina.png)](http://badge.fury.io/rb/mina)
|
17
|
+
|
16
18
|
Documentation
|
17
19
|
-------------
|
18
20
|
|
@@ -39,6 +41,7 @@ To test out stuff in development:
|
|
39
41
|
# Run specs
|
40
42
|
$ rspec
|
41
43
|
$ rspec -t ssh # Run SSH tests (read test_env/config/deploy.rb first)
|
44
|
+
$ rake=10 rspec
|
42
45
|
$ rake=0.9 rspec
|
43
46
|
$ rake=0.8 rspec
|
44
47
|
|
@@ -108,3 +111,4 @@ Michael:
|
|
108
111
|
[nd]: http://nadarei.co
|
109
112
|
[issues]: https://github.com/nadarei/mina/issues
|
110
113
|
[trello]: https://trello.com/board/mina/4fc8b3023d9c9a4d72e573e6
|
114
|
+
|
data/data/deploy.rb
CHANGED
@@ -45,7 +45,7 @@ task :setup => :environment do
|
|
45
45
|
queue! %[chmod g+rx,u+rwx "#{deploy_to}/shared/config"]
|
46
46
|
|
47
47
|
queue! %[touch "#{deploy_to}/shared/config/database.yml"]
|
48
|
-
queue %[-----> Be sure to edit 'shared/config/database.yml'.]
|
48
|
+
queue %[echo "-----> Be sure to edit 'shared/config/database.yml'."]
|
49
49
|
end
|
50
50
|
|
51
51
|
desc "Deploys the current version to the server."
|
@@ -60,7 +60,7 @@ task :deploy => :environment do
|
|
60
60
|
invoke :'rails:assets_precompile'
|
61
61
|
|
62
62
|
to :launch do
|
63
|
-
queue
|
63
|
+
queue "touch #{deploy_to}/tmp/restart.txt"
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
data/lib/mina.rb
CHANGED
@@ -7,6 +7,7 @@ module Mina
|
|
7
7
|
autoload :DeployHelpers, 'mina/deploy_helpers'
|
8
8
|
autoload :OutputHelpers, 'mina/output_helpers'
|
9
9
|
autoload :SshHelpers, 'mina/ssh_helpers'
|
10
|
+
autoload :ExecHelpers, 'mina/exec_helpers'
|
10
11
|
autoload :Helpers, 'mina/helpers'
|
11
12
|
autoload :Settings, 'mina/settings'
|
12
13
|
autoload :Tools, 'mina/tools'
|
@@ -0,0 +1,104 @@
|
|
1
|
+
# # Helpers: Exec helpers
|
2
|
+
# Provides `pretty_system` which Mina uses to parse SSH output, and delegate to
|
3
|
+
# the appropriate Output helper.
|
4
|
+
|
5
|
+
module Mina
|
6
|
+
module ExecHelpers
|
7
|
+
|
8
|
+
# ### pretty_system
|
9
|
+
# __Internal:__ A pretty version of the default `#system` commands, but
|
10
|
+
# indents and puts color.
|
11
|
+
#
|
12
|
+
# Returns the exit code in integer form.
|
13
|
+
#
|
14
|
+
def pretty_system(code)
|
15
|
+
require 'shellwords'
|
16
|
+
cmds = Shellwords.shellsplit(code)
|
17
|
+
coathooks = 0
|
18
|
+
|
19
|
+
status =
|
20
|
+
Tools.popen4(*cmds) do |pid, i, o, e|
|
21
|
+
# Handle `^C`.
|
22
|
+
trap("INT") { Sys.handle_sigint(coathooks += 1, pid, self) }
|
23
|
+
|
24
|
+
# __In the background,__ make stdin passthru, and stream stderr.
|
25
|
+
pid_err = Sys.stream_stderr!(e) { |str| print_stderr str }
|
26
|
+
pid_in = Sys.stream_stdin! { |chr| i.putc chr }
|
27
|
+
|
28
|
+
# __In the foreground,__ stream stdout to the output helper.
|
29
|
+
Sys.stream_stdout(o) { |ch| print_char ch }
|
30
|
+
|
31
|
+
Process.waitpid pid_err
|
32
|
+
Process.kill 'TERM', pid_in
|
33
|
+
end
|
34
|
+
|
35
|
+
status.exitstatus
|
36
|
+
end
|
37
|
+
|
38
|
+
# ## Private methods
|
39
|
+
# Delegate functions, mostly.
|
40
|
+
|
41
|
+
module Sys
|
42
|
+
|
43
|
+
extend self
|
44
|
+
|
45
|
+
# ### Sys.handle_sigint!
|
46
|
+
# Called when a `^C` is pressed. The param `count` is how many times it's
|
47
|
+
# been pressed since. Returns nothing.
|
48
|
+
|
49
|
+
def handle_sigint(count, pid, this)
|
50
|
+
puts ""
|
51
|
+
if count > 1
|
52
|
+
this.print_status "Mina: SIGINT received again. Force quitting..."
|
53
|
+
Process.kill "KILL", pid
|
54
|
+
else
|
55
|
+
this.print_status "Mina: SIGINT received."
|
56
|
+
Process.kill "TERM", pid
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# ### Sys.stream_stderr!
|
61
|
+
# __Internal:__ Read from stderr stream `err` *[0]*, supress expected
|
62
|
+
# errors *[1]*, and yield. Returns the PID.
|
63
|
+
|
64
|
+
def stream_stderr!(err, &blk)
|
65
|
+
fork do
|
66
|
+
trap("INT") {}
|
67
|
+
|
68
|
+
while str = err.gets #[0]
|
69
|
+
next if str.include? "bash: no job control in this shell" #[1]
|
70
|
+
next if str.include? "stdin is not a terminal"
|
71
|
+
|
72
|
+
yield str.strip #[2]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
# ### Sys.stream_stdin!
|
78
|
+
# __Internal:__ Read from the real stdin stream and pass it onto the given
|
79
|
+
# stdin stream `i`. Returns the PID.
|
80
|
+
|
81
|
+
def stream_stdin!(&blk)
|
82
|
+
fork do
|
83
|
+
trap("INT") {}
|
84
|
+
|
85
|
+
while (char = STDIN.getbyte rescue nil)
|
86
|
+
yield char if char
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# ### Sys.stream_stdout
|
92
|
+
# __Internal:__ Read from given stdout stream `o` and delegate it to the
|
93
|
+
# output helper.
|
94
|
+
|
95
|
+
def stream_stdout(o, &blk)
|
96
|
+
while str = o.getc
|
97
|
+
yield str
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
end
|
data/lib/mina/foreman.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
# # Modules: Foreman
|
2
|
+
# Adds settings and tasks for managing projects with [foreman].
|
3
|
+
#
|
4
|
+
# NOTE: Requires sudo privileges
|
5
|
+
#
|
6
|
+
# [foreman]: http://rubygems.org/ddolar/foreman
|
7
|
+
#
|
8
|
+
# require 'mina/foreman'
|
9
|
+
#
|
10
|
+
# ## Common usage
|
11
|
+
#
|
12
|
+
# set :application, "app-name"
|
13
|
+
#
|
14
|
+
# task :deploy => :environment do
|
15
|
+
# deploy do
|
16
|
+
# # ...
|
17
|
+
# invoke 'foreman:export'
|
18
|
+
# # ...
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# to :launch do
|
22
|
+
# invoke 'foreman:restart'
|
23
|
+
# end
|
24
|
+
# end
|
25
|
+
#
|
26
|
+
|
27
|
+
# ## Settings
|
28
|
+
# Any and all of these settings can be overriden in your `deploy.rb`.
|
29
|
+
|
30
|
+
# ### foreman_app
|
31
|
+
# Sets the service name that foreman will export to upstart. Uses *application*
|
32
|
+
# variable as a default. It should be set, otherwise export command will fail.
|
33
|
+
|
34
|
+
# ### foreman_user
|
35
|
+
# Sets the user under which foreman will execute the service. Defaults to *user*
|
36
|
+
|
37
|
+
# ### foreman_log
|
38
|
+
# Sets the foreman log path. Defaults to *shared/log*
|
39
|
+
|
40
|
+
set_default :foreman_app, lambda { application }
|
41
|
+
set_default :foreman_user, lambda { user }
|
42
|
+
set_default :foreman_log, lambda { "#{deploy_to!}/#{shared_path}/log" }
|
43
|
+
|
44
|
+
namespace :foreman do
|
45
|
+
desc 'Export the Procfile to Ubuntu upstart scripts'
|
46
|
+
task :export do
|
47
|
+
export_cmd = "sudo bundle exec foreman export upstart /etc/init -a #{foreman_app} -u #{foreman_user} -l #{foreman_log}"
|
48
|
+
|
49
|
+
queue %{
|
50
|
+
echo "-----> Exporting foreman procfile for #{foreman_app}"
|
51
|
+
#{echo_cmd %[cd #{deploy_to!}/#{current_path!} ; #{export_cmd}]}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
desc "Start the application services"
|
56
|
+
task :start do
|
57
|
+
queue %{
|
58
|
+
echo "-----> Starting #{foreman_app} services"
|
59
|
+
#{echo_cmd %[sudo start #{foreman_app}]}
|
60
|
+
}
|
61
|
+
end
|
62
|
+
|
63
|
+
desc "Stop the application services"
|
64
|
+
task :stop do
|
65
|
+
queue %{
|
66
|
+
echo "-----> Stopping #{foreman_app} services"
|
67
|
+
#{echo_cmd %[sudo stop #{foreman_app}]}
|
68
|
+
}
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "Restart the application services"
|
72
|
+
task :restart do
|
73
|
+
queue %{
|
74
|
+
echo "-----> Restarting #{foreman_app} services"
|
75
|
+
#{echo_cmd %[sudo start #{foreman_app} || sudo restart #{foreman_app}]}
|
76
|
+
}
|
77
|
+
end
|
78
|
+
end
|
data/lib/mina/git.rb
CHANGED
data/lib/mina/helpers.rb
CHANGED
@@ -10,9 +10,14 @@ module Mina
|
|
10
10
|
#
|
11
11
|
# invoke :'git:clone'
|
12
12
|
# invoke :restart
|
13
|
+
#
|
14
|
+
# Options:
|
15
|
+
# reenable (bool) - Execute the task even next time.
|
16
|
+
#
|
13
17
|
|
14
|
-
def invoke(task)
|
18
|
+
def invoke(task, options = {})
|
15
19
|
Rake.application.invoke_task task
|
20
|
+
Rake::Task[task].reenable if options[:reenable]
|
16
21
|
end
|
17
22
|
|
18
23
|
# ### erb
|
@@ -151,6 +156,7 @@ module Mina
|
|
151
156
|
|
152
157
|
def echo_cmd(str)
|
153
158
|
if verbose_mode?
|
159
|
+
require 'shellwords'
|
154
160
|
"echo #{Shellwords.escape("$ " + str)} &&\n#{str}"
|
155
161
|
else
|
156
162
|
str
|
@@ -361,5 +367,11 @@ module Mina
|
|
361
367
|
indent n, unindent(code)
|
362
368
|
end
|
363
369
|
|
370
|
+
# ### capture
|
371
|
+
# Returns the output of command via SSH.
|
372
|
+
def capture(cmd, options={})
|
373
|
+
ssh cmd, options.merge(:return => true)
|
374
|
+
end
|
375
|
+
|
364
376
|
end
|
365
377
|
end
|
data/lib/mina/output_helpers.rb
CHANGED
@@ -19,18 +19,38 @@ module Mina
|
|
19
19
|
#
|
20
20
|
# Returns nothing.
|
21
21
|
#
|
22
|
-
def print_str(
|
23
|
-
if
|
22
|
+
def print_str(line)
|
23
|
+
if line =~ /^\-+> (.*?)$/
|
24
24
|
print_status $1
|
25
|
-
elsif
|
25
|
+
elsif line =~ /^! (.*?)$/
|
26
26
|
print_error $1
|
27
|
-
elsif
|
27
|
+
elsif line =~ /^\$ (.*?)$/
|
28
28
|
print_command $1
|
29
29
|
else
|
30
|
-
print_stdout
|
30
|
+
print_stdout line
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
+
# ### print_char
|
35
|
+
# Prints a single character.
|
36
|
+
def print_char(ch)
|
37
|
+
$last ||= ''
|
38
|
+
|
39
|
+
if ch == "\n"
|
40
|
+
print_clear
|
41
|
+
print_str $last
|
42
|
+
$last = ''
|
43
|
+
else
|
44
|
+
print ' ' if $last == ''
|
45
|
+
print ch
|
46
|
+
$last += ch
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def print_clear
|
51
|
+
print "\033[1K\r"
|
52
|
+
end
|
53
|
+
|
34
54
|
# ### print_status
|
35
55
|
# Prints a status message. (`----->`)
|
36
56
|
def print_status(msg)
|
@@ -68,59 +88,5 @@ module Mina
|
|
68
88
|
def color(str, c)
|
69
89
|
ENV['NO_COLOR'] ? str : "\033[#{c}m#{str}\033[0m"
|
70
90
|
end
|
71
|
-
|
72
|
-
# ### pretty_system
|
73
|
-
# __Internal:__ Works like `system`, but indents and puts color.
|
74
|
-
#
|
75
|
-
# Returns the exit code in integer form.
|
76
|
-
#
|
77
|
-
def pretty_system(code)
|
78
|
-
require 'shellwords'
|
79
|
-
cmds = Shellwords.shellsplit(code)
|
80
|
-
interrupted = false
|
81
|
-
|
82
|
-
status =
|
83
|
-
Tools.popen4(*cmds) do |pid, i, o, e|
|
84
|
-
trap "INT" do
|
85
|
-
puts ""
|
86
|
-
unless interrupted
|
87
|
-
print_status "Mina: SIGINT received."
|
88
|
-
Process.kill "TERM", pid
|
89
|
-
interrupted = true
|
90
|
-
else
|
91
|
-
print_status "Mina: SIGINT received again. Force quitting..."
|
92
|
-
Process.kill "KILL", pid
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# Read stderr in the background.
|
97
|
-
p1 = fork do
|
98
|
-
trap("INT") {}
|
99
|
-
while str = e.gets
|
100
|
-
# Supress expected errors.
|
101
|
-
next if str.include? "bash: no job control in this shell"
|
102
|
-
next if str.include? "stdin is not a terminal"
|
103
|
-
print_stderr str.strip
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
# Read stdin in the background and send it out.
|
108
|
-
p2 = fork do
|
109
|
-
trap("INT") {}
|
110
|
-
while (char = STDIN.getbyte rescue nil)
|
111
|
-
i.putc char if char
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
# Read stdout.
|
116
|
-
while str = o.gets
|
117
|
-
print_str str
|
118
|
-
end
|
119
|
-
|
120
|
-
Process.waitpid p1
|
121
|
-
end
|
122
|
-
|
123
|
-
status.exitstatus
|
124
|
-
end
|
125
91
|
end
|
126
92
|
end
|
data/lib/mina/rake.rb
CHANGED
data/lib/mina/rvm.rb
CHANGED
@@ -53,6 +53,38 @@ task :'rvm:use', :env do |t, args|
|
|
53
53
|
fi
|
54
54
|
|
55
55
|
source #{rvm_path}
|
56
|
-
#{echo_cmd %{rvm use "#{args[:env]}"}} || exit 1
|
56
|
+
#{echo_cmd %{rvm use "#{args[:env]}" --create}} || exit 1
|
57
57
|
}
|
58
58
|
end
|
59
|
+
|
60
|
+
|
61
|
+
# ### rvm:wrapper[]
|
62
|
+
# Creates a rvm wrapper for a given executable
|
63
|
+
#
|
64
|
+
# This is usually placed in the `:setup` task.
|
65
|
+
#
|
66
|
+
# task ::setup => :environment do
|
67
|
+
# ...
|
68
|
+
# invoke :'rvm:wrapper[ruby-1.9.3-p125@gemset_name,wrapper_name,binary_name]'
|
69
|
+
# end
|
70
|
+
#
|
71
|
+
task :'rvm:wrapper', :env, :name, :bin do |t,args|
|
72
|
+
unless args[:env] && args[:name] && args[:bin]
|
73
|
+
print_error "Task 'rvm:wrapper' needs an RVM environment name, an wrapper name and the binary name as arguments"
|
74
|
+
print_error "Example: invoke :'rvm:use[ruby-1.9.2@myapp,myapp,unicorn_rails]'"
|
75
|
+
die
|
76
|
+
end
|
77
|
+
|
78
|
+
queue %{
|
79
|
+
echo "-----> creating RVM wrapper '#{args[:name]}_#{args[:bin]}' using '#{args[:env]}'"
|
80
|
+
if [[ ! -s "#{rvm_path}" ]]; then
|
81
|
+
echo "! Ruby Version Manager not found"
|
82
|
+
echo "! If RVM is installed, check your :rvm_path setting."
|
83
|
+
exit 1
|
84
|
+
fi
|
85
|
+
|
86
|
+
source #{rvm_path}
|
87
|
+
#{echo_cmd %{rvm wrapper #{args[:env]} #{args[:name]} #{args[:bin]} }} || exit 1
|
88
|
+
}
|
89
|
+
|
90
|
+
end
|
data/lib/mina/ssh_helpers.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
# # Helpers: SSH helpers
|
2
2
|
# You don't need to invoke these helpers, they're already invoked automatically.
|
3
|
-
|
3
|
+
|
4
4
|
module Mina
|
5
5
|
module SshHelpers
|
6
|
+
|
6
7
|
# ### ssh
|
7
8
|
# Executes a command via SSH.
|
8
9
|
#
|
@@ -19,38 +20,21 @@ module Mina
|
|
19
20
|
# ssh("ls", return: true)
|
20
21
|
|
21
22
|
def ssh(cmd, options={})
|
22
|
-
cmd = cmd.join("\n") if cmd.is_a?(Array)
|
23
|
-
|
24
23
|
require 'shellwords'
|
25
24
|
|
26
|
-
|
25
|
+
cmd = cmd.join("\n") if cmd.is_a?(Array)
|
27
26
|
script = Shellwords.escape(cmd)
|
28
27
|
|
29
28
|
if options[:return] == true
|
30
|
-
|
29
|
+
`#{ssh_command} -- #{script}`
|
31
30
|
|
32
31
|
elsif simulate_mode?
|
33
|
-
|
34
|
-
puts "#!/usr/bin/env bash"
|
35
|
-
puts "# #{str}"
|
36
|
-
puts "#"
|
37
|
-
|
38
|
-
puts cmd
|
32
|
+
Ssh.simulate(cmd, ssh_command)
|
39
33
|
|
40
34
|
else
|
41
|
-
|
42
|
-
|
43
|
-
result = pretty_system(code)
|
44
|
-
elsif settings.term_mode.to_s == 'exec'
|
45
|
-
exec code
|
46
|
-
else
|
47
|
-
system code
|
48
|
-
result = $?.to_i
|
49
|
-
end
|
35
|
+
result = Ssh.invoke(script, self)
|
36
|
+
Ssh.ensure_successful result, self
|
50
37
|
end
|
51
|
-
|
52
|
-
die result if result.is_a?(Fixnum) && result > 0
|
53
|
-
result
|
54
38
|
end
|
55
39
|
|
56
40
|
# ### ssh_command
|
@@ -63,7 +47,7 @@ module Mina
|
|
63
47
|
# #=> 'ssh diggity@foo.com'
|
64
48
|
|
65
49
|
def ssh_command
|
66
|
-
args = domain
|
50
|
+
args = domain!.dup
|
67
51
|
args = "#{user}@#{args}" if user?
|
68
52
|
args << " -i #{identity_file}" if identity_file?
|
69
53
|
args << " -p #{port}" if port?
|
@@ -72,5 +56,67 @@ module Mina
|
|
72
56
|
args << " -t"
|
73
57
|
"ssh #{args}"
|
74
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
|
+
|
75
121
|
end
|
76
122
|
end
|
data/lib/mina/version.rb
CHANGED
@@ -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,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,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
CHANGED
data/test_env/config/deploy.rb
CHANGED
@@ -30,7 +30,7 @@ task :environment do
|
|
30
30
|
end
|
31
31
|
|
32
32
|
desc "Deploys."
|
33
|
-
task :deploy do
|
33
|
+
task :deploy => :environment do
|
34
34
|
queue "bundle() { true; }" # Stub the bundle command.
|
35
35
|
|
36
36
|
deploy do
|
@@ -61,7 +61,7 @@ namespace :passenger do
|
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
64
|
-
task :
|
64
|
+
task :get_password do
|
65
65
|
set :term_mode, :pretty
|
66
|
-
queue %[echo "Password:"; read x; echo out: $x;]
|
66
|
+
queue %[echo "-> Getting password"; echo -n "Password: "; read x; echo ""; echo out: $x;]
|
67
67
|
end
|
metadata
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mina
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.3.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Rico Sta. Cruz
|
@@ -10,54 +9,48 @@ authors:
|
|
10
9
|
autorequire:
|
11
10
|
bindir: bin
|
12
11
|
cert_chain: []
|
13
|
-
date:
|
12
|
+
date: 2013-07-10 00:00:00.000000000 Z
|
14
13
|
dependencies:
|
15
14
|
- !ruby/object:Gem::Dependency
|
16
15
|
name: rake
|
17
16
|
requirement: !ruby/object:Gem::Requirement
|
18
|
-
none: false
|
19
17
|
requirements:
|
20
|
-
- -
|
18
|
+
- - '>='
|
21
19
|
- !ruby/object:Gem::Version
|
22
20
|
version: '0'
|
23
21
|
type: :runtime
|
24
22
|
prerelease: false
|
25
23
|
version_requirements: !ruby/object:Gem::Requirement
|
26
|
-
none: false
|
27
24
|
requirements:
|
28
|
-
- -
|
25
|
+
- - '>='
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: '0'
|
31
28
|
- !ruby/object:Gem::Dependency
|
32
29
|
name: open4
|
33
30
|
requirement: !ruby/object:Gem::Requirement
|
34
|
-
none: false
|
35
31
|
requirements:
|
36
|
-
- -
|
32
|
+
- - '>='
|
37
33
|
- !ruby/object:Gem::Version
|
38
34
|
version: '0'
|
39
35
|
type: :runtime
|
40
36
|
prerelease: false
|
41
37
|
version_requirements: !ruby/object:Gem::Requirement
|
42
|
-
none: false
|
43
38
|
requirements:
|
44
|
-
- -
|
39
|
+
- - '>='
|
45
40
|
- !ruby/object:Gem::Version
|
46
41
|
version: '0'
|
47
42
|
- !ruby/object:Gem::Dependency
|
48
43
|
name: rspec
|
49
44
|
requirement: !ruby/object:Gem::Requirement
|
50
|
-
none: false
|
51
45
|
requirements:
|
52
|
-
- -
|
46
|
+
- - '>='
|
53
47
|
- !ruby/object:Gem::Version
|
54
48
|
version: '0'
|
55
49
|
type: :development
|
56
50
|
prerelease: false
|
57
51
|
version_requirements: !ruby/object:Gem::Requirement
|
58
|
-
none: false
|
59
52
|
requirements:
|
60
|
-
- -
|
53
|
+
- - '>='
|
61
54
|
- !ruby/object:Gem::Version
|
62
55
|
version: '0'
|
63
56
|
description: Really fast deployer and server automation tool.
|
@@ -72,6 +65,7 @@ files:
|
|
72
65
|
- .gitignore
|
73
66
|
- .rspec
|
74
67
|
- .travis.yml
|
68
|
+
- CONTRIBUTING.md
|
75
69
|
- Gemfile
|
76
70
|
- HISTORY.md
|
77
71
|
- LICENSE
|
@@ -85,6 +79,8 @@ files:
|
|
85
79
|
- lib/mina/default.rb
|
86
80
|
- lib/mina/deploy.rb
|
87
81
|
- lib/mina/deploy_helpers.rb
|
82
|
+
- lib/mina/exec_helpers.rb
|
83
|
+
- lib/mina/foreman.rb
|
88
84
|
- lib/mina/git.rb
|
89
85
|
- lib/mina/helpers.rb
|
90
86
|
- lib/mina/output_helpers.rb
|
@@ -106,38 +102,40 @@ files:
|
|
106
102
|
- spec/commands/deploy_spec.rb
|
107
103
|
- spec/commands/outside_project_spec.rb
|
108
104
|
- spec/commands/real_deploy_spec.rb
|
105
|
+
- spec/commands/ssh_spec.rb
|
109
106
|
- spec/commands/verbose_spec.rb
|
107
|
+
- spec/dsl/invoke_spec.rb
|
110
108
|
- spec/dsl/queue_spec.rb
|
111
109
|
- spec/dsl/settings_in_rake_spec.rb
|
112
110
|
- spec/dsl/settings_spec.rb
|
113
111
|
- spec/dsl/to_spec.rb
|
114
112
|
- spec/fixtures/custom_file_env/custom_deploy.rb
|
115
113
|
- spec/fixtures/empty_env/config/deploy.rb
|
114
|
+
- spec/helpers/output_helper_spec.rb
|
116
115
|
- spec/spec_helper.rb
|
117
116
|
- test_env/config/deploy.rb
|
118
117
|
homepage: http://github.com/nadarei/mina
|
119
118
|
licenses: []
|
119
|
+
metadata: {}
|
120
120
|
post_install_message:
|
121
121
|
rdoc_options: []
|
122
122
|
require_paths:
|
123
123
|
- lib
|
124
124
|
required_ruby_version: !ruby/object:Gem::Requirement
|
125
|
-
none: false
|
126
125
|
requirements:
|
127
|
-
- -
|
126
|
+
- - '>='
|
128
127
|
- !ruby/object:Gem::Version
|
129
128
|
version: '0'
|
130
129
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
131
|
-
none: false
|
132
130
|
requirements:
|
133
|
-
- -
|
131
|
+
- - '>='
|
134
132
|
- !ruby/object:Gem::Version
|
135
133
|
version: '0'
|
136
134
|
requirements: []
|
137
135
|
rubyforge_project:
|
138
|
-
rubygems_version:
|
136
|
+
rubygems_version: 2.0.2
|
139
137
|
signing_key:
|
140
|
-
specification_version:
|
138
|
+
specification_version: 4
|
141
139
|
summary: Really fast deployer and server automation tool.
|
142
140
|
test_files: []
|
143
141
|
has_rdoc:
|