hr_deploy 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 269384c663c1693b844f227cbd8219d1e9e0ddaf
4
- data.tar.gz: 3f9c00a090f410433ea4949950032515eeaa7f76
3
+ metadata.gz: bce644d0caddde4560e698e8995029f32da4976d
4
+ data.tar.gz: aeb328b6b9cec1f7a210f95b4c9fb9b4b6069b3b
5
5
  SHA512:
6
- metadata.gz: d1a59907ccd34338cd0abf9fbaa37b57ad4368207e318918a494743718ad6a4910888923037a495d464bbc1a49654413fcd255003566caecac853928090e6a65
7
- data.tar.gz: b55cfd0cf957c4f195fb3511326dacaa3c2d67bb266a5d78020268b69d54b75670ca775e76d1e7d5aaaf30f8a1eabd4e37463052d45f774809c0391cb1f2671e
6
+ metadata.gz: 13eb8c7a328d864f9e8db2bb7827e4c59ccc0e5be946232c4131320c4fee275c472c37a89db5bf7be6f3b89bc32d700ff086dce86563e8eff0d19b81f7679d29
7
+ data.tar.gz: f8cca7377f6ffa1ad386a96acd9a859c1d76f8ddb1ba0ca1ac7fbf547c0b7e59bcfa5aee0041d8737f197ed741d26f8eb38830602b16a2c6b4fcb6660aadaed8
@@ -60,6 +60,13 @@ module HR_Deploy
60
60
  # when you execute 'hr_deploy deploy' without arguments.
61
61
  :default: true
62
62
 
63
+ # URL to open after deploy is complete. If a 503 (maintenance) or no
64
+ # response is returned for 5 seconds, URL will be retried for a total
65
+ # time of up to a minute. If this is set, user perceived downtime will
66
+ # be calculated. Wrap in quotes and provide the protocol, e.g. 'http://'
67
+ # or 'https://'. Optional, delete to skip opening the app after the deploy.
68
+ :app_url: 'http://app'
69
+
63
70
  # Example of another target, feel free to delete or modify.
64
71
  - :production:
65
72
  :description: Production
@@ -236,6 +243,12 @@ module HR_Deploy
236
243
  return false
237
244
  end
238
245
 
246
+ when :app_url
247
+ unless value.instance_of?(String)
248
+ self.error = 'App URL should be a string'
249
+ return false
250
+ end
251
+
239
252
  else
240
253
  self.error = "Option unknown: #{option}"
241
254
  return false
@@ -274,7 +287,8 @@ module HR_Deploy
274
287
  backup_db: options[:backup_db],
275
288
  maintenance: options[:maintenance],
276
289
  default: options[:default],
277
- s3_asset_sync: options[:s3_asset_sync])
290
+ s3_asset_sync: options[:s3_asset_sync],
291
+ app_url: options[:app_url])
278
292
  else
279
293
  # Only target name was given, 'options' hash is nil
280
294
  HR_Deploy::Target.new(name: name)
@@ -13,6 +13,7 @@ require 'hr_deploy/tasks/precompile_assets_task.rb'
13
13
  require 'hr_deploy/tasks/push_code_task.rb'
14
14
  require 'hr_deploy/tasks/migrate_db_task.rb'
15
15
  require 'hr_deploy/tasks/restart_task.rb'
16
+ require 'hr_deploy/tasks/open_app_task.rb'
16
17
 
17
18
  module HR_Deploy
18
19
 
@@ -196,6 +197,10 @@ module HR_Deploy
196
197
  tasks_to_run << HR_Deploy::DisableMaintenanceTask.new(target: target, confirm: confirm, dry_run: dry_run)
197
198
  end
198
199
 
200
+ if target.app_url
201
+ tasks_to_run << HR_Deploy::OpenAppTask.new(target: target, dry_run: dry_run)
202
+ end
203
+
199
204
  if target.pinging_interaction?
200
205
  tasks_to_run << HR_Deploy::EnablePingerTask.new(target: target, confirm: confirm, dry_run: dry_run)
201
206
  end
@@ -249,14 +254,36 @@ module HR_Deploy
249
254
  def deploy_succeeded
250
255
  if dry_run
251
256
  print_deploy_successful 'Dry run complete'
257
+
252
258
  else
253
- print_deploy_successful "Deploy complete in #{(Time.now - start_time).round} seconds"
259
+ print_deploy_successful "Deploy complete in #{human_time(Time.now - start_time)}"
260
+
261
+ downtime = calculate_downtime
262
+ print_deploy_successful "User perceived downtime was #{human_time(downtime)}" if downtime
254
263
  end
255
264
 
256
265
  # Execution is finished
257
266
  exit 0
258
267
  end
259
268
 
269
+ def calculate_downtime
270
+ open_app = finished_tasks.find { |task| task.class == HR_Deploy::OpenAppTask }
271
+
272
+ # Can't calculate user perceived downtime accurately if app was not opened
273
+ return nil unless open_app
274
+
275
+ enable_maintenance = finished_tasks.find { |task| task.class == HR_Deploy::EnableMaintenanceTask }
276
+ push_code = finished_tasks.find { |task| task.class == HR_Deploy::PushCodeTask }
277
+
278
+ if enable_maintenance
279
+ starting_time = enable_maintenance.start_time
280
+ else
281
+ starting_time = push_code.start_time
282
+ end
283
+
284
+ open_app.end_time - starting_time
285
+ end
286
+
260
287
  def application_state(failed_task)
261
288
 
262
289
  did_not_change = 'Application state did not change'
@@ -286,6 +313,8 @@ module HR_Deploy
286
313
  unknown
287
314
  when HR_Deploy::DisableMaintenanceTask
288
315
  deployed
316
+ when HR_Deploy::OpenAppTask
317
+ deployed
289
318
  when HR_Deploy::EnablePingerTask
290
319
  deployed
291
320
  when HR_Deploy::CleanNewAssetsTask
@@ -336,5 +365,41 @@ module HR_Deploy
336
365
  def print_app_status(msg)
337
366
  puts msg.yellow
338
367
  end
368
+
369
+ def human_time(seconds)
370
+ seconds = seconds.round
371
+ minutes = seconds / 60
372
+ seconds = seconds % 60
373
+
374
+ minute_string = nil
375
+ second_string = nil
376
+
377
+ unless minutes == 0
378
+ if minutes == 1
379
+ minute_string = 'minute'
380
+ else
381
+ minute_string = 'minutes'
382
+ end
383
+ end
384
+
385
+ unless seconds == 0
386
+ if seconds == 1
387
+ second_string = 'second'
388
+ else
389
+ second_string = 'seconds'
390
+ end
391
+ end
392
+
393
+ result = ''
394
+ result += "#{minutes} #{minute_string} " unless minutes == 0
395
+ result += "#{seconds} #{second_string}" unless seconds == 0
396
+ result.strip!
397
+
398
+ if result == ''
399
+ '0 seconds'
400
+ else
401
+ result
402
+ end
403
+ end
339
404
  end
340
405
  end
@@ -6,6 +6,7 @@ module HR_Deploy
6
6
  attr_reader :new_relic_disable_pinger_url
7
7
  attr_reader :new_relic_enable_pinger_url
8
8
  attr_reader :description
9
+ attr_reader :app_url
9
10
 
10
11
  def initialize(args)
11
12
 
@@ -14,6 +15,7 @@ module HR_Deploy
14
15
  @new_relic_enable_pinger_url = args[:new_relic_enable_pinger_url]
15
16
  @s3_asset_sync = args[:s3_asset_sync]
16
17
  @default = args[:default]
18
+ @app_url = args[:app_url]
17
19
 
18
20
  # Use name for description, if no description given
19
21
  @description = args[:description] || name
@@ -7,6 +7,7 @@ module HR_Deploy
7
7
  def run
8
8
  print_stage 'Enabling maintenance mode...'
9
9
 
10
+ set_start_time
10
11
  execute_system_command("heroku maintenance:on --remote #{target.name}")
11
12
 
12
13
  if dry_run? || !confirm?
@@ -0,0 +1,81 @@
1
+ require 'hr_deploy/tasks/task'
2
+ require 'timeout'
3
+ require 'net/http'
4
+
5
+ module HR_Deploy
6
+
7
+ class OpenAppTask < HR_Deploy::Task
8
+
9
+ ONE_TRY_TIME = 5
10
+ TOTAL_TRY_TIME = 60
11
+
12
+ def run
13
+ print_stage 'Opening app...'
14
+ open_command = "heroku open --remote #{target.name}"
15
+
16
+ if dry_run?
17
+ execute_system_command(open_command)
18
+ self.success = true
19
+ return
20
+ end
21
+
22
+ ending_time = Time.now + HR_Deploy::OpenAppTask::TOTAL_TRY_TIME
23
+
24
+ until success == true || success == false
25
+ status = try_status
26
+
27
+ if status == :ok
28
+ execute_system_command(open_command)
29
+ set_end_time
30
+ self.success = true
31
+
32
+ elsif status == :fail || (status == :retry && Time.now > ending_time)
33
+
34
+ self.success = false
35
+ self.error = "Could not open app\n" +
36
+ "To open manually: #{open_command}"
37
+ end
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ # :ok -> app returned a status other than 503 before timeout
44
+ # :retry -> app did not return a status before timeout or returned 503
45
+ # :fail -> an error occurred
46
+ def try_status
47
+ starting_time = Time.now
48
+
49
+ begin
50
+ Timeout::timeout(HR_Deploy::OpenAppTask::ONE_TRY_TIME) do
51
+
52
+ url = target.app_url
53
+ unless url.start_with?('https://') || url.start_with?('http://')
54
+ url = 'http://' + url
55
+ end
56
+
57
+ uri = URI.parse(url)
58
+ http = Net::HTTP.new(uri.host, uri.port)
59
+
60
+ if url.start_with?('https://')
61
+ http.use_ssl = true
62
+ end
63
+
64
+ request = Net::HTTP::Get.new(uri.request_uri)
65
+ response = http.request(request)
66
+
67
+ if response.code == '503'
68
+ sleep(HR_Deploy::OpenAppTask::ONE_TRY_TIME - (starting_time - Time.now))
69
+ :retry
70
+ else
71
+ :ok
72
+ end
73
+ end
74
+ rescue Timeout::Error
75
+ :retry
76
+ rescue
77
+ :fail
78
+ end
79
+ end
80
+ end
81
+ end
@@ -7,6 +7,7 @@ module HR_Deploy
7
7
  def run
8
8
  print_stage 'Pushing new code...'
9
9
 
10
+ set_start_time
10
11
  execute_system_command("git push #{target.name} master")
11
12
 
12
13
  if dry_run? || !confirm?
@@ -6,6 +6,8 @@ module HR_Deploy
6
6
  class Task
7
7
 
8
8
  attr_reader :error
9
+ attr_reader :start_time
10
+ attr_reader :end_time
9
11
 
10
12
  def initialize(args = {})
11
13
  @target = args.fetch(:target, nil)
@@ -13,6 +15,8 @@ module HR_Deploy
13
15
  @dry_run = args.fetch(:dry_run, false)
14
16
  @success = nil
15
17
  @error = nil
18
+ @start_time = nil
19
+ @end_time = nil
16
20
  end
17
21
 
18
22
  def successful?
@@ -28,8 +32,18 @@ module HR_Deploy
28
32
 
29
33
  attr_reader :target
30
34
  attr_writer :error
35
+ attr_writer :start_time
36
+ attr_writer :end_time
31
37
  attr_accessor :success
32
38
 
39
+ def set_start_time
40
+ self.start_time = Time.now
41
+ end
42
+
43
+ def set_end_time
44
+ self.end_time = Time.now
45
+ end
46
+
33
47
  def confirm?
34
48
  !!@confirm
35
49
  end
@@ -64,7 +78,7 @@ module HR_Deploy
64
78
 
65
79
  def execute_system_command(cmd)
66
80
  if dry_run?
67
- puts "Executing command: #{cmd}"
81
+ puts cmd
68
82
  else
69
83
  system(cmd)
70
84
  end
@@ -1,3 +1,3 @@
1
1
  module HR_Deploy
2
- VERSION = '0.0.6'
2
+ VERSION = '0.0.7'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hr_deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dmitry Gubitskiy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-06-30 00:00:00.000000000 Z
11
+ date: 2013-07-01 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Easily deploy your Rails apps to Heroku with one command, automatically
14
14
  taking care of things such as checking current Heroku status, enabling maintenance
@@ -40,6 +40,7 @@ files:
40
40
  - lib/hr_deploy/tasks/push_code_task.rb
41
41
  - lib/hr_deploy/tasks/migrate_db_task.rb
42
42
  - lib/hr_deploy/tasks/restart_task.rb
43
+ - lib/hr_deploy/tasks/open_app_task.rb
43
44
  - lib/hr_deploy/version.rb
44
45
  - bin/hr_deploy
45
46
  homepage: https://github.com/enthrops/hr_deploy