recap 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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)
|