Class: EY::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::Task

Instance Method Details

#bundleObject

task



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/engineyard-serverside/deploy.rb', line 127

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} _#{VERSION}_ install_bundler #{bundler_installer.version}"

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

#cached_deployObject



17
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
# File 'lib/engineyard-serverside/deploy.rb', line 17

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
    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



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

def callback(what)
  @callbacks_reached ||= true
  if File.exist?("#{c.release_path}/deploy/#{what}.rb")
    base_command = [$0, "_#{VERSION}_", 'hook', what.to_s,
      '--app', config.app.to_s,
      '--release-path', config.release_path.to_s,
    ]

    run Escape.shell_command(base_command) do |server, cmd|
      per_instance_args = [
        '--framework-env', c.environment.to_s,
        '--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



146
147
148
149
150
151
# File 'lib/engineyard-serverside/deploy.rb', line 146

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



77
78
79
80
81
# File 'lib/engineyard-serverside/deploy.rb', line 77

def conditionally_enable_maintenance_page
  if c.migrate? || c.stack == "nginx_mongrel"
    enable_maintenance_page
  end
end

#copy_repository_cacheObject

task



185
186
187
188
189
190
191
# File 'lib/engineyard-serverside/deploy.rb', line 185

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



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

def create_revision_file
  run create_revision_file_command
end

#deployObject

default task



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

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

#disable_maintenance_pageObject



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

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



47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/engineyard-serverside/deploy.rb', line 47

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



295
296
297
298
299
300
301
302
303
304
305
# File 'lib/engineyard-serverside/deploy.rb', line 295

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



174
175
176
177
178
179
180
181
182
# File 'lib/engineyard-serverside/deploy.rb', line 174

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



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

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

#restartObject

task



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# File 'lib/engineyard-serverside/deploy.rb', line 105

def restart
  @restart_failed = true
  info "~> Restarting app servers"
  roles :app_master, :app, :solo do
    restart_command = case c.stack
    when "nginx_unicorn"
      pidfile = "/var/run/engineyard/unicorn_#{c.app}.pid"
      condition = "[ -e #{pidfile} ] && [ ! -d /proc/`cat #{pidfile}` ]"
      run("if #{condition}; then rm -f #{pidfile}; fi")
      run("/engineyard/bin/app_#{c.app} deploy")
    when "nginx_mongrel"
      sudo("monit restart all -g #{c.app}")
    when "nginx_passenger"
      run("touch #{c.current_path}/tmp/restart.txt")
    else
      raise "Unknown stack #{c.stack}; restart failed!"
    end
  end
  @restart_failed = false
end

#rollbackObject

task



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
# File 'lib/engineyard-serverside/deploy.rb', line 154

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



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

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

task



218
219
220
221
222
223
224
225
226
# File 'lib/engineyard-serverside/deploy.rb', line 218

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


197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
# File 'lib/engineyard-serverside/deploy.rb', line 197

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",
    "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