engineyard-serverside 2.0.0.pre4 → 2.0.0.pre5
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/engineyard-serverside/cli.rb +18 -1
- data/lib/engineyard-serverside/deploy.rb +14 -75
- data/lib/engineyard-serverside/maintenance.rb +112 -0
- data/lib/engineyard-serverside/paths.rb +30 -1
- data/lib/engineyard-serverside/servers.rb +5 -5
- data/lib/engineyard-serverside/task.rb +4 -21
- data/lib/engineyard-serverside/version.rb +1 -1
- data/spec/custom_deploy_spec.rb +25 -14
- data/spec/restart_spec.rb +3 -3
- metadata +5 -4
@@ -34,7 +34,25 @@ module EY
|
|
34
34
|
EY::Serverside::Deploy.new(servers, config, shell).send(default_task)
|
35
35
|
end
|
36
36
|
|
37
|
+
account_app_env_options
|
38
|
+
config_option
|
39
|
+
instances_options
|
40
|
+
verbose_option
|
41
|
+
desc "enable_maintenance", "Enable maintenance page (disables web access)"
|
42
|
+
def enable_maintenance
|
43
|
+
servers, config, shell = init_and_propagate(options, 'enable_maintenance')
|
44
|
+
EY::Serverside::Maintenance.new(servers, config, shell).manually_enable
|
45
|
+
end
|
37
46
|
|
47
|
+
account_app_env_options
|
48
|
+
config_option
|
49
|
+
instances_options
|
50
|
+
verbose_option
|
51
|
+
desc "disable_maintenance", "Disable maintenance page (enables web access)"
|
52
|
+
def disable_maintenance
|
53
|
+
servers, config, shell = init_and_propagate(options, 'disable_maintenance')
|
54
|
+
EY::Serverside::Maintenance.new(servers, config, shell).manually_disable
|
55
|
+
end
|
38
56
|
|
39
57
|
method_option :release_path, :type => :string,
|
40
58
|
:desc => "Value for #release_path in hooks (mostly for internal coordination)",
|
@@ -95,7 +113,6 @@ module EY
|
|
95
113
|
desc "restart", "Restart app servers, conditionally enabling maintenance page"
|
96
114
|
def restart
|
97
115
|
servers, config, shell = init_and_propagate(options, 'restart')
|
98
|
-
|
99
116
|
EY::Serverside::Deploy.new(servers, config, shell).restart_with_maintenance_page
|
100
117
|
end
|
101
118
|
|
@@ -3,6 +3,7 @@ require 'base64'
|
|
3
3
|
require 'fileutils'
|
4
4
|
require 'json'
|
5
5
|
require 'engineyard-serverside/rails_asset_support'
|
6
|
+
require 'engineyard-serverside/maintenance'
|
6
7
|
|
7
8
|
module EY
|
8
9
|
module Serverside
|
@@ -33,7 +34,7 @@ module EY
|
|
33
34
|
check_for_ey_config
|
34
35
|
symlink_configs
|
35
36
|
setup_sqlite3_if_necessary
|
36
|
-
|
37
|
+
enable_maintenance_page
|
37
38
|
run_with_callbacks(:migrate)
|
38
39
|
run_with_callbacks(:compile_assets) # defined in RailsAssetSupport
|
39
40
|
callback(:before_symlink)
|
@@ -44,7 +45,7 @@ module EY
|
|
44
45
|
|
45
46
|
callback(:after_symlink)
|
46
47
|
run_with_callbacks(:restart)
|
47
|
-
|
48
|
+
disable_maintenance_page
|
48
49
|
|
49
50
|
cleanup_old_releases
|
50
51
|
shell.status "Finished deploy at #{Time.now.asctime}"
|
@@ -117,79 +118,17 @@ To fix this problem, commit your Gemfile.lock to your repository and redeploy.
|
|
117
118
|
|
118
119
|
def restart_with_maintenance_page
|
119
120
|
require_custom_tasks
|
120
|
-
|
121
|
+
enable_maintenance_page
|
122
|
+
restart
|
123
|
+
disable_maintenance_page
|
121
124
|
end
|
122
125
|
|
123
126
|
def enable_maintenance_page
|
124
|
-
|
125
|
-
"public/maintenance.html.custom",
|
126
|
-
"public/maintenance.html.tmp",
|
127
|
-
"public/maintenance.html",
|
128
|
-
"public/system/maintenance.html.default",
|
129
|
-
].map do |file|
|
130
|
-
File.join(c.latest_release, file)
|
131
|
-
end
|
132
|
-
|
133
|
-
# this one is guaranteed to exist
|
134
|
-
maintenance_page_candidates << File.expand_path("default_maintenance_page.html", File.dirname(__FILE__))
|
135
|
-
|
136
|
-
# put in the maintenance page
|
137
|
-
maintenance_file = maintenance_page_candidates.detect do |file|
|
138
|
-
File.exists?(file)
|
139
|
-
end
|
140
|
-
|
141
|
-
shell.status "Enabling maintenance page."
|
142
|
-
@maintenance_up = true
|
143
|
-
roles :app_master, :app, :solo do
|
144
|
-
run Escape.shell_command(['mkdir', '-p', File.dirname(c.maintenance_page_enabled_path)])
|
145
|
-
run Escape.shell_command(['cp', maintenance_file, c.maintenance_page_enabled_path])
|
146
|
-
end
|
147
|
-
end
|
148
|
-
|
149
|
-
def conditionally_enable_maintenance_page
|
150
|
-
if c.enable_maintenance_page?
|
151
|
-
enable_maintenance_page
|
152
|
-
else
|
153
|
-
explain_not_enabling_maintenance_page
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
def explain_not_enabling_maintenance_page
|
158
|
-
if c.migrate?
|
159
|
-
if !c.maintenance_on_migrate? && !c.maintenance_on_restart?
|
160
|
-
shell.status "Skipping maintenance page. (maintenance_on_migrate is false in ey.yml)"
|
161
|
-
shell.notice "[Caution] No maintenance migrations must be non-destructive!"
|
162
|
-
shell.notice "Requests may be served during a partially migrated state."
|
163
|
-
end
|
164
|
-
else
|
165
|
-
if c.required_downtime_stack? && !c.maintenance_on_restart?
|
166
|
-
shell.status "Skipping maintenance page. (maintenance_on_restart is false in ey.yml, overriding recommended default)"
|
167
|
-
unless File.exist?(c.maintenance_page_enabled_path)
|
168
|
-
shell.warning <<-WARN
|
169
|
-
No maintenance page! Brief downtime may be possible during restart.
|
170
|
-
This application stack does not support no-downtime restarts.
|
171
|
-
WARN
|
172
|
-
end
|
173
|
-
elsif !c.required_downtime_stack?
|
174
|
-
shell.status "Skipping maintenance page. (no-downtime restarts supported)"
|
175
|
-
end
|
176
|
-
end
|
127
|
+
maintenance.conditionally_enable
|
177
128
|
end
|
178
129
|
|
179
130
|
def disable_maintenance_page
|
180
|
-
|
181
|
-
@maintenance_up = false
|
182
|
-
roles :app_master, :app, :solo do
|
183
|
-
run "rm -f #{c.maintenance_page_enabled_path}"
|
184
|
-
end
|
185
|
-
end
|
186
|
-
|
187
|
-
def conditionally_disable_maintenance_page
|
188
|
-
if c.disable_maintenance_page?
|
189
|
-
disable_maintenance_page
|
190
|
-
elsif File.exists?(c.maintenance_page_enabled_path)
|
191
|
-
shell.notice "[Attention] Maintenance page is still up.\nYou must remove it manually using `ey web enable`."
|
192
|
-
end
|
131
|
+
maintenance.conditionally_disable
|
193
132
|
end
|
194
133
|
|
195
134
|
def run_with_callbacks(task)
|
@@ -296,7 +235,9 @@ chmod 0700 #{path}
|
|
296
235
|
sudo "rm -rf #{rolled_back_release}"
|
297
236
|
bundle
|
298
237
|
shell.status "Restarting with previous release."
|
299
|
-
|
238
|
+
enable_maintenance_page
|
239
|
+
run_with_callbacks(:restart)
|
240
|
+
disable_maintenance_page
|
300
241
|
shell.status "Finished rollback at #{Time.now.asctime}"
|
301
242
|
rescue Exception
|
302
243
|
shell.status "Failed to rollback at #{Time.now.asctime}"
|
@@ -483,7 +424,7 @@ WRAP
|
|
483
424
|
def puts_deploy_failure
|
484
425
|
if @cleanup_failed
|
485
426
|
shell.notice "[Relax] Your site is running new code, but clean up of old deploys failed."
|
486
|
-
elsif
|
427
|
+
elsif maintenance.up?
|
487
428
|
message = "[Attention] Maintenance page still up, consider the following before removing:\n"
|
488
429
|
message << " * Deploy hooks ran. This might cause problems for reverting to old code.\n" if @callbacks_reached
|
489
430
|
message << " * Migrations ran. This might cause problems for reverting to old code.\n" if @migrations_reached
|
@@ -501,10 +442,8 @@ WRAP
|
|
501
442
|
end
|
502
443
|
end
|
503
444
|
|
504
|
-
def
|
505
|
-
|
506
|
-
yield if block_given?
|
507
|
-
conditionally_disable_maintenance_page
|
445
|
+
def maintenance
|
446
|
+
@maintenance ||= Maintenance.new(servers, config, shell)
|
508
447
|
end
|
509
448
|
|
510
449
|
def with_failed_release_cleanup
|
@@ -0,0 +1,112 @@
|
|
1
|
+
module EY
|
2
|
+
module Serverside
|
3
|
+
class Maintenance
|
4
|
+
|
5
|
+
def initialize(servers, config, shell)
|
6
|
+
@servers, @config, @shell = servers, config, shell
|
7
|
+
end
|
8
|
+
|
9
|
+
def exist?
|
10
|
+
enabled_maintenance_page_pathname.exist?
|
11
|
+
end
|
12
|
+
|
13
|
+
def up?
|
14
|
+
@up
|
15
|
+
end
|
16
|
+
|
17
|
+
def manually_enable
|
18
|
+
if paths.deployed?
|
19
|
+
enable
|
20
|
+
else
|
21
|
+
shell.fatal "Cannot enabled maintenance page. Application #{config.app_name} has never been deployed."
|
22
|
+
false
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def manually_disable
|
27
|
+
if paths.deployed?
|
28
|
+
disable
|
29
|
+
else
|
30
|
+
shell.fatal "Cannot enabled maintenance page. Application #{config.app_name} has never been deployed."
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def conditionally_enable
|
36
|
+
if config.enable_maintenance_page?
|
37
|
+
enable
|
38
|
+
else
|
39
|
+
explain_not_enabling
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def conditionally_disable
|
44
|
+
if config.disable_maintenance_page?
|
45
|
+
disable
|
46
|
+
elsif exist?
|
47
|
+
shell.notice "[Attention] Maintenance page is still up.\nYou must remove it manually using `ey web enable`."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
protected
|
52
|
+
|
53
|
+
attr_reader :config, :shell
|
54
|
+
|
55
|
+
def enable
|
56
|
+
shell.status "Enabling maintenance page."
|
57
|
+
@up = true
|
58
|
+
run "mkdir -p #{maintenance_page_dirname}"
|
59
|
+
run "cp #{source_path} #{enabled_maintenance_page_pathname}"
|
60
|
+
end
|
61
|
+
|
62
|
+
def disable
|
63
|
+
shell.status "Removing maintenance page."
|
64
|
+
@up = false
|
65
|
+
run "rm -f #{enabled_maintenance_page_pathname}"
|
66
|
+
end
|
67
|
+
|
68
|
+
def run(cmd)
|
69
|
+
@servers.roles(:app_master, :app, :solo).run(shell, cmd)
|
70
|
+
end
|
71
|
+
|
72
|
+
def paths
|
73
|
+
config.paths
|
74
|
+
end
|
75
|
+
|
76
|
+
def source_path
|
77
|
+
paths.maintenance_page_candidates.detect {|path| path.exist? }
|
78
|
+
end
|
79
|
+
|
80
|
+
def enabled_maintenance_page_pathname
|
81
|
+
paths.enabled_maintenance_page
|
82
|
+
end
|
83
|
+
|
84
|
+
def maintenance_page_dirname
|
85
|
+
enabled_maintenance_page_pathname.dirname
|
86
|
+
end
|
87
|
+
|
88
|
+
def explain_not_enabling
|
89
|
+
if config.migrate?
|
90
|
+
if !config.maintenance_on_migrate? && !config.maintenance_on_restart?
|
91
|
+
shell.status "Skipping maintenance page. (maintenance_on_migrate is false in ey.yml)"
|
92
|
+
shell.notice "[Caution] No maintenance migrations must be non-destructive!"
|
93
|
+
shell.notice "Requests may be served during a partially migrated state."
|
94
|
+
end
|
95
|
+
else
|
96
|
+
if config.required_downtime_stack? && !config.maintenance_on_restart?
|
97
|
+
shell.status "Skipping maintenance page. (maintenance_on_restart is false in ey.yml, overriding recommended default)"
|
98
|
+
unless exist?
|
99
|
+
shell.warning <<-WARN
|
100
|
+
No maintenance page! Brief downtime may be possible during restart.
|
101
|
+
This application stack does not support no-downtime restarts.
|
102
|
+
WARN
|
103
|
+
end
|
104
|
+
elsif !config.required_downtime_stack?
|
105
|
+
shell.status "Skipping maintenance page. (no-downtime restarts supported)"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -27,10 +27,23 @@ module EY
|
|
27
27
|
def ssh_identity_file() paths.ssh_identity.to_s end
|
28
28
|
end
|
29
29
|
|
30
|
+
# Maintenance page candidates in order of search preference.
|
31
|
+
MAINTENANCE_CANDIDATES = [
|
32
|
+
"public/maintenance.html.custom",
|
33
|
+
"public/maintenance.html.tmp",
|
34
|
+
"public/maintenance.html",
|
35
|
+
"public/system/maintenance.html.default",
|
36
|
+
]
|
37
|
+
|
38
|
+
# This one is guaranteed to exist.
|
39
|
+
DEFAULT_MAINTENANCE_PAGE = Pathname.new("default_maintenance_page.html").expand_path(File.dirname(__FILE__))
|
40
|
+
|
41
|
+
# Define methods that get us paths
|
30
42
|
def self.def_path(name, parts)
|
31
43
|
define_method(name.to_sym) { path(*parts) }
|
32
44
|
end
|
33
45
|
|
46
|
+
# Load a path given a root and more parts
|
34
47
|
def path(root, *parts)
|
35
48
|
send(root).join(*parts)
|
36
49
|
end
|
@@ -93,8 +106,24 @@ module EY
|
|
93
106
|
all_releases.last
|
94
107
|
end
|
95
108
|
|
109
|
+
def deployed?
|
110
|
+
!!latest_release
|
111
|
+
end
|
112
|
+
|
113
|
+
def maintenance_page_candidates
|
114
|
+
if latest_release
|
115
|
+
candidates = MAINTENANCE_CANDIDATES.map do |file|
|
116
|
+
path(:latest_release, file)
|
117
|
+
end
|
118
|
+
else
|
119
|
+
candidates = []
|
120
|
+
end
|
121
|
+
candidates << DEFAULT_MAINTENANCE_PAGE
|
122
|
+
candidates
|
123
|
+
end
|
124
|
+
|
96
125
|
def rollback
|
97
|
-
if previous_release
|
126
|
+
if deployed? && previous_release
|
98
127
|
self.class.new(@opts.dup.merge(:active_release => previous_release))
|
99
128
|
else
|
100
129
|
nil
|
@@ -63,18 +63,18 @@ module EY
|
|
63
63
|
end
|
64
64
|
|
65
65
|
# Run a command on this set of servers.
|
66
|
-
def run(cmd, &blk)
|
67
|
-
run_on_servers('sh -l -c', cmd, &blk)
|
66
|
+
def run(shell, cmd, &blk)
|
67
|
+
run_on_servers(shell, 'sh -l -c', cmd, &blk)
|
68
68
|
end
|
69
69
|
|
70
70
|
# Run a sudo command on this set of servers.
|
71
|
-
def sudo(cmd, &blk)
|
72
|
-
run_on_servers('sudo sh -l -c', cmd, &blk)
|
71
|
+
def sudo(shell, cmd, &blk)
|
72
|
+
run_on_servers(shell, 'sudo sh -l -c', cmd, &blk)
|
73
73
|
end
|
74
74
|
|
75
75
|
private
|
76
76
|
|
77
|
-
def run_on_servers(prefix, cmd, &block)
|
77
|
+
def run_on_servers(shell, prefix, cmd, &block)
|
78
78
|
commands = map do |server|
|
79
79
|
exec_cmd = server.command_on_server(prefix, cmd, &block)
|
80
80
|
proc { shell.logged_system(exec_cmd) }
|
@@ -59,31 +59,14 @@ module EY
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
def run(cmd, &
|
63
|
-
|
62
|
+
def run(cmd, &block)
|
63
|
+
servers.roles(@roles).run(shell, cmd, &block)
|
64
64
|
end
|
65
65
|
|
66
|
-
def sudo(cmd, &
|
67
|
-
|
66
|
+
def sudo(cmd, &block)
|
67
|
+
servers.roles(@roles).sudo(shell, cmd, &block)
|
68
68
|
end
|
69
69
|
|
70
|
-
private
|
71
|
-
|
72
|
-
def run_on_roles(prefix, cmd, &block)
|
73
|
-
servers = @servers.roles(@roles)
|
74
|
-
|
75
|
-
commands = servers.map do |server|
|
76
|
-
exec_cmd = server.command_on_server(prefix, cmd, &block)
|
77
|
-
proc { shell.logged_system(exec_cmd) }
|
78
|
-
end
|
79
|
-
|
80
|
-
futures = EY::Serverside::Future.call(commands)
|
81
|
-
|
82
|
-
unless EY::Serverside::Future.success?(futures)
|
83
|
-
failures = futures.select {|f| f.error? }.map {|f| f.inspect}.join("\n")
|
84
|
-
raise EY::Serverside::RemoteFailure.new(failures)
|
85
|
-
end
|
86
|
-
end
|
87
70
|
end
|
88
71
|
end
|
89
72
|
end
|
data/spec/custom_deploy_spec.rb
CHANGED
@@ -18,19 +18,19 @@ describe "the EY::Serverside::Deploy API" do
|
|
18
18
|
@call_order = []
|
19
19
|
end
|
20
20
|
|
21
|
-
def push_code()
|
22
|
-
def copy_repository_cache()
|
23
|
-
def create_revision_file()
|
24
|
-
def bundle()
|
25
|
-
def setup_services()
|
26
|
-
def symlink_configs()
|
27
|
-
def migrate()
|
28
|
-
def compile_assets()
|
29
|
-
def symlink()
|
30
|
-
def restart()
|
31
|
-
def cleanup_old_releases()
|
32
|
-
def
|
33
|
-
def disable_maintenance_page()
|
21
|
+
def push_code() @call_order << 'push_code' end
|
22
|
+
def copy_repository_cache() @call_order << 'copy_repository_cache' end
|
23
|
+
def create_revision_file() @call_order << 'create_revision_file' end
|
24
|
+
def bundle() @call_order << 'bundle' end
|
25
|
+
def setup_services() @call_order << 'setup_services' end
|
26
|
+
def symlink_configs() @call_order << 'symlink_configs' end
|
27
|
+
def migrate() @call_order << 'migrate' end
|
28
|
+
def compile_assets() @call_order << 'compile_assets' end
|
29
|
+
def symlink() @call_order << 'symlink' end
|
30
|
+
def restart() @call_order << 'restart' end
|
31
|
+
def cleanup_old_releases() @call_order << 'cleanup_old_releases' end
|
32
|
+
def enable_maintenance_page() @call_order << 'enable_maintenance_page' end
|
33
|
+
def disable_maintenance_page() @call_order << 'disable_maintenance_page' end
|
34
34
|
end
|
35
35
|
|
36
36
|
config = EY::Serverside::Deploy::Configuration.new({
|
@@ -40,6 +40,17 @@ describe "the EY::Serverside::Deploy API" do
|
|
40
40
|
|
41
41
|
td = TestDeploy.new(test_servers, config, test_shell)
|
42
42
|
td.deploy
|
43
|
+
|
44
|
+
############################# IMPORTANT ####################################
|
45
|
+
#
|
46
|
+
# Call order is referenced in the engineyard gem eydeploy.rb documentation.
|
47
|
+
#
|
48
|
+
# https://support.cloud.engineyard.com/entries/20996661-customize-your-deployment
|
49
|
+
#
|
50
|
+
# Changing call order or removing methods may adversely affect customers
|
51
|
+
# that are using eydeploy.rb and relying on this documentation.
|
52
|
+
#
|
53
|
+
############################################################################
|
43
54
|
td.call_order.should == %w(
|
44
55
|
push_code
|
45
56
|
copy_repository_cache
|
@@ -47,7 +58,7 @@ describe "the EY::Serverside::Deploy API" do
|
|
47
58
|
bundle
|
48
59
|
setup_services
|
49
60
|
symlink_configs
|
50
|
-
|
61
|
+
enable_maintenance_page
|
51
62
|
migrate
|
52
63
|
compile_assets
|
53
64
|
symlink
|
data/spec/restart_spec.rb
CHANGED
@@ -20,12 +20,12 @@ describe "EY::Serverside::Deploy#restart_with_maintenance_page" do
|
|
20
20
|
end
|
21
21
|
|
22
22
|
it "puts up the maintenance page if necessary, restarts, and takes down the maintenance page" do
|
23
|
-
config = EY::Serverside::Deploy::Configuration.new('app' => 'app_name')
|
23
|
+
config = EY::Serverside::Deploy::Configuration.new('deploy_to' => deploy_dir, 'app' => 'app_name')
|
24
24
|
deployer = TestRestartWithMaintenancePage.new(test_servers, config, test_shell)
|
25
25
|
deployer.restart_with_maintenance_page
|
26
26
|
deployer.call_order.should == %w(
|
27
27
|
require_custom_tasks
|
28
|
-
|
28
|
+
enable_maintenance_page
|
29
29
|
restart
|
30
30
|
disable_maintenance_page
|
31
31
|
)
|
@@ -35,7 +35,7 @@ end
|
|
35
35
|
describe "glassfish stack" do
|
36
36
|
|
37
37
|
it "requires a maintenance page" do
|
38
|
-
config = EY::Serverside::Deploy::Configuration.new(
|
38
|
+
config = EY::Serverside::Deploy::Configuration.new('deploy_to' => deploy_dir, 'app' => 'app_name', 'stack' => 'glassfish')
|
39
39
|
deployer = TestRestartDeploy.new(test_servers, config, test_shell)
|
40
40
|
deployer.restart_with_maintenance_page
|
41
41
|
deployer.call_order.should include('enable_maintenance_page')
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: engineyard-serverside
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 3919216497
|
5
5
|
prerelease: 6
|
6
6
|
segments:
|
7
7
|
- 2
|
8
8
|
- 0
|
9
9
|
- 0
|
10
10
|
- pre
|
11
|
-
-
|
12
|
-
version: 2.0.0.
|
11
|
+
- 5
|
12
|
+
version: 2.0.0.pre5
|
13
13
|
platform: ruby
|
14
14
|
authors:
|
15
15
|
- EY Cloud Team
|
@@ -17,7 +17,7 @@ autorequire:
|
|
17
17
|
bindir: bin
|
18
18
|
cert_chain: []
|
19
19
|
|
20
|
-
date: 2012-06-
|
20
|
+
date: 2012-06-14 00:00:00 Z
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
23
23
|
name: rspec
|
@@ -115,6 +115,7 @@ files:
|
|
115
115
|
- lib/engineyard-serverside/futures/celluloid.rb
|
116
116
|
- lib/engineyard-serverside/futures/dataflow.rb
|
117
117
|
- lib/engineyard-serverside/lockfile_parser.rb
|
118
|
+
- lib/engineyard-serverside/maintenance.rb
|
118
119
|
- lib/engineyard-serverside/paths.rb
|
119
120
|
- lib/engineyard-serverside/rails_asset_support.rb
|
120
121
|
- lib/engineyard-serverside/server.rb
|