Class: Shred::Commands::Deploy

Inherits:
Base
  • Object
show all
Defined in:
lib/shred/commands/deploy.rb

Instance Attribute Summary

Attributes inherited from Base

#command_config, #command_name, #console

Instance Method Summary collapse

Methods inherited from Base

#initialize

Constructor Details

This class inherits a constructor from Shred::Commands::Base

Instance Method Details

#allObject



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/shred/commands/deploy.rb', line 29

def all
  invoke(:update_code_from_heroku)
  invoke(:detect_pending_migrations)
  if migration_count > 0
    maintenance_on
    scale_down
  end
  push_code_to_heroku
  if migration_count > 0
    snapshot_db
    migrate_db
    scale_up
    restart_app
    maintenance_off
  end
  send_notifications
end

#detect_pending_migrationsObject



64
65
66
67
68
69
70
71
72
# File 'lib/shred/commands/deploy.rb', line 64

def detect_pending_migrations
  if migration_count > 1
    console.say_ok("#{migration_count} pending database migrations detected")
  elsif migration_count == 1
    console.say_ok("#{migration_count} pending database migration detected")
  else
    console.say_ok("No pending database migrations detected")
  end
end

#maintenance_offObject



176
177
178
179
# File 'lib/shred/commands/deploy.rb', line 176

def maintenance_off
  heroku.app.update(heroku_app_name, maintenance:false)
  console.say_ok("Maintenance mode disabled")
end

#maintenance_onObject



75
76
77
78
# File 'lib/shred/commands/deploy.rb', line 75

def maintenance_on
  heroku.app.update(heroku_app_name, maintenance: true)
  console.say_ok("Maintenance mode enabled")
end

#migrate_dbObject



119
120
121
122
123
124
125
126
127
# File 'lib/shred/commands/deploy.rb', line 119

def migrate_db
  if migration_count > 0
    dyno = heroku.dyno.create(heroku_app_name, command: 'rake db:migrate db:seed')
    poll_one_off_dyno_until_done(dyno)
    console.say_ok("Pending database migrations applied")
  else
    console.say_ok("No pending database migrations to apply")
  end
end

#push_code_to_herokuObject



103
104
105
106
107
108
# File 'lib/shred/commands/deploy.rb', line 103

def push_code_to_heroku
  run_shell_command(ShellCommand.new(
    command_lines: "git push -f #{heroku_remote_name} #{branch}:master"
  ))
  console.say_ok("Pushed code to Heroku")
end

#restart_appObject



161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/shred/commands/deploy.rb', line 161

def restart_app
  dynos = heroku.dyno.list(heroku_app_name).find_all { |d| d['type'] == 'web' }
  dynos.each do |dyno|
    heroku.dyno.restart(heroku_app_name, dyno['id'])
  end
  if dynos.count > 1
    console.say_ok("Restarted #{dynos.count} web dynos")
  elsif dynos.count == 1
    console.say_ok("Restarted #{dynos.count} web dyno")
  else
    console.say_ok("No web dynos to restart")
  end
end

#scale_downObject



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/shred/commands/deploy.rb', line 81

def scale_down
  updates = process_counts.each_with_object([]) do |(process_type, count), m|
    m << {'process' => process_type.to_s, 'quantity' => 0} if count > 0
  end
  heroku.formation.batch_update(heroku_app_name, 'updates' => updates)
  updated = process_counts.map do |(process_type, count)|
    if count > 1
      "#{count} #{process_type} processes"
    elsif count == 1
      "#{count} #{process_type} process"
    else
      nil
    end
  end.compact
  if updated.any?
    console.say_ok("Scaled down #{updated.join(', ')}")
  else
    console.say_ok("No non-web processes to scale down")
  end
end

#scale_upObject



132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/shred/commands/deploy.rb', line 132

def scale_up
  updates = if options[:worker] || options[:clock]
    [:worker, :clock].each_with_object([]) do |process_type, m|
      m << {'process' => process_type.to_s, 'quantity' => options[process_type]}
    end
  else
    [:worker, :clock].each_with_object([]) do |process_type, m|
      count = process_counts[process_type] || 0
      m << {'process' => process_type.to_s, 'quantity' => count} if count > 0
    end
  end
  heroku.formation.batch_update(heroku_app_name, 'updates' => updates)
  updated = process_counts.map do |(process_type, count)|
    if count > 1
      "#{count} #{process_type} processes"
    elsif count == 1
      "#{count} #{process_type} process"
    else
      nil
    end
  end.compact
  if updated.any?
    console.say_ok("Scaled up #{updated.join(', ')}")
  else
    console.say_ok("No non-web processes to scale up")
  end
end

#send_notificationsObject



182
183
184
185
186
187
188
189
190
191
# File 'lib/shred/commands/deploy.rb', line 182

def send_notifications
  Array(cfg('notifications', required: false)).each do |(service, command)|
    command.
      gsub!(%r[{environment}], environment).
      gsub!(%r[{revision}], revision)
    dyno = heroku.dyno.create(heroku_app_name, command: command)
    poll_one_off_dyno_until_done(dyno)
    console.say_ok("Notification sent to #{service}")
  end
end

#snapshot_dbObject



111
112
113
114
115
116
# File 'lib/shred/commands/deploy.rb', line 111

def snapshot_db
  run_shell_command(ShellCommand.new(
    command_lines: "heroku pgbackups:capture --expire --app #{heroku_app_name}"
  ))
  console.say_ok("Database snapshot captured")
end

#update_code_from_herokuObject



48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/shred/commands/deploy.rb', line 48

def update_code_from_heroku
  exit_status = run_shell_command(ShellCommand.new(
    command_lines: "git remote | grep #{heroku_remote_name} > /dev/null"
  ))
  unless exit_status.success?
    run_shell_command(ShellCommand.new(
      command_lines: "git remote add #{heroku_remote_name} #{heroku_info['git_url']}"
    ))
  end
  run_shell_command(ShellCommand.new(
    command_lines: "git fetch #{heroku_remote_name}"
  ))
  console.say_ok("Updated code from #{heroku_app_name} Heroku app")
end