recap 0.1.0 → 0.2.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 +3 -0
- data/.travis.yml +4 -0
- data/README.md +12 -3
- data/Rakefile +8 -0
- data/Vagrantfile +61 -0
- data/doc/index.html +45 -26
- data/doc/lib/recap/bootstrap.html +42 -0
- data/doc/lib/recap/bundler.html +36 -19
- data/doc/lib/recap/capistrano_extensions.html +28 -23
- data/doc/lib/recap/cli.html +3 -0
- data/doc/lib/recap/compatibility.html +6 -3
- data/doc/lib/recap/deploy.html +41 -86
- data/doc/lib/recap/env.html +6 -1
- data/doc/lib/recap/foreman.html +3 -0
- data/doc/lib/recap/namespace.html +42 -0
- data/doc/lib/recap/preflight.html +12 -7
- data/doc/lib/recap/rails.html +3 -0
- data/doc/lib/recap/version.html +3 -0
- data/doc/lib/recap.html +42 -0
- data/features/bundling-gems.feature +18 -0
- data/features/deploying-projects.feature +21 -0
- data/features/managing-processes.feature +17 -0
- data/features/setting-environment-variables.feature +21 -0
- data/features/steps/capistrano_steps.rb +98 -0
- data/features/support/project.rb +211 -0
- data/features/support/server.rb +53 -0
- data/features/templates/gem/binary.erb +43 -0
- data/features/templates/gem/gemspec.erb +11 -0
- data/features/templates/project/Capfile +21 -0
- data/features/templates/project/Capfile.erb +21 -0
- data/features/templates/project/Gemfile.erb +7 -0
- data/features/templates/project/Procfile.erb +1 -0
- data/index.rb +26 -17
- data/lib/recap/bootstrap.rb +47 -0
- data/lib/recap/bundler.rb +31 -21
- data/lib/recap/capistrano_extensions.rb +11 -9
- data/lib/recap/cli.rb +1 -1
- data/lib/recap/compatibility.rb +3 -3
- data/lib/recap/deploy.rb +45 -57
- data/lib/recap/env.rb +30 -26
- data/lib/recap/environment.rb +54 -0
- data/lib/recap/foreman.rb +28 -9
- data/lib/recap/namespace.rb +37 -0
- data/lib/recap/preflight.rb +10 -8
- data/lib/recap/rails.rb +6 -4
- data/lib/recap/ruby.rb +3 -0
- data/lib/recap/static.rb +1 -0
- data/lib/recap/version.rb +1 -1
- data/lib/recap.rb +12 -0
- data/recap.gemspec +8 -4
- data/spec/models/environment_spec.rb +143 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/tasks/bootstrap_spec.rb +34 -0
- data/spec/tasks/bundler_spec.rb +126 -0
- data/spec/tasks/deploy_spec.rb +209 -0
- data/spec/tasks/env_spec.rb +38 -0
- data/spec/tasks/foreman_spec.rb +154 -0
- data/test-vm/manifests/base.pp +17 -0
- data/test-vm/share/.gitkeep +0 -0
- metadata +138 -19
- /data/bin/{tomafro-deploy → recap} +0 -0
@@ -0,0 +1,42 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta http-equiv="content-type" content="text/html;charset=utf-8">
|
5
|
+
<title>namespace.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>namespace.rb</h1></th>
|
36
|
+
<th class=code></th>
|
37
|
+
</tr>
|
38
|
+
</thead>
|
39
|
+
<tbody>
|
40
|
+
</table>
|
41
|
+
</div>
|
42
|
+
</body>
|
@@ -13,6 +13,8 @@
|
|
13
13
|
<div id="jump_wrapper">
|
14
14
|
<div id="jump_page">
|
15
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>
|
16
18
|
<a class="source" href="bundler.html">bundler.rb</a>
|
17
19
|
<a class="source" href="capistrano_extensions.html">capistrano_extensions.rb</a>
|
18
20
|
<a class="source" href="cli.html">cli.rb</a>
|
@@ -20,6 +22,7 @@
|
|
20
22
|
<a class="source" href="deploy.html">deploy.rb</a>
|
21
23
|
<a class="source" href="env.html">env.rb</a>
|
22
24
|
<a class="source" href="foreman.html">foreman.rb</a>
|
25
|
+
<a class="source" href="namespace.html">namespace.rb</a>
|
23
26
|
<a class="source" href="preflight.html">preflight.rb</a>
|
24
27
|
<a class="source" href="rails.html">rails.rb</a>
|
25
28
|
<a class="source" href="version.html">version.rb</a>
|
@@ -59,7 +62,10 @@ application specific files. Each deploying user should be added to the applicat
|
|
59
62
|
should a check fail.</p>
|
60
63
|
</td>
|
61
64
|
<td class=code>
|
62
|
-
<div class='highlight'><pre><span class="
|
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>
|
63
69
|
</td>
|
64
70
|
</tr>
|
65
71
|
<tr id='section-2'>
|
@@ -70,12 +76,11 @@ should a check fail.</p>
|
|
70
76
|
<p>The preflight check is pretty quick, so run it before every <code>deploy:setup</code> and <code>deploy</code></p>
|
71
77
|
</td>
|
72
78
|
<td class=code>
|
73
|
-
<div class='highlight'><pre>
|
74
|
-
|
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>
|
75
81
|
|
76
|
-
|
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>
|
77
83
|
|
78
|
-
<span class="n">namespace</span> <span class="ss">:preflight</span> <span class="k">do</span>
|
79
84
|
<span class="n">task</span> <span class="ss">:check</span> <span class="k">do</span></pre></div>
|
80
85
|
</td>
|
81
86
|
</tr>
|
@@ -87,7 +92,7 @@ should a check fail.</p>
|
|
87
92
|
<p>First check the <code>application_user</code> exists</p>
|
88
93
|
</td>
|
89
94
|
<td class=code>
|
90
|
-
<div class='highlight'><pre> <span class="k">if</span> <span class="n">
|
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>
|
91
96
|
<span class="nb">abort</span> <span class="sx">%{</span>
|
92
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>
|
93
98
|
|
@@ -104,7 +109,7 @@ should a check fail.</p>
|
|
104
109
|
<p>Then the <code>application_group</code></p>
|
105
110
|
</td>
|
106
111
|
<td class=code>
|
107
|
-
<div class='highlight'><pre> <span class="k">if</span> <span class="n">
|
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>
|
108
113
|
<span class="nb">abort</span> <span class="sx">%{</span>
|
109
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>
|
110
115
|
|
data/doc/lib/recap/rails.html
CHANGED
@@ -13,6 +13,8 @@
|
|
13
13
|
<div id="jump_wrapper">
|
14
14
|
<div id="jump_page">
|
15
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>
|
16
18
|
<a class="source" href="bundler.html">bundler.rb</a>
|
17
19
|
<a class="source" href="capistrano_extensions.html">capistrano_extensions.rb</a>
|
18
20
|
<a class="source" href="cli.html">cli.rb</a>
|
@@ -20,6 +22,7 @@
|
|
20
22
|
<a class="source" href="deploy.html">deploy.rb</a>
|
21
23
|
<a class="source" href="env.html">env.rb</a>
|
22
24
|
<a class="source" href="foreman.html">foreman.rb</a>
|
25
|
+
<a class="source" href="namespace.html">namespace.rb</a>
|
23
26
|
<a class="source" href="preflight.html">preflight.rb</a>
|
24
27
|
<a class="source" href="rails.html">rails.rb</a>
|
25
28
|
<a class="source" href="version.html">version.rb</a>
|
data/doc/lib/recap/version.html
CHANGED
@@ -13,6 +13,8 @@
|
|
13
13
|
<div id="jump_wrapper">
|
14
14
|
<div id="jump_page">
|
15
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>
|
16
18
|
<a class="source" href="bundler.html">bundler.rb</a>
|
17
19
|
<a class="source" href="capistrano_extensions.html">capistrano_extensions.rb</a>
|
18
20
|
<a class="source" href="cli.html">cli.rb</a>
|
@@ -20,6 +22,7 @@
|
|
20
22
|
<a class="source" href="deploy.html">deploy.rb</a>
|
21
23
|
<a class="source" href="env.html">env.rb</a>
|
22
24
|
<a class="source" href="foreman.html">foreman.rb</a>
|
25
|
+
<a class="source" href="namespace.html">namespace.rb</a>
|
23
26
|
<a class="source" href="preflight.html">preflight.rb</a>
|
24
27
|
<a class="source" href="rails.html">rails.rb</a>
|
25
28
|
<a class="source" href="version.html">version.rb</a>
|
data/doc/lib/recap.html
ADDED
@@ -0,0 +1,42 @@
|
|
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>
|
@@ -0,0 +1,18 @@
|
|
1
|
+
Feature: Bundling gems in ruby projects
|
2
|
+
|
3
|
+
Scenario: Deploying a project with a Gemfile
|
4
|
+
|
5
|
+
Given a new ruby project and a bootstrapped server
|
6
|
+
And a bundle requiring version "1.0" of "example-gem"
|
7
|
+
When I run "cap deploy:setup deploy"
|
8
|
+
Then the project should be deployed
|
9
|
+
And the deployed project should include version "1.0" of "example-gem"
|
10
|
+
|
11
|
+
Scenario: Updating a project bundle
|
12
|
+
|
13
|
+
Given a new ruby project and a bootstrapped server
|
14
|
+
And a bundle requiring version "1.0" of "example-gem"
|
15
|
+
And I run "cap deploy:setup deploy"
|
16
|
+
When I update the bundle to require version "1.1" of "example-gem"
|
17
|
+
And I run "cap deploy"
|
18
|
+
Then the deployed project should include version "1.1" of "example-gem"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Feature: Deploying and rolling back deployments
|
2
|
+
|
3
|
+
Scenario: Deploying for the first time
|
4
|
+
|
5
|
+
Given a new project and a bootstrapped server
|
6
|
+
When I run "cap deploy:setup deploy"
|
7
|
+
Then the project should be deployed
|
8
|
+
|
9
|
+
Scenario: Deploying after changes
|
10
|
+
|
11
|
+
Given a deployed project
|
12
|
+
When I commit changes to the project
|
13
|
+
And I run "cap deploy"
|
14
|
+
Then the latest version of the project should be deployed
|
15
|
+
|
16
|
+
Scenario: Rolling back to the previous version
|
17
|
+
|
18
|
+
Given a deployed project
|
19
|
+
When I commit and deploy changes to the project
|
20
|
+
And I run "cap deploy:rollback"
|
21
|
+
Then the previous project version should be deployed
|
@@ -0,0 +1,17 @@
|
|
1
|
+
|
2
|
+
Feature: Managing processes with foreman
|
3
|
+
|
4
|
+
Scenario: Running an application process
|
5
|
+
Given a new ruby project and a bootstrapped server
|
6
|
+
And the project has an application process defined in a Procfile
|
7
|
+
When I run "cap deploy:setup deploy"
|
8
|
+
Then the project should own the running application process
|
9
|
+
|
10
|
+
Scenario: Running processes can read environment variables
|
11
|
+
Given a new ruby project and a bootstrapped server
|
12
|
+
And the project has an application process defined in a Procfile
|
13
|
+
And the variable "MONSTER" is set to "tricorn"
|
14
|
+
When I run "cap deploy:setup deploy"
|
15
|
+
And I wait for the server to start
|
16
|
+
Then the variable "MONSTER" should be set to "tricorn"
|
17
|
+
Then the running application process should know that "MONSTER" is set to "tricorn"
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Feature: Setting and unsetting environment config variables
|
2
|
+
|
3
|
+
Scenario: Setting an environment variable
|
4
|
+
|
5
|
+
Given a new project and a bootstrapped server
|
6
|
+
When I run "cap env:set SECRET=very-secure"
|
7
|
+
Then the variable "SECRET" should be set to "very-secure"
|
8
|
+
|
9
|
+
@wip
|
10
|
+
Scenario: Setting an environment variable based on an existing variable
|
11
|
+
|
12
|
+
Given a new project and a bootstrapped server
|
13
|
+
When I run "cap env:set SUPER_PATH=\$PATH"
|
14
|
+
Then the variable "SUPER_PATH" should be set to the application's PATH
|
15
|
+
|
16
|
+
Scenario: Unsetting a variable
|
17
|
+
|
18
|
+
Given a new project and a bootstrapped server
|
19
|
+
And the variable "SECRET" is set to "very-secure"
|
20
|
+
When I run "cap env:set SECRET="
|
21
|
+
Then the variable "SECRET" should have no value
|
@@ -0,0 +1,98 @@
|
|
1
|
+
Before do
|
2
|
+
FileUtils.rm_rf 'test-vm/share/projects'
|
3
|
+
FileUtils.rm_rf 'test-vm/share/gems'
|
4
|
+
`bundle exec vagrant sandbox on` unless ENV['SKIP_ROLLBACK']
|
5
|
+
end
|
6
|
+
|
7
|
+
After do
|
8
|
+
`bundle exec vagrant sandbox rollback` unless ENV['SKIP_ROLLBACK']
|
9
|
+
if project
|
10
|
+
project.run_on_server "sudo stop #{project.name} || true"
|
11
|
+
project.run_on_server "sudo rm -rf /etc/init/#{project.name}* || true"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Given /^a new (ruby )?project and a bootstrapped server$/ do |project_type|
|
16
|
+
type = (project_type || 'static').strip
|
17
|
+
start_project server: server, capfile: { recap_require: "recap/#{type}" }
|
18
|
+
project.run_cap 'bootstrap'
|
19
|
+
end
|
20
|
+
|
21
|
+
Given /^a deployed project$/ do
|
22
|
+
start_project server: server
|
23
|
+
project.run_cap 'bootstrap'
|
24
|
+
project.run_cap 'deploy:setup deploy'
|
25
|
+
end
|
26
|
+
|
27
|
+
Given /^a bundle requiring version "([^"]*)" of "([^"]*)"$/ do |version, gem|
|
28
|
+
project.add_gem_to_bundle(gem, version)
|
29
|
+
end
|
30
|
+
|
31
|
+
Given /^the variable "([^"]*)" is set to "([^"]*)"$/ do |name, value|
|
32
|
+
project.run_cap "env:set #{name}=#{value}"
|
33
|
+
end
|
34
|
+
|
35
|
+
Given /^the project has an application process defined in a Procfile$/ do
|
36
|
+
@application_process = 'an-application-process'
|
37
|
+
project.add_foreman_to_bundle
|
38
|
+
project.add_gem_to_bundle @application_process, '1.0.0'
|
39
|
+
project.add_command_to_procfile 'process', "bin/#{@application_process} --server"
|
40
|
+
end
|
41
|
+
|
42
|
+
When /^I update the bundle to require version "([^"]*)" of "([^"]*)"$/ do |version, gem|
|
43
|
+
project.add_gem_to_bundle(gem, version)
|
44
|
+
end
|
45
|
+
|
46
|
+
When /^I run "cap ([^"]*)"$/ do |command|
|
47
|
+
project.run_cap command
|
48
|
+
end
|
49
|
+
|
50
|
+
When /^I commit changes to the project$/ do
|
51
|
+
project.commit_changes
|
52
|
+
end
|
53
|
+
|
54
|
+
When /^I commit and deploy changes to the project$/ do
|
55
|
+
project.commit_changes
|
56
|
+
project.run_cap 'deploy'
|
57
|
+
end
|
58
|
+
|
59
|
+
When /^I wait for the server to start$/ do
|
60
|
+
sleep(5)
|
61
|
+
end
|
62
|
+
|
63
|
+
Then /^the project should be deployed$/ do
|
64
|
+
project.deployed_version.should eql(project.latest_version)
|
65
|
+
end
|
66
|
+
|
67
|
+
Then /^the latest version of the project should be deployed$/ do
|
68
|
+
project.deployed_version.should eql(project.latest_version)
|
69
|
+
end
|
70
|
+
|
71
|
+
Then /^the previous project version should be deployed$/ do
|
72
|
+
project.deployed_version.should eql(project.previous_version)
|
73
|
+
end
|
74
|
+
|
75
|
+
Then /^the deployed project should include version "([^"]*)" of "([^"]*)"$/ do |version, gem|
|
76
|
+
project.run_on_server("bin/#{gem} --version").strip.should eql(version)
|
77
|
+
end
|
78
|
+
|
79
|
+
Then /^the variable "([^"]*)" should be set to "([^"]*)"$/ do |name, value|
|
80
|
+
project.run_on_server("sudo su - #{project.name} -c 'env | grep #{name}'").strip.should eql("#{name}=#{value}")
|
81
|
+
end
|
82
|
+
|
83
|
+
Then /^the variable "([^"]*)" should be set to the application's PATH$/ do |name|
|
84
|
+
path = project.run_on_server("echo $PATH").strip
|
85
|
+
project.run_on_server("sudo su - #{project.name} -c 'env | grep #{name}'").strip.should eql("#{name}=#{path}")
|
86
|
+
end
|
87
|
+
|
88
|
+
Then /^the variable "([^"]*)" should have no value$/ do |name|
|
89
|
+
project.run_on_server("sudo su - #{project.name} -c 'env'").include?("#{name}=").should be_false
|
90
|
+
end
|
91
|
+
|
92
|
+
Then /^the project should own the running application process$/ do
|
93
|
+
project.run_on_server("ps -U #{project.name} u").include?(@application_process).should be_true
|
94
|
+
end
|
95
|
+
|
96
|
+
Then /^the running application process should know that "([^"]*)" is set to "([^"]*)"$/ do |name, value|
|
97
|
+
project.run_on_server("/usr/bin/curl localhost:3500/env | grep #{name}").strip.should eql("#{name}=#{value}")
|
98
|
+
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
require 'faker'
|
3
|
+
require 'erb'
|
4
|
+
|
5
|
+
module ProjectSupport
|
6
|
+
def project
|
7
|
+
@project
|
8
|
+
end
|
9
|
+
|
10
|
+
def start_project(options = {})
|
11
|
+
@project = Project.new(options)
|
12
|
+
end
|
13
|
+
|
14
|
+
class Template
|
15
|
+
def initialize(template_name)
|
16
|
+
@template_name = template_name
|
17
|
+
end
|
18
|
+
|
19
|
+
def template_root
|
20
|
+
File.expand_path("../../templates/", __FILE__)
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_s
|
24
|
+
ERB.new(read_template).result(binding)
|
25
|
+
end
|
26
|
+
|
27
|
+
def write_to(path)
|
28
|
+
full_path = File.expand_path(path)
|
29
|
+
FileUtils.mkdir_p File.dirname(full_path)
|
30
|
+
File.write(full_path, to_s)
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_template
|
34
|
+
template_path = File.join(template_root, @template_name)
|
35
|
+
File.read(template_path)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Capfile < Template
|
40
|
+
attr_reader :project, :recap_require
|
41
|
+
|
42
|
+
def initialize(project, options = {})
|
43
|
+
super('project/Capfile.erb')
|
44
|
+
@project = project
|
45
|
+
@recap_require = options[:recap_require] || 'recap/static'
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class Gemfile < Template
|
50
|
+
attr_accessor :foreman
|
51
|
+
attr_accessor :gems
|
52
|
+
|
53
|
+
def initialize(gems = {})
|
54
|
+
super('project/Gemfile.erb')
|
55
|
+
@gems = gems
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class Procfile < Template
|
60
|
+
attr_reader :name, :command
|
61
|
+
|
62
|
+
def initialize(name, command)
|
63
|
+
super('project/Procfile.erb')
|
64
|
+
@name = name
|
65
|
+
@command = command
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
class BundledGem
|
70
|
+
def initialize(gem, version)
|
71
|
+
@gem = gem
|
72
|
+
@version = version
|
73
|
+
@output_path = File.expand_path("../../../test-vm/share/gems/#{gem}", __FILE__)
|
74
|
+
end
|
75
|
+
|
76
|
+
def generate
|
77
|
+
FileUtils.mkdir_p @output_path
|
78
|
+
FileUtils.chdir @output_path do
|
79
|
+
GemBinary.new(@gem, @version).write_to "bin/#{@gem}"
|
80
|
+
Gemspec.new(@gem, @version).write_to "#{@name}.gemspec"
|
81
|
+
|
82
|
+
`git init`
|
83
|
+
`git add --all`
|
84
|
+
`git commit -m 'Committed version #{@version}'`
|
85
|
+
`git tag #{@version}`
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
class Gemspec < Template
|
90
|
+
attr_reader :gem, :version
|
91
|
+
|
92
|
+
def initialize(gem, version)
|
93
|
+
super 'gem/gemspec.erb'
|
94
|
+
@gem = gem
|
95
|
+
@version = version
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
class GemBinary < Template
|
100
|
+
attr_reader :gem, :version
|
101
|
+
|
102
|
+
def initialize(name, version)
|
103
|
+
super 'gem/binary.erb'
|
104
|
+
@gem = name
|
105
|
+
@version = version
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class Project
|
111
|
+
def initialize(options = {})
|
112
|
+
@server = options[:server]
|
113
|
+
@gems = {}
|
114
|
+
FileUtils.rm_rf repository_path
|
115
|
+
git 'init'
|
116
|
+
write_and_commit_file 'Capfile', Capfile.new(self, options[:capfile] || {})
|
117
|
+
end
|
118
|
+
|
119
|
+
def name
|
120
|
+
@name ||= Faker::Name.first_name.downcase
|
121
|
+
end
|
122
|
+
|
123
|
+
def private_key_path
|
124
|
+
@server.private_key_path
|
125
|
+
end
|
126
|
+
|
127
|
+
def latest_version
|
128
|
+
committed_versions[0]
|
129
|
+
end
|
130
|
+
|
131
|
+
def previous_version
|
132
|
+
committed_versions[1]
|
133
|
+
end
|
134
|
+
|
135
|
+
def committed_versions
|
136
|
+
`cd #{repository_path} && git log --pretty=format:"%H"`.split("\n")
|
137
|
+
end
|
138
|
+
|
139
|
+
def write_and_commit_file(path, content = "")
|
140
|
+
full_path = File.join(repository_path, path)
|
141
|
+
FileUtils.mkdir_p File.dirname(full_path)
|
142
|
+
File.write(full_path, content)
|
143
|
+
commit_files(path)
|
144
|
+
end
|
145
|
+
|
146
|
+
def commit_files(*paths)
|
147
|
+
git "add #{paths.join(' ')}"
|
148
|
+
git "commit -m 'Added #{paths.join(' ')}'"
|
149
|
+
end
|
150
|
+
|
151
|
+
def repository_path(path = "")
|
152
|
+
File.join('test-vm/share/projects/', name, path)
|
153
|
+
end
|
154
|
+
|
155
|
+
def deployment_path(path = "")
|
156
|
+
File.join("/home/#{name}/apps/#{name}", path)
|
157
|
+
end
|
158
|
+
|
159
|
+
def deployed_version
|
160
|
+
(@server.run "cd #{deployment_path} && git rev-parse HEAD").strip
|
161
|
+
end
|
162
|
+
|
163
|
+
def run_cap(command)
|
164
|
+
`cap -l capistrano.log -f #{repository_path('Capfile')} #{command}`
|
165
|
+
raise "Exit code returned running 'cap #{command}'" if $?.exitstatus != 0
|
166
|
+
end
|
167
|
+
|
168
|
+
def run_on_server(cmd)
|
169
|
+
@server.run("cd #{deployment_path} && #{cmd}")
|
170
|
+
end
|
171
|
+
|
172
|
+
def git(command)
|
173
|
+
FileUtils.mkdir_p repository_path
|
174
|
+
FileUtils.chdir repository_path do
|
175
|
+
`git #{command}`
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
def gemfile
|
180
|
+
@gemfile ||= Gemfile.new
|
181
|
+
end
|
182
|
+
|
183
|
+
def add_gem_to_bundle(gem, version)
|
184
|
+
gemfile.gems[gem] = version
|
185
|
+
BundledGem.new(gem, version).generate
|
186
|
+
regenerate_bundle
|
187
|
+
end
|
188
|
+
|
189
|
+
def add_foreman_to_bundle
|
190
|
+
gemfile.foreman = true
|
191
|
+
regenerate_bundle
|
192
|
+
end
|
193
|
+
|
194
|
+
def regenerate_bundle
|
195
|
+
write_and_commit_file 'Gemfile', gemfile
|
196
|
+
# Nasty hack to generate a Gemfile.lock
|
197
|
+
@server.run "cd /recap/share/projects/#{name} && bundle install"
|
198
|
+
commit_files 'Gemfile.lock'
|
199
|
+
end
|
200
|
+
|
201
|
+
def add_command_to_procfile(name, command)
|
202
|
+
write_and_commit_file 'Procfile', Procfile.new(name, command)
|
203
|
+
end
|
204
|
+
|
205
|
+
def commit_changes
|
206
|
+
write_and_commit_file 'project-file', Faker::Lorem.sentence
|
207
|
+
end
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
World(ProjectSupport)
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'vagrant'
|
2
|
+
|
3
|
+
module ServerSupport
|
4
|
+
def server
|
5
|
+
@server ||= Server.instance
|
6
|
+
end
|
7
|
+
|
8
|
+
class Server
|
9
|
+
class << self
|
10
|
+
def instance
|
11
|
+
Server.new
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def private_key_path
|
16
|
+
env.default_private_key_path
|
17
|
+
end
|
18
|
+
|
19
|
+
def run(command, user = 'vagrant')
|
20
|
+
output = nil
|
21
|
+
env.primary_vm.channel.sudo("su - #{user} -c '#{command}'") do |type, data|
|
22
|
+
output = data if type == :stdout
|
23
|
+
end
|
24
|
+
output
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_user?(name)
|
28
|
+
test? "id -u #{name}"
|
29
|
+
end
|
30
|
+
|
31
|
+
def has_group?(name)
|
32
|
+
test? "id -g #{name}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def has_directory?(path)
|
36
|
+
test? "[ -d #{path} ]"
|
37
|
+
end
|
38
|
+
|
39
|
+
def has_file?(path)
|
40
|
+
test? "[ -f #{path} ]"
|
41
|
+
end
|
42
|
+
|
43
|
+
def test?(command)
|
44
|
+
env.primary_vm.channel.test(command)
|
45
|
+
end
|
46
|
+
|
47
|
+
def env
|
48
|
+
@env ||= Vagrant::Environment.new
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
World(ServerSupport)
|