mina 0.2.1 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
[](http://travis-ci.org/nadarei/mina) [](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:
|