recap 0.2.0 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -1
- data/README.md +55 -10
- data/Rakefile +19 -5
- data/bin/recap +2 -2
- data/features/managing-processes.feature +1 -1
- data/features/setting-environment-variables.feature +26 -1
- data/features/steps/capistrano_steps.rb +10 -6
- data/features/support/project.rb +24 -5
- data/features/templates/project/Capfile.erb +1 -1
- data/lib/recap/recipes/rails.rb +6 -0
- data/lib/recap/recipes/ruby.rb +11 -0
- data/lib/recap/recipes/static.rb +3 -0
- data/lib/recap/recipes.rb +18 -0
- data/lib/recap/support/capistrano_extensions.rb +85 -0
- data/lib/recap/support/cli.rb +57 -0
- data/lib/recap/{compatibility.rb → support/compatibility.rb} +2 -2
- data/lib/recap/support/environment.rb +61 -0
- data/lib/recap/support/namespace.rb +47 -0
- data/lib/recap/support/shell_command.rb +35 -0
- data/lib/recap/support/templates/Capfile.erb +6 -0
- data/lib/recap/tasks/bootstrap.rb +77 -0
- data/lib/recap/{bundler.rb → tasks/bundler.rb} +15 -6
- data/lib/recap/{deploy.rb → tasks/deploy.rb} +30 -17
- data/lib/recap/tasks/env.rb +111 -0
- data/lib/recap/{foreman.rb → tasks/foreman.rb} +20 -12
- data/lib/recap/{preflight.rb → tasks/preflight.rb} +13 -11
- data/lib/recap/tasks/rails.rb +42 -0
- data/lib/recap/tasks.rb +16 -0
- data/lib/recap/version.rb +1 -1
- data/lib/recap.rb +119 -10
- data/recap.gemspec +3 -2
- data/spec/models/capistrano_extensions_spec.rb +41 -0
- data/spec/models/cli_spec.rb +25 -0
- data/spec/models/environment_spec.rb +14 -14
- data/spec/models/shell_command_spec.rb +55 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/tasks/bootstrap_spec.rb +9 -13
- data/spec/tasks/bundler_spec.rb +39 -7
- data/spec/tasks/deploy_spec.rb +42 -26
- data/spec/tasks/env_spec.rb +81 -5
- data/spec/tasks/foreman_spec.rb +10 -5
- data/spec/tasks/rails_spec.rb +80 -0
- metadata +65 -57
- data/doc/index.html +0 -235
- data/doc/lib/recap/bootstrap.html +0 -42
- data/doc/lib/recap/bundler.html +0 -168
- data/doc/lib/recap/capistrano_extensions.html +0 -208
- data/doc/lib/recap/cli.html +0 -42
- data/doc/lib/recap/compatibility.html +0 -73
- data/doc/lib/recap/deploy.html +0 -328
- data/doc/lib/recap/env.html +0 -108
- data/doc/lib/recap/foreman.html +0 -42
- data/doc/lib/recap/namespace.html +0 -42
- data/doc/lib/recap/preflight.html +0 -163
- data/doc/lib/recap/rails.html +0 -42
- data/doc/lib/recap/version.html +0 -42
- data/doc/lib/recap.html +0 -42
- data/index.rb +0 -62
- data/lib/recap/bootstrap.rb +0 -47
- data/lib/recap/capistrano_extensions.rb +0 -74
- data/lib/recap/cli.rb +0 -32
- data/lib/recap/deploy/templates/Capfile.erb +0 -6
- data/lib/recap/env.rb +0 -58
- data/lib/recap/environment.rb +0 -54
- data/lib/recap/namespace.rb +0 -37
- data/lib/recap/rails.rb +0 -24
- data/lib/recap/ruby.rb +0 -3
- data/lib/recap/static.rb +0 -1
@@ -1,163 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
5
|
-
<title>preflight.rb</title>
|
6
|
-
<link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
|
7
|
-
</head>
|
8
|
-
<body>
|
9
|
-
<div id='container'>
|
10
|
-
<div id="background"></div>
|
11
|
-
<div id="jump_to">
|
12
|
-
Jump To …
|
13
|
-
<div id="jump_wrapper">
|
14
|
-
<div id="jump_page">
|
15
|
-
<a class="source" href="../../index.html">index.rb</a>
|
16
|
-
<a class="source" href="../recap.html">recap.rb</a>
|
17
|
-
<a class="source" href="bootstrap.html">bootstrap.rb</a>
|
18
|
-
<a class="source" href="bundler.html">bundler.rb</a>
|
19
|
-
<a class="source" href="capistrano_extensions.html">capistrano_extensions.rb</a>
|
20
|
-
<a class="source" href="cli.html">cli.rb</a>
|
21
|
-
<a class="source" href="compatibility.html">compatibility.rb</a>
|
22
|
-
<a class="source" href="deploy.html">deploy.rb</a>
|
23
|
-
<a class="source" href="env.html">env.rb</a>
|
24
|
-
<a class="source" href="foreman.html">foreman.rb</a>
|
25
|
-
<a class="source" href="namespace.html">namespace.rb</a>
|
26
|
-
<a class="source" href="preflight.html">preflight.rb</a>
|
27
|
-
<a class="source" href="rails.html">rails.rb</a>
|
28
|
-
<a class="source" href="version.html">version.rb</a>
|
29
|
-
</div>
|
30
|
-
</div>
|
31
|
-
</div>
|
32
|
-
<table cellspacing=0 cellpadding=0>
|
33
|
-
<thead>
|
34
|
-
<tr>
|
35
|
-
<th class=docs><h1>preflight.rb</h1></th>
|
36
|
-
<th class=code></th>
|
37
|
-
</tr>
|
38
|
-
</thead>
|
39
|
-
<tbody>
|
40
|
-
<tr id='section-1'>
|
41
|
-
<td class=docs>
|
42
|
-
<div class="pilwrap">
|
43
|
-
<a class="pilcrow" href="#section-1">¶</a>
|
44
|
-
</div>
|
45
|
-
<p>Before <code>recap</code> will work correctly, a small amount of setup work needs to be performed on
|
46
|
-
all target servers.</p>
|
47
|
-
|
48
|
-
<p>First, each user who can deploy the app needs to have an account on each server, and must be able
|
49
|
-
to ssh into the box. They’ll also each need to be sudoers.</p>
|
50
|
-
|
51
|
-
<p>Secondly, each deploying user should set their git <code>user.name</code> and <code>user.email</code>. This can easily
|
52
|
-
be done by running:</p>
|
53
|
-
|
54
|
-
<p><code>git config —global user.email “you@example.com”</code>
|
55
|
-
<code>git config —global user.name “Your Name”</code></p>
|
56
|
-
|
57
|
-
<p>Finally, a user and group representing the application (and usually with the same name) should be
|
58
|
-
created. Where possible, the application user will run application code, while the group will own
|
59
|
-
application specific files. Each deploying user should be added to the application group.</p>
|
60
|
-
|
61
|
-
<p>This preflight recipe checks each of these things in turn, and attempts to give helpful advice
|
62
|
-
should a check fail.</p>
|
63
|
-
</td>
|
64
|
-
<td class=code>
|
65
|
-
<div class='highlight'><pre><span class="k">module</span> <span class="nn">Recap::Preflight</span>
|
66
|
-
<span class="kp">extend</span> <span class="no">Recap</span><span class="o">::</span><span class="no">Namespace</span>
|
67
|
-
|
68
|
-
<span class="n">namespace</span> <span class="ss">:preflight</span> <span class="k">do</span></pre></div>
|
69
|
-
</td>
|
70
|
-
</tr>
|
71
|
-
<tr id='section-2'>
|
72
|
-
<td class=docs>
|
73
|
-
<div class="pilwrap">
|
74
|
-
<a class="pilcrow" href="#section-2">¶</a>
|
75
|
-
</div>
|
76
|
-
<p>The preflight check is pretty quick, so run it before every <code>deploy:setup</code> and <code>deploy</code></p>
|
77
|
-
</td>
|
78
|
-
<td class=code>
|
79
|
-
<div class='highlight'><pre> <span class="n">before</span> <span class="s1">'deploy:setup'</span><span class="p">,</span> <span class="s1">'preflight:check'</span>
|
80
|
-
<span class="n">before</span> <span class="s1">'deploy'</span><span class="p">,</span> <span class="s1">'preflight:check'</span>
|
81
|
-
|
82
|
-
<span class="n">set</span><span class="p">(</span><span class="ss">:remote_username</span><span class="p">)</span> <span class="p">{</span> <span class="n">capture</span><span class="p">(</span><span class="s1">'whoami'</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span> <span class="p">}</span>
|
83
|
-
|
84
|
-
<span class="n">task</span> <span class="ss">:check</span> <span class="k">do</span></pre></div>
|
85
|
-
</td>
|
86
|
-
</tr>
|
87
|
-
<tr id='section-3'>
|
88
|
-
<td class=docs>
|
89
|
-
<div class="pilwrap">
|
90
|
-
<a class="pilcrow" href="#section-3">¶</a>
|
91
|
-
</div>
|
92
|
-
<p>First check the <code>application_user</code> exists</p>
|
93
|
-
</td>
|
94
|
-
<td class=code>
|
95
|
-
<div class='highlight'><pre> <span class="k">if</span> <span class="n">exit_code</span><span class="p">(</span><span class="s2">"id </span><span class="si">#{</span><span class="n">application_user</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span> <span class="o">!=</span> <span class="s2">"0"</span>
|
96
|
-
<span class="nb">abort</span> <span class="sx">%{</span>
|
97
|
-
<span class="sx">The application user '</span><span class="si">#{</span><span class="n">application_user</span><span class="si">}</span><span class="sx">' doesn't exist. You can create this user by logging into the server and running:</span>
|
98
|
-
|
99
|
-
<span class="sx"> sudo useradd </span><span class="si">#{</span><span class="n">application_user</span><span class="si">}</span><span class="sx"></span>
|
100
|
-
<span class="se">\n</span><span class="sx">}</span>
|
101
|
-
<span class="k">end</span></pre></div>
|
102
|
-
</td>
|
103
|
-
</tr>
|
104
|
-
<tr id='section-4'>
|
105
|
-
<td class=docs>
|
106
|
-
<div class="pilwrap">
|
107
|
-
<a class="pilcrow" href="#section-4">¶</a>
|
108
|
-
</div>
|
109
|
-
<p>Then the <code>application_group</code></p>
|
110
|
-
</td>
|
111
|
-
<td class=code>
|
112
|
-
<div class='highlight'><pre> <span class="k">if</span> <span class="n">exit_code</span><span class="p">(</span><span class="s2">"id -g </span><span class="si">#{</span><span class="n">application_group</span><span class="si">}</span><span class="s2">"</span><span class="p">)</span> <span class="o">!=</span> <span class="s2">"0"</span>
|
113
|
-
<span class="nb">abort</span> <span class="sx">%{</span>
|
114
|
-
<span class="sx">The application group '</span><span class="si">#{</span><span class="n">application_group</span><span class="si">}</span><span class="sx">' doesn't exist. You can create this group by logging into the server and running:</span>
|
115
|
-
|
116
|
-
<span class="sx"> sudo groupadd </span><span class="si">#{</span><span class="n">application_group</span><span class="si">}</span><span class="sx"></span>
|
117
|
-
<span class="sx"> sudo usermod --append -G </span><span class="si">#{</span><span class="n">application_group</span><span class="si">}</span><span class="sx"> </span><span class="si">#{</span><span class="n">application_user</span><span class="si">}</span><span class="sx"></span>
|
118
|
-
<span class="se">\n</span><span class="sx">}</span>
|
119
|
-
<span class="k">end</span></pre></div>
|
120
|
-
</td>
|
121
|
-
</tr>
|
122
|
-
<tr id='section-5'>
|
123
|
-
<td class=docs>
|
124
|
-
<div class="pilwrap">
|
125
|
-
<a class="pilcrow" href="#section-5">¶</a>
|
126
|
-
</div>
|
127
|
-
<p>Check the git configuration exists</p>
|
128
|
-
</td>
|
129
|
-
<td class=code>
|
130
|
-
<div class='highlight'><pre> <span class="k">if</span> <span class="n">capture</span><span class="p">(</span><span class="s1">'git config user.name || true'</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="o">.</span><span class="n">empty?</span> <span class="o">||</span> <span class="n">capture</span><span class="p">(</span><span class="s1">'git config user.email || true'</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="o">.</span><span class="n">empty?</span>
|
131
|
-
<span class="nb">abort</span> <span class="sx">%{</span>
|
132
|
-
<span class="sx">Your remote user must have a git user.name and user.email set. You can set these by logging into the server as </span><span class="si">#{</span><span class="n">remote_username</span><span class="si">}</span><span class="sx"> and running:</span>
|
133
|
-
|
134
|
-
<span class="sx"> git config --global user.email "you@example.com"</span>
|
135
|
-
<span class="sx"> git config --global user.name "Your Name"</span>
|
136
|
-
<span class="se">\n</span><span class="sx">}</span>
|
137
|
-
<span class="k">end</span></pre></div>
|
138
|
-
</td>
|
139
|
-
</tr>
|
140
|
-
<tr id='section-6'>
|
141
|
-
<td class=docs>
|
142
|
-
<div class="pilwrap">
|
143
|
-
<a class="pilcrow" href="#section-6">¶</a>
|
144
|
-
</div>
|
145
|
-
<p>And finally check the remote user is a member of the <code>application_group</code></p>
|
146
|
-
|
147
|
-
</td>
|
148
|
-
<td class=code>
|
149
|
-
<div class='highlight'><pre> <span class="k">unless</span> <span class="n">capture</span><span class="p">(</span><span class="s1">'groups'</span><span class="p">)</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">" "</span><span class="p">)</span><span class="o">.</span><span class="n">include?</span><span class="p">(</span><span class="n">application_group</span><span class="p">)</span>
|
150
|
-
<span class="nb">abort</span> <span class="sx">%{</span>
|
151
|
-
<span class="sx">Your remote user must be a member of the '</span><span class="si">#{</span><span class="n">application_group</span><span class="si">}</span><span class="sx">' group in order to perform deployments. You can add yourself to this group by logging into the server and running:</span>
|
152
|
-
|
153
|
-
<span class="sx"> sudo usermod --append -G </span><span class="si">#{</span><span class="n">application_group</span><span class="si">}</span><span class="sx"> </span><span class="si">#{</span><span class="n">remote_username</span><span class="si">}</span><span class="sx"></span>
|
154
|
-
<span class="se">\n</span><span class="sx">}</span>
|
155
|
-
<span class="k">end</span>
|
156
|
-
<span class="k">end</span>
|
157
|
-
<span class="k">end</span>
|
158
|
-
<span class="k">end</span></pre></div>
|
159
|
-
</td>
|
160
|
-
</tr>
|
161
|
-
</table>
|
162
|
-
</div>
|
163
|
-
</body>
|
data/doc/lib/recap/rails.html
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
5
|
-
<title>rails.rb</title>
|
6
|
-
<link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
|
7
|
-
</head>
|
8
|
-
<body>
|
9
|
-
<div id='container'>
|
10
|
-
<div id="background"></div>
|
11
|
-
<div id="jump_to">
|
12
|
-
Jump To …
|
13
|
-
<div id="jump_wrapper">
|
14
|
-
<div id="jump_page">
|
15
|
-
<a class="source" href="../../index.html">index.rb</a>
|
16
|
-
<a class="source" href="../recap.html">recap.rb</a>
|
17
|
-
<a class="source" href="bootstrap.html">bootstrap.rb</a>
|
18
|
-
<a class="source" href="bundler.html">bundler.rb</a>
|
19
|
-
<a class="source" href="capistrano_extensions.html">capistrano_extensions.rb</a>
|
20
|
-
<a class="source" href="cli.html">cli.rb</a>
|
21
|
-
<a class="source" href="compatibility.html">compatibility.rb</a>
|
22
|
-
<a class="source" href="deploy.html">deploy.rb</a>
|
23
|
-
<a class="source" href="env.html">env.rb</a>
|
24
|
-
<a class="source" href="foreman.html">foreman.rb</a>
|
25
|
-
<a class="source" href="namespace.html">namespace.rb</a>
|
26
|
-
<a class="source" href="preflight.html">preflight.rb</a>
|
27
|
-
<a class="source" href="rails.html">rails.rb</a>
|
28
|
-
<a class="source" href="version.html">version.rb</a>
|
29
|
-
</div>
|
30
|
-
</div>
|
31
|
-
</div>
|
32
|
-
<table cellspacing=0 cellpadding=0>
|
33
|
-
<thead>
|
34
|
-
<tr>
|
35
|
-
<th class=docs><h1>rails.rb</h1></th>
|
36
|
-
<th class=code></th>
|
37
|
-
</tr>
|
38
|
-
</thead>
|
39
|
-
<tbody>
|
40
|
-
</table>
|
41
|
-
</div>
|
42
|
-
</body>
|
data/doc/lib/recap/version.html
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
5
|
-
<title>version.rb</title>
|
6
|
-
<link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
|
7
|
-
</head>
|
8
|
-
<body>
|
9
|
-
<div id='container'>
|
10
|
-
<div id="background"></div>
|
11
|
-
<div id="jump_to">
|
12
|
-
Jump To …
|
13
|
-
<div id="jump_wrapper">
|
14
|
-
<div id="jump_page">
|
15
|
-
<a class="source" href="../../index.html">index.rb</a>
|
16
|
-
<a class="source" href="../recap.html">recap.rb</a>
|
17
|
-
<a class="source" href="bootstrap.html">bootstrap.rb</a>
|
18
|
-
<a class="source" href="bundler.html">bundler.rb</a>
|
19
|
-
<a class="source" href="capistrano_extensions.html">capistrano_extensions.rb</a>
|
20
|
-
<a class="source" href="cli.html">cli.rb</a>
|
21
|
-
<a class="source" href="compatibility.html">compatibility.rb</a>
|
22
|
-
<a class="source" href="deploy.html">deploy.rb</a>
|
23
|
-
<a class="source" href="env.html">env.rb</a>
|
24
|
-
<a class="source" href="foreman.html">foreman.rb</a>
|
25
|
-
<a class="source" href="namespace.html">namespace.rb</a>
|
26
|
-
<a class="source" href="preflight.html">preflight.rb</a>
|
27
|
-
<a class="source" href="rails.html">rails.rb</a>
|
28
|
-
<a class="source" href="version.html">version.rb</a>
|
29
|
-
</div>
|
30
|
-
</div>
|
31
|
-
</div>
|
32
|
-
<table cellspacing=0 cellpadding=0>
|
33
|
-
<thead>
|
34
|
-
<tr>
|
35
|
-
<th class=docs><h1>version.rb</h1></th>
|
36
|
-
<th class=code></th>
|
37
|
-
</tr>
|
38
|
-
</thead>
|
39
|
-
<tbody>
|
40
|
-
</table>
|
41
|
-
</div>
|
42
|
-
</body>
|
data/doc/lib/recap.html
DELETED
@@ -1,42 +0,0 @@
|
|
1
|
-
<!DOCTYPE html>
|
2
|
-
<html>
|
3
|
-
<head>
|
4
|
-
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
5
|
-
<title>recap.rb</title>
|
6
|
-
<link rel="stylesheet" href="http://jashkenas.github.com/docco/resources/docco.css">
|
7
|
-
</head>
|
8
|
-
<body>
|
9
|
-
<div id='container'>
|
10
|
-
<div id="background"></div>
|
11
|
-
<div id="jump_to">
|
12
|
-
Jump To …
|
13
|
-
<div id="jump_wrapper">
|
14
|
-
<div id="jump_page">
|
15
|
-
<a class="source" href="../index.html">index.rb</a>
|
16
|
-
<a class="source" href="recap.html">recap.rb</a>
|
17
|
-
<a class="source" href="recap/bootstrap.html">bootstrap.rb</a>
|
18
|
-
<a class="source" href="recap/bundler.html">bundler.rb</a>
|
19
|
-
<a class="source" href="recap/capistrano_extensions.html">capistrano_extensions.rb</a>
|
20
|
-
<a class="source" href="recap/cli.html">cli.rb</a>
|
21
|
-
<a class="source" href="recap/compatibility.html">compatibility.rb</a>
|
22
|
-
<a class="source" href="recap/deploy.html">deploy.rb</a>
|
23
|
-
<a class="source" href="recap/env.html">env.rb</a>
|
24
|
-
<a class="source" href="recap/foreman.html">foreman.rb</a>
|
25
|
-
<a class="source" href="recap/namespace.html">namespace.rb</a>
|
26
|
-
<a class="source" href="recap/preflight.html">preflight.rb</a>
|
27
|
-
<a class="source" href="recap/rails.html">rails.rb</a>
|
28
|
-
<a class="source" href="recap/version.html">version.rb</a>
|
29
|
-
</div>
|
30
|
-
</div>
|
31
|
-
</div>
|
32
|
-
<table cellspacing=0 cellpadding=0>
|
33
|
-
<thead>
|
34
|
-
<tr>
|
35
|
-
<th class=docs><h1>recap.rb</h1></th>
|
36
|
-
<th class=code></th>
|
37
|
-
</tr>
|
38
|
-
</thead>
|
39
|
-
<tbody>
|
40
|
-
</table>
|
41
|
-
</div>
|
42
|
-
</body>
|
data/index.rb
DELETED
@@ -1,62 +0,0 @@
|
|
1
|
-
# This is the annotated source code and documentation for
|
2
|
-
# [recap](http://github.com/freerange/recap), a simple, opinionated set of capistrano
|
3
|
-
# deployment recipes.
|
4
|
-
|
5
|
-
# Inspired in part by
|
6
|
-
# [this blog post](https://github.com/blog/470-deployment-script-spring-cleaning), these recipes use
|
7
|
-
# git's strengths to deploy applications in a faster, simpler manner than a standard capistrano
|
8
|
-
# deployment. Using git to manage release versions means apps can be deployed to a single directory.
|
9
|
-
# There's no need for `releases`, `shared` or `current` folders, and no symlinking.
|
10
|
-
|
11
|
-
# ### Goals ###
|
12
|
-
|
13
|
-
# These deployment recipes try to do the following:
|
14
|
-
|
15
|
-
# Where possible run commands as the `application_user`, loading the full user environment. The only
|
16
|
-
# exceptions are `git` commands (which often rely on SSH agent forwarding for authentication), and
|
17
|
-
# anything that requires `sudo`.
|
18
|
-
#
|
19
|
-
|
20
|
-
# Use `git` to avoid unecessary work. If the `Gemfile.lock` hasn't changed, there's no need to run
|
21
|
-
# `bundle install`. Similarly if there are no new migrations, why do `rake db:migrate`? Faster
|
22
|
-
# deploys mean more frequent deploys.
|
23
|
-
#
|
24
|
-
|
25
|
-
# Avoid the use of `sudo` (other than to change to the `application_user`). As much as possible,
|
26
|
-
# `sudo` is only used to `su` to the `application_user` before running a command. To avoid having to
|
27
|
-
# type a password to perform the majority of deployment tasks, these lines can be added to
|
28
|
-
# `/etc/sudoers.d/application` (change `application` to the name of your app).
|
29
|
-
|
30
|
-
%application ALL=NOPASSWD: /sbin/start application*
|
31
|
-
%application ALL=NOPASSWD: /sbin/stop application*
|
32
|
-
%application ALL=NOPASSWD: /sbin/restart application*
|
33
|
-
%application ALL=NOPASSWD: /bin/su - application*
|
34
|
-
%application ALL=NOPASSWD: /bin/su application*
|
35
|
-
|
36
|
-
# Use environment variables for configuration. Rather than setting `rails_env` in the `Capfile`,
|
37
|
-
# `RAILS_ENV` (or `RACK_ENV`) variables should be set for the `application_user`. The `env:set` and
|
38
|
-
# `env:edit` tasks help do this.
|
39
|
-
|
40
|
-
# ### Code layout ###
|
41
|
-
|
42
|
-
# The main deployment tasks are defined in [recap/deploy.rb](lib/recap/deploy.html). Automatic
|
43
|
-
# checks to ensure servers are correctly setup are in
|
44
|
-
# [recap/preflight.rb](lib/recap/preflight.html), while tasks for environment variables are in
|
45
|
-
# [recap/env.rb](lib/recap/env.html)
|
46
|
-
|
47
|
-
# In addition, there are extensions for [bundler](lib/recap/bundler.html),
|
48
|
-
# [foreman](lib/recap/foreman.html) and [rails](lib/recap/rails.html)
|
49
|
-
|
50
|
-
# For limited compatability with other existing recipes, see
|
51
|
-
# [compatibility](lib/recap/compatibility.html).
|
52
|
-
|
53
|
-
# ### Deployment target ###
|
54
|
-
|
55
|
-
# These recipes have been developed and tested using Ubuntu 11.04, though they may work well with
|
56
|
-
# other flavours of unix.
|
57
|
-
|
58
|
-
# The application should be run as the application user; if using Apache and Passenger, you should
|
59
|
-
# set the `PassengerDefaultUser` directive to be the same as the `application_user`.
|
60
|
-
|
61
|
-
# The code is available [on github](http://github.com/freerange/recap) and released under the
|
62
|
-
# [MIT License](https://github.com/freerange/recap/blob/master/LICENSE)
|
data/lib/recap/bootstrap.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module Recap::Bootstrap
|
2
|
-
extend Recap::Namespace
|
3
|
-
|
4
|
-
namespace :bootstrap do
|
5
|
-
set(:remote_username) { capture('whoami').strip }
|
6
|
-
set(:application_home) { "/home/#{application_user}"}
|
7
|
-
|
8
|
-
task :default do
|
9
|
-
application
|
10
|
-
user
|
11
|
-
end
|
12
|
-
|
13
|
-
task :application do
|
14
|
-
if exit_code("id #{application_user}").strip != "0"
|
15
|
-
sudo "useradd #{application_user} -d #{application_home}"
|
16
|
-
end
|
17
|
-
sudo "mkdir -p #{application_home}"
|
18
|
-
sudo "chown #{application_user}:#{application_group} #{application_home}"
|
19
|
-
sudo "chmod 755 #{application_home}"
|
20
|
-
|
21
|
-
put_as_app %{
|
22
|
-
if [ -s "$HOME/.env" ]; then
|
23
|
-
rm -rf $HOME/.recap-env-export
|
24
|
-
touch $HOME/.recap-env-export
|
25
|
-
while read line
|
26
|
-
do echo "export $line" >> $HOME/.recap-env-export;
|
27
|
-
done < $HOME/.env
|
28
|
-
. $HOME/.recap-env-export
|
29
|
-
fi
|
30
|
-
}, "#{application_home}/.recap"
|
31
|
-
|
32
|
-
as_app "touch .profile", "~"
|
33
|
-
|
34
|
-
if exit_code(%{grep '\\. \\$HOME\\/.recap' .profile}) != "0"
|
35
|
-
as_app %{echo >> .profile && echo ". \\$HOME/.recap" >> .profile}, "~"
|
36
|
-
end
|
37
|
-
|
38
|
-
as_app "mkdir -p #{deploy_to}", "~"
|
39
|
-
end
|
40
|
-
|
41
|
-
task :user do
|
42
|
-
run "git config --global user.name '#{`git config user.name`.strip}'"
|
43
|
-
run "git config --global user.email '#{`git config user.email`.strip}'"
|
44
|
-
sudo "usermod --append -G #{application_group} #{remote_username}"
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
@@ -1,74 +0,0 @@
|
|
1
|
-
require 'tempfile'
|
2
|
-
|
3
|
-
module Recap
|
4
|
-
module CapistranoExtensions
|
5
|
-
# Run a command as the given user
|
6
|
-
def as_user(user, command, pwd = deploy_to)
|
7
|
-
sudo "su - #{user} -c 'cd #{pwd} && #{command}'"
|
8
|
-
end
|
9
|
-
|
10
|
-
# Run a command as root
|
11
|
-
def as_root(command, pwd = deploy_to)
|
12
|
-
as_user 'root', command, pwd
|
13
|
-
end
|
14
|
-
|
15
|
-
# Run a command as the application user
|
16
|
-
def as_app(command, pwd = deploy_to)
|
17
|
-
as_user application_user, command, pwd
|
18
|
-
end
|
19
|
-
|
20
|
-
# Put a string into a file as the application user
|
21
|
-
def put_as_app(string, path)
|
22
|
-
put string, "/tmp/recap-put-as-app"
|
23
|
-
as_app "cp /tmp/recap-put-as-app #{path} && chmod g+rw #{path}", "/"
|
24
|
-
end
|
25
|
-
|
26
|
-
# Edit a file on the remote server, using a local editor
|
27
|
-
def edit_file(path)
|
28
|
-
if editor = ENV['DEPLOY_EDITOR'] || ENV['EDITOR']
|
29
|
-
as_app "touch #{path} && chmod g+rw #{path}"
|
30
|
-
local_path = Tempfile.new('deploy-edit').path
|
31
|
-
get(path, local_path)
|
32
|
-
`#{editor} #{local_path}`
|
33
|
-
upload(local_path, path)
|
34
|
-
else
|
35
|
-
abort "To edit a remote file, either the EDITOR or DEPLOY_EDITOR environment variables must be set"
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
# Run a git command in the `deploy_to` directory
|
40
|
-
def git(command)
|
41
|
-
run "cd #{deploy_to} && umask 002 && sg #{application_group} -c \"git #{command}\""
|
42
|
-
end
|
43
|
-
|
44
|
-
# Capture the result of a git command run within the `deploy_to` directory
|
45
|
-
def capture_git(command)
|
46
|
-
capture "cd #{deploy_to} && umask 002 && sg #{application_group} -c 'git #{command}'"
|
47
|
-
end
|
48
|
-
|
49
|
-
def exit_code(command)
|
50
|
-
capture("#{command} > /dev/null 2>&1; echo $?").strip
|
51
|
-
end
|
52
|
-
|
53
|
-
# Find the latest tag from the repository. As `git tag` returns tags in order, and our release
|
54
|
-
# tags are timestamps, the latest tag will always be the last in the list.
|
55
|
-
def latest_tag_from_repository
|
56
|
-
result = capture_git("tag | tail -n1").strip
|
57
|
-
result.empty? ? nil : result
|
58
|
-
end
|
59
|
-
|
60
|
-
# Does the given file exist within the deployment directory?
|
61
|
-
def deployed_file_exists?(path)
|
62
|
-
exit_code("cd #{deploy_to} && [ -f #{path} ]") == "0"
|
63
|
-
end
|
64
|
-
|
65
|
-
# Has the given path been created or changed since the previous deployment? During the first
|
66
|
-
# successful deployment this will always return true.
|
67
|
-
def deployed_file_changed?(path)
|
68
|
-
return true unless latest_tag
|
69
|
-
exit_code("cd #{deploy_to} && git diff --exit-code #{latest_tag} origin/#{branch} #{path}") == "1"
|
70
|
-
end
|
71
|
-
|
72
|
-
Capistrano::Configuration.send :include, self
|
73
|
-
end
|
74
|
-
end
|
data/lib/recap/cli.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'thor'
|
2
|
-
|
3
|
-
module Recap
|
4
|
-
class CLI < Thor
|
5
|
-
include Thor::Actions
|
6
|
-
|
7
|
-
attr_accessor :name, :repository
|
8
|
-
|
9
|
-
def self.source_root
|
10
|
-
File.expand_path("../deploy/templates", __FILE__)
|
11
|
-
end
|
12
|
-
|
13
|
-
desc 'setup', 'Setup basic capistrano recipes, e.g: recap setup'
|
14
|
-
method_option :name, :aliases => "-n"
|
15
|
-
method_option :repository, :aliases => "-r"
|
16
|
-
def setup
|
17
|
-
self.name = options["name"] || guess_name
|
18
|
-
self.repository = options["repo"] || guess_repository
|
19
|
-
template 'Capfile.erb', 'Capfile'
|
20
|
-
end
|
21
|
-
|
22
|
-
private
|
23
|
-
|
24
|
-
def guess_name
|
25
|
-
Dir.pwd.split(File::SEPARATOR).last
|
26
|
-
end
|
27
|
-
|
28
|
-
def guess_repository
|
29
|
-
`git remote -v`.split[1]
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
data/lib/recap/env.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
# Environment variables are a useful way to set application configuration, such as database passwords
|
2
|
-
# or S3 keys and secrets. [recap](http://github.com/freerange/recap) stores these extra variables in
|
3
|
-
# a special file, usually stored at `$HOME/.env`. This file is loaded each time the shell starts by
|
4
|
-
# adding the following to the user's `.profile`:
|
5
|
-
#
|
6
|
-
# . $HOME/.recap
|
7
|
-
#
|
8
|
-
# The `.recap` script is automatically generated in the bootstrap process.
|
9
|
-
|
10
|
-
module Recap::Env
|
11
|
-
extend Recap::Namespace
|
12
|
-
|
13
|
-
namespace :env do
|
14
|
-
# Environment
|
15
|
-
set(:environment_file) { "/home/#{application_user}/.env" }
|
16
|
-
|
17
|
-
def current_environment
|
18
|
-
@current_environment ||= begin
|
19
|
-
if deployed_file_exists?(environment_file)
|
20
|
-
Recap::Environment.from_string(capture("cat #{environment_file}"))
|
21
|
-
else
|
22
|
-
Recap::Environment.new
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
task :default do
|
28
|
-
if current_environment.empty?
|
29
|
-
puts "There are no config variables set"
|
30
|
-
else
|
31
|
-
puts "The config variables are:"
|
32
|
-
puts
|
33
|
-
puts current_environment
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
task :set do
|
38
|
-
env = ARGV[1..-1].inject(current_environment) do |env, string|
|
39
|
-
env.set_string(string)
|
40
|
-
logger.debug "Setting #{string}"
|
41
|
-
logger.debug "Env is now: #{env}"
|
42
|
-
env
|
43
|
-
end
|
44
|
-
|
45
|
-
if env.empty?
|
46
|
-
as_app "rm -f #{environment_file}", "~"
|
47
|
-
else
|
48
|
-
put_as_app env.to_s, environment_file
|
49
|
-
end
|
50
|
-
default
|
51
|
-
end
|
52
|
-
|
53
|
-
task :edit do
|
54
|
-
edit_file environment_file
|
55
|
-
default
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
data/lib/recap/environment.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
class Recap::Environment
|
2
|
-
def initialize(variables = {})
|
3
|
-
@variables = variables
|
4
|
-
end
|
5
|
-
|
6
|
-
def get(name)
|
7
|
-
@variables[name]
|
8
|
-
end
|
9
|
-
|
10
|
-
def set(name, value)
|
11
|
-
if value.nil? || value.empty?
|
12
|
-
@variables.delete(name)
|
13
|
-
else
|
14
|
-
@variables[name] = value
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
def set_string(string)
|
19
|
-
if string =~ /\A([A-Za-z0-9_]+)=(.*)\z/
|
20
|
-
set $1, $2
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def empty?
|
25
|
-
@variables.empty?
|
26
|
-
end
|
27
|
-
|
28
|
-
def merge(hash)
|
29
|
-
hash.each {|k, v| set(k, v)}
|
30
|
-
end
|
31
|
-
|
32
|
-
def each(&block)
|
33
|
-
@variables.sort.each(&block)
|
34
|
-
end
|
35
|
-
|
36
|
-
def include?(key)
|
37
|
-
@variables.include?(key)
|
38
|
-
end
|
39
|
-
|
40
|
-
def to_s
|
41
|
-
@variables.keys.sort.map do |key|
|
42
|
-
key + "=" + @variables[key] + "\n" if @variables[key]
|
43
|
-
end.compact.join
|
44
|
-
end
|
45
|
-
|
46
|
-
class << self
|
47
|
-
def from_string(string)
|
48
|
-
string.split("\n").inject(new) do |env, line|
|
49
|
-
env.set_string(line)
|
50
|
-
env
|
51
|
-
end
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|