hr_deploy 0.0.2 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,57 @@
1
+ module HR_Deploy
2
+
3
+ class Helper
4
+
5
+ private
6
+
7
+ HELP_STRING = <<-eos
8
+ Usage: hr_deploy [command]
9
+
10
+ The following commands are supported:
11
+
12
+ generate Generate a config file which specifies targets to deploy to.
13
+ Won't overwrite existing config unless confirmed.
14
+
15
+ deploy [target] Deploy to [target]. If no [target] is specified, deploy
16
+ to default target specified in config.
17
+ This command supports the following options:
18
+
19
+ --no-confirm Skip confirmations while deploying.
20
+ This does not affect the initial
21
+ confirmation that triggers the deploy itself.
22
+ Default behavior is to confirm actions.
23
+
24
+ --dry-run Don't actually execute commands, only show
25
+ which commands would get executed on a real
26
+ deploy. This skips all confirmations,
27
+ including the initial confirmation that
28
+ triggers the deploy itself.
29
+ Default behavior is to actually run commands.
30
+
31
+ --no-db-change Skip database related commands: backing up,
32
+ migrating and restarting.
33
+
34
+ version Show gem version.
35
+
36
+ help Show help.
37
+
38
+ Verbose documentation is at:
39
+ https://github.com/enthrops/hr_deploy/blob/master/README.md
40
+ eos
41
+
42
+ public
43
+
44
+ def show_help(args)
45
+ after_failed_parse = args.fetch(:failed_parse, false)
46
+
47
+ if after_failed_parse
48
+ puts 'Unknown command'
49
+ puts
50
+ end
51
+
52
+ puts HELP_STRING
53
+
54
+ exit 1 if after_failed_parse
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,102 @@
1
+ module HR_Deploy
2
+
3
+ class Parser
4
+
5
+ def parse_cmd_args
6
+ command = {}
7
+ command[:action] = nil
8
+ command[:options] = {}
9
+
10
+ cmd_options = ARGV
11
+
12
+ if cmd_options == [] || cmd_options == ['help']
13
+ command[:action] = :help
14
+ return command
15
+ end
16
+
17
+ if cmd_options == ['version']
18
+ command[:action] = :version
19
+ return command
20
+ end
21
+
22
+ if cmd_options == ['generate']
23
+ command[:action] = :generate
24
+ return command
25
+ end
26
+
27
+ if cmd_options.first == 'deploy'
28
+
29
+ deploy_args = cmd_options[1, cmd_options.length]
30
+
31
+ if deploy_args_valid?(deploy_args)
32
+
33
+ # Don't dry run by default
34
+ dry_run = deploy_args.delete('--dry-run')
35
+
36
+ # Confirm actions on deploys by default
37
+ # If '--dry-run' was provided, skip confirmations
38
+ confirm = !(deploy_args.delete('--no-confirm') || dry_run)
39
+
40
+ # Run database change actions by default
41
+ db_change = !deploy_args.delete('--no-db-change')
42
+
43
+ # If no target specified, it will be set to 'nil'
44
+ target_name = deploy_args.first
45
+
46
+ command[:action] = :deploy
47
+ command[:options][:target_name] = target_name
48
+ command[:options][:confirm] = confirm
49
+ command[:options][:dry_run] = dry_run
50
+ command[:options][:db_change] = db_change
51
+
52
+ return command
53
+ end
54
+ end
55
+
56
+ # Can't parse command
57
+ command[:action] = :help
58
+ command[:options][:failed_parse] = true
59
+ command
60
+ end
61
+
62
+ private
63
+
64
+ def deploy_args_valid?(args_to_deploy)
65
+
66
+ # We are going to mutate args later in the method
67
+ args_to_deploy = args_to_deploy.dup
68
+
69
+ # 0 to 3 additional options to 'deploy' command
70
+ # (target name, '--no-confirm', '--dry-run', '--no-db-change')
71
+ return false unless args_to_deploy.length <= 4
72
+
73
+ # Delete '--no-confirm' flag if it is present
74
+ if args_to_deploy.index('--no-confirm')
75
+ args_to_deploy.delete_at(args_to_deploy.index('--no-confirm'))
76
+ end
77
+
78
+ # Delete '--dry-run' flag if it is present
79
+ if args_to_deploy.index('--dry-run')
80
+ args_to_deploy.delete_at(args_to_deploy.index('--dry-run'))
81
+ end
82
+
83
+ # Delete '--no-db-change' flag if it is present
84
+ if args_to_deploy.index('--no-db-change')
85
+ args_to_deploy.delete_at(args_to_deploy.index('--no-db-change'))
86
+ end
87
+
88
+ # After we have removed '--no-confirm', '--dry-run' and '--no-db-change'
89
+ # we either have one param (target name) or nothing
90
+ return false unless args_to_deploy.length <= 1
91
+
92
+ # Explicit target should not be a command argument
93
+ if args_to_deploy.length == 1
94
+ if args_to_deploy.first.start_with?('--') || args_to_deploy.first.start_with?('-')
95
+ return false
96
+ end
97
+ end
98
+
99
+ true
100
+ end
101
+ end
102
+ end
@@ -3,53 +3,61 @@ module HR_Deploy
3
3
  class Target
4
4
 
5
5
  attr_reader :name
6
+ attr_reader :new_relic_disable_pinger_url
7
+ attr_reader :new_relic_enable_pinger_url
6
8
  attr_reader :description
7
- attr_reader :disable_pinger_url
8
- attr_reader :enable_pinger_url
9
9
 
10
- def backup_db?
11
- !!@backup_db
10
+ def initialize(args)
11
+
12
+ @name = args[:name]
13
+ @new_relic_disable_pinger_url = args[:new_relic_disable_pinger_url]
14
+ @new_relic_enable_pinger_url = args[:new_relic_enable_pinger_url]
15
+ @s3_asset_sync = args[:s3_asset_sync]
16
+ @default = args[:default]
17
+
18
+ # Use name for description, if no description given
19
+ @description = args[:description] || name
20
+
21
+ # Backup is off by default
22
+ @backup_db = args[:backup_db] == true
23
+
24
+ # Control maintenance mode is on by default
25
+ @maintenance = args[:maintenance] == false ? false : true
12
26
  end
13
27
 
14
- def default?
15
- !!@default
28
+ def pinging_interaction?
29
+ !!new_relic_disable_pinger_url
16
30
  end
17
31
 
18
32
  def requires_curl?
19
- !!disable_pinger_url
20
- end
21
-
22
- def requires_pinging_interaction?
23
- # If URL to disable pinging is set, we want to disable and enable pinging when deploying
24
- disable_pinger_url
25
- end
26
-
27
- def initialize(raw_target)
28
- target_name = raw_target.keys.first
29
- @name = target_name.to_s
30
-
31
- options = raw_target[target_name]
32
- # Target might have no options
33
- if options
34
- options.each do |option, value|
35
- case option
36
- when :description
37
- @description = value
38
- when :new_relic_disable_pinger_url
39
- @disable_pinger_url = value
40
- when :new_relic_enable_pinger_url
41
- @enable_pinger_url = value
42
- when :backup_db
43
- @backup_db = value
44
- when :default
45
- @default = value
46
- else
47
- raise "Unknown option: #{option}"
48
- end
49
- end
50
- end
51
-
52
- @description = name unless description
33
+ pinging_interaction?
34
+ end
35
+
36
+ def requires_rake?
37
+ s3_asset_sync?
38
+ end
39
+
40
+ def s3_asset_sync?
41
+ !!s3_asset_sync
53
42
  end
43
+
44
+ def backup_db?
45
+ !!backup_db
46
+ end
47
+
48
+ def maintenance_interaction?
49
+ !!maintenance
50
+ end
51
+
52
+ def default?
53
+ !!default
54
+ end
55
+
56
+ private
57
+
58
+ attr_reader :s3_asset_sync
59
+ attr_reader :maintenance
60
+ attr_reader :backup_db
61
+ attr_reader :default
54
62
  end
55
63
  end
@@ -0,0 +1,25 @@
1
+ require 'hr_deploy/tasks/task'
2
+
3
+ module HR_Deploy
4
+
5
+ class BackupDBTask < HR_Deploy::Task
6
+
7
+ def run
8
+ print_stage 'Backing up database...'
9
+
10
+ execute_system_command("heroku pgbackups:capture --expire --remote #{target.name}")
11
+
12
+ if dry_run? || !confirm?
13
+ self.success = true
14
+ return
15
+ end
16
+
17
+ if confirm_successful?('Database backed up?')
18
+ self.success = true
19
+ else
20
+ self.success = false
21
+ self.error = 'Could not back up database'
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,64 @@
1
+ require 'hr_deploy/tasks/task'
2
+ require 'uri'
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'json'
6
+
7
+ module HR_Deploy
8
+
9
+ class CheckHerokuTask < HR_Deploy::Task
10
+
11
+ def run
12
+ print_stage 'Checking Heroku status...'
13
+
14
+ if dry_run?
15
+ self.success = true
16
+ return
17
+ end
18
+
19
+ uri = URI.parse('https://status.heroku.com/api/v3/current-status')
20
+
21
+ http = Net::HTTP.new(uri.host, uri.port)
22
+ http.use_ssl = true
23
+
24
+ request = Net::HTTP::Get.new(uri.request_uri)
25
+
26
+ begin
27
+ response = http.request(request)
28
+
29
+ rescue
30
+ self.success = false
31
+ self.error = 'Could not fetch Heroku status'
32
+
33
+ else
34
+ if response.code == '200'
35
+
36
+ status = JSON.parse(response.body)
37
+ status = status['status'] if status
38
+
39
+ if status && status['Production'] && status['Development']
40
+
41
+ production_ok = status['Production'] == 'green'
42
+ development_ok = status['Development'] == 'green'
43
+
44
+ if production_ok && development_ok
45
+ print_success 'Heroku is operating correctly'
46
+ self.success = true
47
+ else
48
+ self.success = false
49
+ self.error = 'Heroku is having problems'
50
+ end
51
+ else
52
+
53
+ self.success = false
54
+ self.error = 'Could not parse Heroku status'
55
+ end
56
+
57
+ else
58
+ self.success = false
59
+ self.error = 'Could not fetch Heroku status'
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,29 @@
1
+ require 'hr_deploy/tasks/task'
2
+ require 'open-uri'
3
+
4
+ module HR_Deploy
5
+
6
+ class CheckNetworkTask < HR_Deploy::Task
7
+
8
+ def run
9
+ print_stage 'Checking Internet connection...'
10
+
11
+ if dry_run?
12
+ self.success = true
13
+ return
14
+ end
15
+
16
+ begin
17
+ open('http://www.google.com')
18
+
19
+ rescue
20
+ self.error = 'Not connected to the Internet'
21
+ self.success = false
22
+
23
+ else
24
+ print_success 'Internet connection is fine'
25
+ self.success = true
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ require 'hr_deploy/tasks/task'
2
+
3
+ module HR_Deploy
4
+
5
+ class CleanNewAssetsTask < HR_Deploy::Task
6
+
7
+ def run
8
+ print_stage 'Cleaning up new assets...'
9
+
10
+ execute_system_command('rake assets:clean')
11
+
12
+ if dry_run? || !confirm?
13
+ self.success = true
14
+ return
15
+ end
16
+
17
+ if confirm_successful?('New assets cleaned up?')
18
+ self.success = true
19
+ else
20
+ self.success = false
21
+ self.error = 'Could not clean up new assets'
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'hr_deploy/tasks/task'
2
+
3
+ module HR_Deploy
4
+
5
+ class CleanOldAssetsTask < HR_Deploy::Task
6
+
7
+ def run
8
+ print_stage 'Cleaning up old assets...'
9
+
10
+ execute_system_command('rake assets:clean')
11
+
12
+ if dry_run? || !confirm?
13
+ self.success = true
14
+ return
15
+ end
16
+
17
+ if confirm_successful?('Old assets cleaned up?')
18
+ self.success = true
19
+ else
20
+ self.success = false
21
+ self.error = 'Could not clean up old assets'
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require 'hr_deploy/tasks/task'
2
+
3
+ module HR_Deploy
4
+
5
+ class DisableMaintenanceTask < HR_Deploy::Task
6
+
7
+ def run
8
+ print_stage 'Disabling maintenance mode...'
9
+
10
+ execute_system_command("heroku maintenance:off --remote #{target.name}")
11
+
12
+ if dry_run? || !confirm?
13
+ self.success = true
14
+ return
15
+ end
16
+
17
+ if confirm_successful?('Maintenance mode disabled?')
18
+ self.success = true
19
+ else
20
+ self.success = false
21
+ self.error = 'Could not disable maintenance mode'
22
+ end
23
+ end
24
+ end
25
+ end