Class: EY::Serverside::DeployBase

Inherits:
Task show all
Includes:
LoggedOutput
Defined in:
lib/engineyard-serverside/deploy.rb

Direct Known Subclasses

Deploy

Constant Summary

Constants included from Dataflow

Dataflow::UnificationError, Dataflow::VERSION

Instance Attribute Summary

Attributes inherited from Task

#config

Instance Method Summary collapse

Methods included from LoggedOutput

#debug, #info, logfile, logfile=, #logged_system, verbose=, verbose?, #verbose?

Methods inherited from Task

#initialize, #require_custom_tasks, #roles, #run, #sudo

Methods included from Dataflow

#barrier, #by_need, #flow, included, #local, #need_later, #unify

Constructor Details

This class inherits a constructor from EY::Serverside::Task

Instance Method Details

#bundleObject

task



131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/engineyard-serverside/deploy.rb', line 131

def bundle
  if File.exist?("#{c.release_path}/Gemfile")
    info "~> Gemfile detected, bundling gems"
    lockfile = File.join(c.release_path, "Gemfile.lock")

    bundler_installer = if File.exist?(lockfile)
                          get_bundler_installer(lockfile)
                        else
                          warn_about_missing_lockfile
                          bundler_09_installer(default_09_bundler)
                        end

    sudo "#{$0} _#{EY::Serverside::VERSION}_ install_bundler #{bundler_installer.version}"

    run "cd #{c.release_path} && bundle _#{bundler_installer.version}_ install #{bundler_installer.options}"
  end
end

#cached_deployObject



18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/engineyard-serverside/deploy.rb', line 18

def cached_deploy
  debug "Deploying app from cached copy at #{Time.now.asctime}"
  require_custom_tasks
  push_code

  info "~> Starting full deploy"
  copy_repository_cache

  with_failed_release_cleanup do
    create_revision_file
    run_with_callbacks(:bundle)
    symlink_configs
    conditionally_enable_maintenance_page
    run_with_callbacks(:migrate)
    callback(:before_symlink)
    symlink
  end

  callback(:after_symlink)
  run_with_callbacks(:restart)
  disable_maintenance_page

  cleanup_old_releases
  debug "Finished deploy at #{Time.now.asctime}"
rescue Exception
  debug "Finished failing to deploy at #{Time.now.asctime}"
  puts_deploy_failure
  raise
end

#callback(what) ⇒ Object



233
234
235
236
237
238
239
240
241
242
243
244
245
# File 'lib/engineyard-serverside/deploy.rb', line 233

def callback(what)
  @callbacks_reached ||= true
  if File.exist?("#{c.release_path}/deploy/#{what}.rb")
    run Escape.shell_command(base_callback_command_for(what)) do |server, cmd|
      per_instance_args = [
        '--current-roles', server.roles.join(' '),
        '--config', c.to_json,
      ]
      per_instance_args << '--current-name' << server.name.to_s if server.name
      cmd << " " << Escape.shell_command(per_instance_args)
    end
  end
end

#cleanup_old_releasesObject

task



150
151
152
153
154
155
# File 'lib/engineyard-serverside/deploy.rb', line 150

def cleanup_old_releases
  @cleanup_failed = true
  info "~> Cleaning up old releases"
  sudo "ls #{c.release_dir} | head -n -3 | xargs -I{} rm -rf #{c.release_dir}/{}"
  @cleanup_failed = false
end

#conditionally_enable_maintenance_pageObject



85
86
87
88
89
# File 'lib/engineyard-serverside/deploy.rb', line 85

def conditionally_enable_maintenance_page
  if c.migrate? || required_downtime_stack?
    enable_maintenance_page
  end
end

#copy_repository_cacheObject

task



189
190
191
192
193
194
195
# File 'lib/engineyard-serverside/deploy.rb', line 189

def copy_repository_cache
  info "~> Copying to #{c.release_path}"
  run("mkdir -p #{c.release_path} && rsync -aq #{c.exclusions} #{c.repository_cache}/ #{c.release_path}")

  info "~> Ensuring proper ownership"
  sudo("chown -R #{c.user}:#{c.group} #{c.deploy_to}")
end

#create_revision_fileObject



197
198
199
# File 'lib/engineyard-serverside/deploy.rb', line 197

def create_revision_file
  run create_revision_file_command
end

#deployObject

default task



12
13
14
15
16
# File 'lib/engineyard-serverside/deploy.rb', line 12

def deploy
  debug "Starting deploy at #{Time.now.asctime}"
  update_repository_cache
  cached_deploy
end

#disable_maintenance_pageObject



95
96
97
98
99
100
# File 'lib/engineyard-serverside/deploy.rb', line 95

def disable_maintenance_page
  @maintenance_up = false
  roles :app_master, :app, :solo do
    run "rm -f #{File.join(c.shared_path, "system", "maintenance.html")}"
  end
end

#enable_maintenance_pageObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/engineyard-serverside/deploy.rb', line 55

def enable_maintenance_page
  maintenance_page_candidates = [
    "public/maintenance.html.custom",
    "public/maintenance.html.tmp",
    "public/maintenance.html",
    "public/system/maintenance.html.default",
  ].map do |file|
    File.join(c.latest_release, file)
  end

  # this one is guaranteed to exist
  maintenance_page_candidates <<  File.expand_path(
    "default_maintenance_page.html",
    File.dirname(__FILE__)
    )

  # put in the maintenance page
  maintenance_file = maintenance_page_candidates.detect do |file|
    File.exists?(file)
  end

  @maintenance_up = true
  roles :app_master, :app, :solo do
    maint_page_dir = File.join(c.shared_path, "system")
    visible_maint_page = File.join(maint_page_dir, "maintenance.html")
    run Escape.shell_command(['mkdir', '-p', maint_page_dir])
    run Escape.shell_command(['cp', maintenance_file, visible_maint_page])
  end
end

#get_bundler_installer(lockfile) ⇒ Object



307
308
309
310
311
312
313
314
315
316
317
# File 'lib/engineyard-serverside/deploy.rb', line 307

def get_bundler_installer(lockfile)
  parser = LockfileParser.new(File.read(lockfile))
  case parser.lockfile_version
  when :bundler09
    bundler_09_installer(parser.bundler_version || default_09_bundler)
  when :bundler10
    bundler_10_installer(parser.bundler_version || default_10_bundler)
  else
    raise "Unknown lockfile version #{parser.lockfile_version}"
  end
end

#migrateObject

task



178
179
180
181
182
183
184
185
186
# File 'lib/engineyard-serverside/deploy.rb', line 178

def migrate
  return unless c.migrate?
  @migrations_reached = true
  roles :app_master, :solo do
    cmd = "cd #{c.release_path} && PATH=#{c.binstubs_path}:$PATH #{c.framework_envs} #{c.migration_command}"
    info "~> Migrating: #{cmd}"
    run(cmd)
  end
end

#push_codeObject

task



109
110
111
112
113
114
# File 'lib/engineyard-serverside/deploy.rb', line 109

def push_code
  info "~> Pushing code to all servers"
  barrier *(EY::Serverside::Server.all.map do |server|
    need_later { server.sync_directory(config.repository_cache) }
  end)
end

#required_downtime_stack?Boolean

Returns:

  • (Boolean)


91
92
93
# File 'lib/engineyard-serverside/deploy.rb', line 91

def required_downtime_stack?
  %w[ nginx_mongrel glassfish ].include? c.stack
end

#restartObject

task



117
118
119
120
121
122
123
124
# File 'lib/engineyard-serverside/deploy.rb', line 117

def restart
  @restart_failed = true
  info "~> Restarting app servers"
  roles :app_master, :app, :solo do
    run(restart_command)
  end
  @restart_failed = false
end

#restart_commandObject



126
127
128
# File 'lib/engineyard-serverside/deploy.rb', line 126

def restart_command
  "/engineyard/bin/app_#{c.app} deploy"
end

#restart_with_maintenance_pageObject



48
49
50
51
52
53
# File 'lib/engineyard-serverside/deploy.rb', line 48

def restart_with_maintenance_page
  require_custom_tasks
  conditionally_enable_maintenance_page
  restart
  disable_maintenance_page
end

#rollbackObject

task



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# File 'lib/engineyard-serverside/deploy.rb', line 158

def rollback
  if c.all_releases.size > 1
    rolled_back_release = c.latest_release
    c.release_path = c.previous_release(rolled_back_release)

    revision = File.read(File.join(c.release_path, 'REVISION')).strip
    info "~> Rolling back to previous release: #{short_log_message(revision)}"

    run_with_callbacks(:symlink)
    sudo "rm -rf #{rolled_back_release}"
    bundle
    info "~> Restarting with previous release"
    with_maintenance_page { run_with_callbacks(:restart) }
  else
    info "~> Already at oldest release, nothing to roll back to"
    exit(1)
  end
end

#run_with_callbacks(task) ⇒ Object



102
103
104
105
106
# File 'lib/engineyard-serverside/deploy.rb', line 102

def run_with_callbacks(task)
  callback("before_#{task}")
  send(task)
  callback("after_#{task}")
end

task



223
224
225
226
227
228
229
230
231
# File 'lib/engineyard-serverside/deploy.rb', line 223

def symlink(release_to_link=c.release_path)
  info "~> Symlinking code"
  run "rm -f #{c.current_path} && ln -nfs #{release_to_link} #{c.current_path} && chown -R #{c.user}:#{c.group} #{c.current_path}"
  @symlink_changed = true
rescue Exception
  sudo "rm -f #{c.current_path} && ln -nfs #{c.previous_release(release_to_link)} #{c.current_path} && chown -R #{c.user}:#{c.group} #{c.current_path}"
  @symlink_changed = false
  raise
end


201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/engineyard-serverside/deploy.rb', line 201

def symlink_configs(release_to_link=c.release_path)
  info "~> Symlinking configs"
  [ "chmod -R g+w #{release_to_link}",
    "rm -rf #{release_to_link}/log #{release_to_link}/public/system #{release_to_link}/tmp/pids",
    "mkdir -p #{release_to_link}/tmp",
    "ln -nfs #{c.shared_path}/log #{release_to_link}/log",
    "mkdir -p #{release_to_link}/public",
    "mkdir -p #{release_to_link}/config",
    "ln -nfs #{c.shared_path}/system #{release_to_link}/public/system",
    "ln -nfs #{c.shared_path}/pids #{release_to_link}/tmp/pids",
    "find #{c.shared_path}/config -type f -exec ln -s {} #{release_to_link}/config \\;",
    "ln -nfs #{c.shared_path}/config/database.yml #{release_to_link}/config/database.yml",
    "ln -nfs #{c.shared_path}/config/mongrel_cluster.yml #{release_to_link}/config/mongrel_cluster.yml",
  ].each do |cmd|
    run cmd
  end

  sudo "chown -R #{c.user}:#{c.group} #{release_to_link}"
  run "if [ -f \"#{c.shared_path}/config/newrelic.yml\" ]; then ln -nfs #{c.shared_path}/config/newrelic.yml #{release_to_link}/config/newrelic.yml; fi"
end