deployhq 2.0.4 → 2.2.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2960dfa1052e55bb3174a4f45ffe857918dfd624016c1536215ceeccd5ff541f
4
- data.tar.gz: ac02d56e4afb69f993453f470626f5abaa2c8229e7e24213d0d73d8449d453b6
3
+ metadata.gz: 49b0d4dee17978ab6c1930da674f450c2a39f510e7ea16c7e780071ce4d01645
4
+ data.tar.gz: 605d88bb4aab28b84f66b9924dfcce27321b1c483498fd932600f29058e77de6
5
5
  SHA512:
6
- metadata.gz: 5344ddc86c626f64a4b3a5c943c07ec92f9a6861eb06c012a810ea384983d1061ab4a8d9e38a15cf4b006c6a62cebbc2f47027c69bee48b525cc66b16853a307
7
- data.tar.gz: 664c4a3d67eb79addcf3b880520a70261c1665f1b41251d94e96bd04350fa7443b04c4d79c6d7998d08cc3a855c8867ba3cfe5c40bc04f9f1b5cfb134c855904
6
+ metadata.gz: 2475fd2e69653132c6d19b41de8f1c3a842dca009822965ec7e2d5b81c9a57200d3aeab53cf7746a98d3c19a111f127d7749d5611e80ae5dcdb309253f073f10
7
+ data.tar.gz: d4239817c17165c41324afe6e895745e6062a55fdb6f9800850fab675636ef59038b94d5872eccc6d74f0d9bb3c611ffc394bac67c75affeadf2155dc89e23ef
data/bin/deployhq CHANGED
@@ -1,5 +1,7 @@
1
1
  #!/usr/bin/env ruby
2
- libdir = File.expand_path('../../lib', __FILE__)
2
+ # frozen_string_literal: true
3
+
4
+ libdir = File.expand_path('../lib', __dir__)
3
5
  $LOAD_PATH.unshift(libdir)
4
6
 
5
7
  require 'deploy/cli'
@@ -1,9 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
4
  class CLI
5
+
3
6
  class DeploymentProgressOutput
7
+
4
8
  SERVER_TAG_COLOURS = %w[32 33 34 35 36].cycle
5
9
 
6
- attr_reader :deployment, :step_index, :server_tags
10
+ attr_reader :deployment
11
+ attr_reader :step_index
12
+ attr_reader :server_tags
7
13
 
8
14
  def initialize(deployment)
9
15
  @deployment = deployment
@@ -26,13 +32,14 @@ module Deploy
26
32
 
27
33
  private
28
34
 
35
+ # rubocop:disable Metrics/AbcSize
29
36
  def handle_log_entry(payload)
30
37
  step = step_index[payload['step']]
31
38
  server_tag = server_tags[step.server]
32
39
 
33
- line = "\n"
34
- line << server_tag if server_tag
35
- line << payload['message']
40
+ lines = ["\n"]
41
+ lines << server_tag
42
+ lines << payload['message']
36
43
 
37
44
  if payload['detail']
38
45
  padding_width = 0
@@ -40,22 +47,25 @@ module Deploy
40
47
  padding = ' ' * padding_width
41
48
 
42
49
  payload['detail'].split("\n").each do |detail_line|
43
- line << "\n#{padding}| #{detail_line}"
50
+ lines << "\n#{padding}| #{detail_line}"
44
51
  end
45
52
  end
46
53
 
47
- STDOUT.print line
54
+ $stdout.print lines.join
48
55
  end
56
+ # rubocop:enable Metrics/AbcSize
49
57
 
50
58
  def handle_status_change(payload)
51
59
  if payload['status'] == 'completed'
52
- STDOUT.print "\nDeployment has finished successfully!\n"
60
+ $stdout.print "\nDeployment has finished successfully!\n"
53
61
  elsif payload['status'] == 'failed'
54
- STDOUT.print "\nDeployment has failed!\n"
62
+ $stdout.print "\nDeployment has failed!\n"
55
63
  end
56
64
 
57
65
  throw(:finished) if %w[completed failed].include?(payload['status'])
58
66
  end
67
+
59
68
  end
69
+
60
70
  end
61
71
  end
@@ -1,14 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'websocket-eventmachine-client'
2
4
  require 'logger'
3
5
 
4
6
  module Deploy
5
7
  class CLI
8
+
6
9
  # Manages a connection and associated subscriptions to DeployHQ's websocket
7
10
  class WebsocketClient
11
+
8
12
  attr_reader :subscriptions
9
13
 
10
14
  class Subscription
11
- attr_reader :exchange, :routing_key
15
+
16
+ attr_reader :exchange
17
+ attr_reader :routing_key
12
18
 
13
19
  def initialize(exchange, routing_key)
14
20
  @exchange = exchange
@@ -36,6 +42,7 @@ module Deploy
36
42
  def subscribed!
37
43
  @subscribed = true
38
44
  end
45
+
39
46
  end
40
47
 
41
48
  def initialize
@@ -51,10 +58,10 @@ module Deploy
51
58
  catch(:finished) do
52
59
  EM.run do
53
60
  connection.onopen do
54
- logger.info "connected"
61
+ logger.info 'connected'
55
62
  end
56
63
 
57
- connection.onmessage do |msg, type|
64
+ connection.onmessage do |msg, _type|
58
65
  receive(msg)
59
66
  end
60
67
 
@@ -68,7 +75,7 @@ module Deploy
68
75
 
69
76
  private
70
77
 
71
- def dispatch(event, payload, mq = nil)
78
+ def dispatch(event, payload, rmq = nil)
72
79
  case event
73
80
  when 'Welcome'
74
81
  authenticate
@@ -79,7 +86,7 @@ module Deploy
79
86
  when 'Error', 'InternalError'
80
87
  websocket_error(payload)
81
88
  else
82
- subscription_event(event, payload, mq) if mq
89
+ subscription_event(event, payload, rmq) if rmq
83
90
  end
84
91
  end
85
92
 
@@ -88,7 +95,7 @@ module Deploy
88
95
  end
89
96
 
90
97
  def request_subscriptions
91
- subscriptions.each do |_key, subscription|
98
+ subscriptions.each_value do |subscription|
92
99
  send('Subscribe', exchange: subscription.exchange, routing_key: subscription.routing_key)
93
100
  end
94
101
  end
@@ -96,17 +103,17 @@ module Deploy
96
103
  def successful_subscription(payload)
97
104
  key = subscription_key(payload['exchange'], payload['routing_key'])
98
105
  subscription = subscriptions[key]
99
- subscription.subscribed! if subscription
106
+ subscription&.subscribed!
100
107
  end
101
108
 
102
109
  def websocket_error(payload)
103
110
  raise Deploy::Errors::WebsocketError, payload['error']
104
111
  end
105
112
 
106
- def subscription_event(event, payload, mq)
107
- key = subscription_key(mq["e"], mq["rk"])
113
+ def subscription_event(event, payload, rmq)
114
+ key = subscription_key(rmq['e'], rmq['rk'])
108
115
  subscription = subscriptions[key]
109
- subscription.dispatch(event, payload) if subscription
116
+ subscription&.dispatch(event, payload)
110
117
  end
111
118
 
112
119
  def receive(msg)
@@ -131,7 +138,7 @@ module Deploy
131
138
  end
132
139
 
133
140
  def logger
134
- @logger ||= Logger.new(STDOUT)
141
+ @logger ||= Logger.new($stdout)
135
142
  @logger.level = Logger::ERROR
136
143
  @logger
137
144
  end
@@ -139,6 +146,8 @@ module Deploy
139
146
  def subscription_key(exchange, routing_key)
140
147
  [exchange, routing_key].join('-')
141
148
  end
149
+
142
150
  end
151
+
143
152
  end
144
153
  end
data/lib/deploy/cli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'optparse'
2
4
  require 'highline/import'
3
5
 
@@ -5,43 +7,55 @@ require 'deploy'
5
7
  require 'deploy/cli/websocket_client'
6
8
  require 'deploy/cli/deployment_progress_output'
7
9
 
8
- HighLine.colorize_strings
10
+ OptionsStruct = Struct.new(:config_file, :project, :config_files_deployment)
9
11
 
12
+ # rubocop:disable Metrics/ClassLength
13
+ # rubocop:disable Metrics/AbcSize
14
+ # rubocop:disable Metrics/CyclomaticComplexity
15
+ # rubocop:disable Metrics/MethodLength
16
+ # rubocop:disable Metrics/PerceivedComplexity
10
17
  module Deploy
11
18
  class CLI
19
+
12
20
  ## Constants for formatting output
13
- PROTOCOL_NAME = {:ssh => "SSH/SFTP", :ftp => "FTP", :s3 => "Amazon S3", :rackspace => "Rackspace CloudFiles"}
21
+ PROTOCOL_NAME = { ssh: 'SSH/SFTP', ftp: 'FTP', s3: 'Amazon S3', rackspace: 'Rackspace CloudFiles' }.freeze
14
22
 
15
23
  class << self
24
+
16
25
  def invoke(args)
17
- @options = OpenStruct.new
26
+ @options = OptionsStruct.new
18
27
 
19
- parser = OptionParser.new do |opts|
20
- opts.banner = "Usage: deployhq [options] command"
21
- opts.separator ""
22
- opts.separator "Commands:"
28
+ parser = OptionParser.new do |opts| # rubocop:disable Metrics/BlockLength
29
+ opts.banner = 'Usage: deployhq [options] command'
30
+ opts.separator ''
31
+ opts.separator 'Commands:'
23
32
  opts.separator "deploy\t\t Start a new deployment"
24
33
  opts.separator "servers\t\t List configured servers and server groups"
25
34
  opts.separator "configure\t\t Create a new configuration file for this tool"
26
- opts.separator ""
27
- opts.separator "Common Options:"
35
+ opts.separator ''
36
+ opts.separator 'Common Options:'
28
37
 
29
38
  @options.config_file = './Deployfile'
30
- opts.on("-c", "--config path", 'Configuration file path') do |config_file_path|
39
+ opts.on('-c', '--config path', 'Configuration file path') do |config_file_path|
31
40
  @options.config_file = config_file_path
32
41
  end
33
42
 
34
- opts.on("-p", "--project project",
35
- "Project to operate on (default is read from project: in config file)") do |project_permalink|
43
+ opts.on('-p', '--project project',
44
+ 'Project to operate on (default is read from project: in config file)') do |project_permalink|
36
45
  @options.project = project_permalink
37
46
  end
38
47
 
39
- opts.on_tail('-v', '--version', "Shows Version") do
48
+ @options.config_files_deployment = false
49
+ opts.on('--config-files', 'Config files deployment') do |_config_files_deployment|
50
+ @options.config_files_deployment = true
51
+ end
52
+
53
+ opts.on_tail('-v', '--version', 'Shows Version') do
40
54
  puts Deploy::VERSION
41
55
  exit
42
56
  end
43
57
 
44
- opts.on_tail("-h", "--help", "Displays Help") do
58
+ opts.on_tail('-h', '--help', 'Displays Help') do
45
59
  puts opts
46
60
  exit
47
61
  end
@@ -51,7 +65,7 @@ module Deploy
51
65
  parser.parse!(args)
52
66
  command = args.pop
53
67
  rescue OptionParser::InvalidOption
54
- STDERR.puts parser.to_s
68
+ warn parser
55
69
  exit 1
56
70
  end
57
71
 
@@ -59,13 +73,13 @@ module Deploy
59
73
  begin
60
74
  Deploy.configuration_file = @options.config_file
61
75
  rescue Errno::ENOENT
62
- STDERR.puts "Couldn't find configuration file at #{@options.config_file.inspect}"
76
+ warn "Couldn't find configuration file at #{@options.config_file.inspect}"
63
77
  exit 1
64
78
  end
65
79
 
66
80
  project_permalink = @options.project || Deploy.configuration.project
67
81
  if project_permalink.nil?
68
- STDERR.puts "Project must be specified in config file or as --project argument"
82
+ warn 'Project must be specified in config file or as --project argument'
69
83
  exit 1
70
84
  end
71
85
 
@@ -80,25 +94,25 @@ module Deploy
80
94
  when 'configure'
81
95
  configure
82
96
  else
83
- STDERR.puts parser.to_s
97
+ warn parser
84
98
  end
85
99
  end
86
100
 
87
101
  def server_list
88
102
  @server_groups ||= @project.server_groups
89
- if @server_groups.count > 0
103
+ if @server_groups.count.positive?
90
104
  @server_groups.each do |group|
91
- puts "Group: #{group.name}".bold
92
- puts group.servers.map {|server| format_server(server) }.join("\n\n")
105
+ puts "Group: #{group.name}"
106
+ puts group.servers.map { |server| format_server(server) }.join("\n\n")
93
107
  end
94
108
  end
95
109
 
96
110
  @ungrouped_servers ||= @project.servers
97
- if @ungrouped_servers.count > 0
98
- puts "\n" if @server_groups.count > 0
99
- puts "Ungrouped Servers".bold
100
- puts @ungrouped_servers.map {|server| format_server(server) }.join("\n\n")
101
- end
111
+ return unless @ungrouped_servers.count.positive?
112
+
113
+ puts "\n" if @server_groups.count.positive?
114
+ puts 'Ungrouped Servers'
115
+ puts @ungrouped_servers.map { |server| format_server(server) }.join("\n\n")
102
116
  end
103
117
 
104
118
  def deploy
@@ -108,34 +122,40 @@ module Deploy
108
122
  parent = nil
109
123
  while parent.nil?
110
124
  parent = choose do |menu|
111
- menu.prompt = "Please choose a server or group to deploy to:"
125
+ menu.prompt = 'Please choose a server or group to deploy to:'
112
126
 
113
127
  menu.choices(*(@ungrouped_servers + @server_groups))
114
- menu.choice("List Server Details") do
128
+ menu.choice('List Server Details') do
115
129
  server_list
116
130
  nil
117
131
  end
118
132
  end
119
133
  end
120
134
 
121
- latest_revision = @project.latest_revision(parent.preferred_branch)
122
- deployment = @project.deploy(parent.identifier, parent.last_revision, latest_revision)
135
+ if @options.config_files_deployment
136
+ $stdout.print "\nStarting config files deployment\n"
137
+ deployment = @project.config_files_deployment(parent.identifier)
138
+ else
139
+ $stdout.print "\nStarting deployment\n"
140
+ latest_revision = @project.latest_revision(parent.preferred_branch)
141
+ deployment = @project.deploy(parent.identifier, parent.last_revision, latest_revision)
142
+ end
123
143
 
124
- STDOUT.print "Waiting for an available deployment slot..."
144
+ $stdout.print 'Waiting for an available deployment slot...'
125
145
  DeploymentProgressOutput.new(deployment).monitor
126
146
  end
127
147
 
128
148
  def configure
129
149
  configuration = {
130
- account: ask_config_question("Account Domain (e.g. https://atech.deployhq.com)",
131
- %r{\Ahttps?://[a-z0-9\.\-]+.deployhq.com\z}),
132
- username: ask_config_question("Username or e-mail address"),
133
- api_key: ask_config_question("API key (You can find this in Settings -> Security)"),
134
- project: ask_config_question("Default project to use (please use permalink from web URL)")
150
+ account: ask_config_question('Account Domain (e.g. https://atech.deployhq.com)',
151
+ /\Ahttps?:\/\/[a-z0-9.-]+.deployhq.com\z/),
152
+ username: ask_config_question('Username or e-mail address'),
153
+ api_key: ask_config_question('API key (You can find this in Settings -> Security)'),
154
+ project: ask_config_question('Default project to use (please use permalink from web URL)')
135
155
  }
136
156
 
137
157
  confirmation = true
138
- if File.exists?(@options.config_file)
158
+ if File.exist?(@options.config_file)
139
159
  confirmation = agree("File already exists at #{@options.config_file}. Overwrite? ")
140
160
  end
141
161
 
@@ -150,7 +170,7 @@ module Deploy
150
170
  question_text = "#{question_text}: "
151
171
  ask(question_text) do |q|
152
172
  q.whitespace = :remove
153
- q.responses[:not_valid] = "That answer is not valid"
173
+ q.responses[:not_valid] = 'That answer is not valid'
154
174
  q.responses[:ask_on_error] = :question
155
175
  q.validate = valid_format
156
176
  end
@@ -161,30 +181,38 @@ module Deploy
161
181
  ## Data formatters
162
182
  def format_server(server)
163
183
  server_params = {
164
- "Name" => server.name,
165
- "Type" => PROTOCOL_NAME[server.protocol_type.to_sym],
166
- "Path" => server.server_path,
167
- "Branch" => server.preferred_branch,
168
- "Current Revision" => server.last_revision,
184
+ 'Name' => server.name,
185
+ 'Type' => PROTOCOL_NAME[server.protocol_type.to_sym],
186
+ 'Path' => server.server_path,
187
+ 'Branch' => server.preferred_branch,
188
+ 'Current Revision' => server.last_revision
169
189
  }
170
- server_params["Hostname"] = [server.hostname, server.port].join(':') if server.hostname
171
- server_params["Bucket"] = server.bucket_name if server.bucket_name
172
- server_params["Region"] = server.region if server.region
173
- server_params["Container"] = server.container_name if server.container_name
190
+ server_params['Hostname'] = [server.hostname, server.port].join(':') if server.hostname
191
+ server_params['Bucket'] = server.bucket_name if server.bucket_name
192
+ server_params['Region'] = server.region if server.region
193
+ server_params['Container'] = server.container_name if server.container_name
174
194
 
175
- Array.new.tap do |a|
195
+ [].tap do |a|
176
196
  a << format_kv_pair(server_params)
177
197
  end.join("\n")
178
198
  end
179
199
 
200
+ # rubocop:disable Lint/FormatParameterMismatch
180
201
  def format_kv_pair(hash)
181
202
  longest_key = hash.keys.map(&:length).max + 2
182
- hash.each_with_index.map do |(k,v), i|
183
- str = sprintf("%#{longest_key}s : %s", k,v)
184
- i == 0 ? str.color(:bold) : str
203
+ hash.each_with_index.map do |(k, v), _i|
204
+ str = format("%#{longest_key}s : %s", k, v)
205
+ str
185
206
  end.join("\n")
186
207
  end
208
+ # rubocop:enable Lint/FormatParameterMismatch
187
209
 
188
210
  end
211
+
189
212
  end
190
213
  end
214
+ # rubocop:enable Metrics/ClassLength
215
+ # rubocop:enable Metrics/AbcSize
216
+ # rubocop:enable Metrics/CyclomaticComplexity
217
+ # rubocop:enable Metrics/MethodLength
218
+ # rubocop:enable Metrics/PerceivedComplexity
@@ -1,6 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
4
  class Configuration
3
- attr_accessor :account, :username, :api_key, :project
5
+
6
+ attr_accessor :account
7
+ attr_accessor :username
8
+ attr_accessor :api_key
9
+ attr_accessor :project
4
10
  attr_writer :websocket_hostname
5
11
 
6
12
  def websocket_hostname
@@ -11,7 +17,7 @@ module Deploy
11
17
  file_contents = File.read(path)
12
18
  parsed_contents = JSON.parse(file_contents)
13
19
 
14
- self.new.tap do |config|
20
+ new.tap do |config|
15
21
  config.account = parsed_contents['account']
16
22
  config.username = parsed_contents['username']
17
23
  config.api_key = parsed_contents['api_key']
@@ -19,5 +25,6 @@ module Deploy
19
25
  config.websocket_hostname = parsed_contents['websocket_hostname']
20
26
  end
21
27
  end
28
+
22
29
  end
23
30
  end
data/lib/deploy/errors.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
4
 
3
5
  ## Base level error which all other deploy errors will inherit from. It may also be
@@ -13,10 +15,12 @@ module Deploy
13
15
  ## Access was denied to the remote service
14
16
  class AccessDenied < Error; end
15
17
 
16
- ## A communication error occured while talking to the Deploy API
18
+ ## A communication error occurred while talking to the Deploy API
17
19
  class CommunicationError < Error; end
18
20
 
19
21
  # Raised from the websocket client when we receive an error event
20
22
  class WebsocketError < Error; end
23
+
21
24
  end
25
+
22
26
  end
@@ -1,7 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+
5
+ # rubocop:disable Metrics/AbcSize
6
+ # rubocop:disable Metrics/CyclomaticComplexity
7
+ # rubocop:disable Metrics/MethodLength
1
8
  module Deploy
2
9
  class Request
3
10
 
4
- attr_reader :path, :method
11
+ attr_reader :path
12
+ attr_reader :method
5
13
  attr_accessor :data
6
14
 
7
15
  def initialize(path, method = :get)
@@ -23,30 +31,28 @@ module Deploy
23
31
  uri = URI.parse([Deploy.configuration.account, @path].join('/'))
24
32
  http_request = http_class.new(uri.request_uri)
25
33
  http_request.basic_auth(Deploy.configuration.username, Deploy.configuration.api_key)
26
- http_request["Accept"] = "application/json"
27
- http_request["Content-type"] = "application/json"
34
+ http_request['Accept'] = 'application/json'
35
+ http_request['Content-Type'] = 'application/json'
28
36
 
29
37
  http = Net::HTTP.new(uri.host, uri.port)
30
- if uri.scheme == 'https'
31
- http.use_ssl = true
32
- end
38
+ http.use_ssl = true if uri.scheme == 'https'
33
39
 
34
40
  data = self.data.to_json if self.data.is_a?(Hash) && self.data.respond_to?(:to_json)
35
41
  http_result = http.request(http_request, data)
36
42
  @output = http_result.body
37
- @success = case http_result
43
+ case http_result
38
44
  when Net::HTTPSuccess
39
- true
45
+ @success = true
40
46
  when Net::HTTPServiceUnavailable
41
- raise Deploy::Errors::ServiceUnavailable
47
+ @success = raise Deploy::Errors::ServiceUnavailable
42
48
  when Net::HTTPForbidden, Net::HTTPUnauthorized
43
- raise Deploy::Errors::AccessDenied, "Access Denied for '#{Deploy.configuration.username}'"
49
+ @success = raise Deploy::Errors::AccessDenied, "Access Denied for '#{Deploy.configuration.username}'"
44
50
  when Net::HTTPNotFound
45
- raise Deploy::Errors::CommunicationError, "Not Found at #{uri.to_s}"
51
+ @success = raise Deploy::Errors::CommunicationError, "Not Found at #{uri}"
46
52
  when Net::HTTPClientError
47
- false
53
+ @success = false
48
54
  else
49
- raise Deploy::Errors::CommunicationError, http_result.body
55
+ @success = raise Deploy::Errors::CommunicationError, http_result.body
50
56
  end
51
57
  self
52
58
  end
@@ -65,3 +71,6 @@ module Deploy
65
71
 
66
72
  end
67
73
  end
74
+ # rubocop:enable Metrics/AbcSize
75
+ # rubocop:enable Metrics/CyclomaticComplexity
76
+ # rubocop:enable Metrics/MethodLength
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
4
  class Resource
3
5
 
@@ -9,14 +11,18 @@ module Deploy
9
11
  def method_missing(method, *params)
10
12
  set = method.to_s.include?('=')
11
13
  key = method.to_s.sub('=', '')
12
- self.attributes = Hash.new unless self.attributes.is_a?(Hash)
14
+ self.attributes = ({}) unless attributes.is_a?(Hash)
13
15
  if set
14
- self.attributes[key] = params.first
16
+ attributes[key] = params.first
15
17
  else
16
- self.attributes[key]
18
+ attributes[key]
17
19
  end
18
20
  end
19
21
 
22
+ def respond_to_missing?(method_name, include_private = false)
23
+ method_name.to_s.start_with?('user_') || super
24
+ end
25
+
20
26
  class << self
21
27
 
22
28
  ## Find a record or set of records. Passing :all will return all records and passing an integer
@@ -30,11 +36,13 @@ module Deploy
30
36
 
31
37
  ## Find all objects and return an array of objects with the attributes set.
32
38
  def find_all(params)
33
- output = JSON.parse(Request.new(collection_path(params)).make.output)
34
- if output.is_a?(Hash) && output['records'] && output['pagination']
35
- output = output['records']
36
- end
39
+ request = Request.new(collection_path(params))
40
+ output = request.make.output
41
+ output = JSON.parse(output)
42
+
43
+ output = output['records'] if output.is_a?(Hash) && output['records'] && output['pagination']
37
44
  return [] unless output.is_a?(Array)
45
+
38
46
  output.map do |o|
39
47
  create_object(o, params)
40
48
  end
@@ -42,12 +50,13 @@ module Deploy
42
50
 
43
51
  ## Find a single object and return an object for it.
44
52
  def find_single(id, params = {})
45
- o = JSON.parse(Request.new(member_path(id, params)).make.output)
46
- if o.is_a?(Hash)
47
- create_object(o, params)
48
- else
49
- raise Deploy::Errors::NotFound, "Record not found"
50
- end
53
+ request = Request.new(member_path(id, params))
54
+ output = request.make.output
55
+ output = JSON.parse(output)
56
+
57
+ raise Deploy::Errors::NotFound, 'Record not found' unless output.is_a?(Hash)
58
+
59
+ create_object(output, params)
51
60
  end
52
61
 
53
62
  ## Post to the specified object on the collection path
@@ -58,18 +67,18 @@ module Deploy
58
67
  ## Return the collection path for this model. Very lazy pluralizion here
59
68
  ## at the moment, nothing in Deploy needs to be pluralized with anything
60
69
  ## other than just adding an 's'.
61
- def collection_path(params = {})
62
- class_name.downcase + 's'
70
+ def collection_path(_params = {})
71
+ "#{class_name.downcase}s"
63
72
  end
64
73
 
65
74
  ## Return the member path for the passed ID & attributes
66
- def member_path(id, params = {})
75
+ def member_path(id, _params = {})
67
76
  [collection_path, id].join('/')
68
77
  end
69
78
 
70
79
  ## Return the deploy class name
71
80
  def class_name
72
- self.name.to_s.split('::').last.downcase
81
+ name.to_s.split('::').last.downcase
73
82
  end
74
83
 
75
84
  private
@@ -77,20 +86,21 @@ module Deploy
77
86
  ## Create a new object with the specified attributes and getting and ID.
78
87
  ## Returns the newly created object
79
88
  def create_object(attributes, objects = [])
80
- o = self.new
89
+ o = new
81
90
  o.attributes = attributes
82
91
  o.id = attributes['id']
83
- for key, object in objects.select{|k,v| v.kind_of?(Deploy::Resource)}
92
+ objects.select { |_k, v| v.is_a?(Deploy::Resource) }.each do |key, object|
84
93
  o.attributes[key.to_s] = object
85
94
  end
86
95
  o
87
96
  end
97
+
88
98
  end
89
99
 
90
100
  ## Run a post on the member path. Returns the ouput from the post, false if a conflict or raises
91
101
  ## a Deploy::Error. Optionally, pass a second 'data' parameter to send data to the post action.
92
102
  def post(action, data = nil)
93
- path = self.class.member_path(self.id, default_params) + "/" + action.to_s
103
+ path = "#{self.class.member_path(id, default_params)}/#{action}"
94
104
  request = Request.new(path, :post)
95
105
  request.data = data
96
106
  request.make
@@ -99,20 +109,21 @@ module Deploy
99
109
  ## Delete this record from the remote service. Returns true or false depending on the success
100
110
  ## status of the destruction.
101
111
  def destroy
102
- Request.new(self.class.member_path(self.id, default_params), :delete).make.success?
112
+ Request.new(self.class.member_path(id, default_params), :delete).make.success?
103
113
  end
104
114
 
105
115
  def new_record?
106
- self.id.nil?
116
+ id.nil?
107
117
  end
108
118
 
109
119
  def save
110
120
  new_record? ? create : update
111
121
  end
112
122
 
123
+ # rubocop:disable Metrics/AbcSize
113
124
  def create
114
125
  request = Request.new(self.class.collection_path(default_params), :post)
115
- request.data = {self.class.class_name.downcase.to_sym => attributes_to_post}
126
+ request.data = { self.class.class_name.downcase.to_sym => attributes_to_post }
116
127
  if request.make && request.success?
117
128
  new_record = JSON.parse(request.output)
118
129
  self.attributes = new_record
@@ -123,13 +134,14 @@ module Deploy
123
134
  false
124
135
  end
125
136
  end
137
+ # rubocop:enable Metrics/AbcSize
126
138
 
127
139
  ## Push the updated attributes to the remote. Returns true if the record was saved successfully
128
140
  ## other false if not. If not saved successfully, the errors hash will be updated with an array
129
141
  ## of all errors with the submission.
130
142
  def update
131
- request = Request.new(self.class.member_path(self.id, default_params), :put)
132
- request.data = {self.class.class_name.downcase.to_sym => attributes_to_post}
143
+ request = Request.new(self.class.member_path(id, default_params), :put)
144
+ request.data = { self.class.class_name.downcase.to_sym => attributes_to_post }
133
145
  if request.make && request.success?
134
146
  true
135
147
  else
@@ -142,23 +154,21 @@ module Deploy
142
154
 
143
155
  ## Populate the errors hash from the given raw JSON output
144
156
  def populate_errors(json)
145
- self.errors = Hash.new
146
- JSON.parse(json).inject(self.errors) do |r, e|
157
+ self.errors = ({})
158
+ JSON.parse(json).each_with_object(errors) do |e, r|
147
159
  r[e.first] = e.last
148
- r
149
160
  end
150
161
  end
151
162
 
152
163
  ## An array of params which should always be sent with this instances requests
153
164
  def default_params
154
- Hash.new
165
+ {}
155
166
  end
156
167
 
157
168
  ## Attributes which can be passed for update & creation
158
169
  def attributes_to_post
159
- self.attributes.inject(Hash.new) do |r,(key,value)|
170
+ attributes.each_with_object({}) do |(key, value), r|
160
171
  r[key] = value if value.is_a?(String) || value.is_a?(Integer)
161
- r
162
172
  end
163
173
  end
164
174
 
@@ -1,6 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
4
  class Deployment < Resource
5
+
3
6
  class << self
7
+
4
8
  def collection_path(params = {})
5
9
  "projects/#{params[:project].permalink}/deployments"
6
10
  end
@@ -8,17 +12,16 @@ module Deploy
8
12
  def member_path(id, params = {})
9
13
  "projects/#{params[:project].permalink}/deployments/#{id}"
10
14
  end
15
+
11
16
  end
12
17
 
13
18
  def default_params
14
- {:project => self.project}
19
+ { project: project }
15
20
  end
16
21
 
17
22
  def project
18
- if self.attributes['project'].is_a?(Hash)
19
- self.attributes['project'] = Project.send(:create_object, self.attributes['project'])
20
- end
21
- self.attributes['project']
23
+ attributes['project'] = Project.send(:create_object, attributes['project']) if attributes['project'].is_a?(Hash)
24
+ attributes['project']
22
25
  end
23
26
 
24
27
  def servers
@@ -47,5 +50,6 @@ module Deploy
47
50
  []
48
51
  end
49
52
  end
53
+
50
54
  end
51
55
  end
@@ -1,12 +1,16 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
4
  class DeploymentStep < Resource
5
+
3
6
  def default_params
4
- { deployment: self.deployment, project: self.deployment.project }
7
+ { deployment: deployment, project: deployment.project }
5
8
  end
6
9
 
7
10
  def logs(params = {})
8
11
  params = default_params.merge(step: self).merge(params)
9
12
  DeploymentStepLog.find(:all, params)
10
13
  end
14
+
11
15
  end
12
16
  end
@@ -1,7 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
4
  class DeploymentStepLog < Resource
5
+
3
6
  def self.collection_path(params = {})
4
- "projects/#{params[:project].permalink}/deployments/#{params[:deployment].identifier}/steps/#{params[:step].identifier}/logs"
7
+ permalink = params[:project].permalink
8
+ project_identifier = params[:project].identifier
9
+ step_identifier = params[:step].identifier
10
+
11
+ "projects/#{permalink}/deployments/#{project_identifier}/steps/#{step_identifier}/logs"
5
12
  end
13
+
6
14
  end
7
15
  end
@@ -1,31 +1,38 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
4
  class Project < Resource
3
5
 
4
6
  ## Return all deployments for this project
5
7
  def deployments
6
- Deployment.find(:all, :project => self)
8
+ Deployment.find(:all, project: self)
7
9
  end
8
10
 
9
11
  ## Return a deployment
10
12
  def deployment(identifier)
11
- Deployment.find(identifier, :project => self)
13
+ Deployment.find(identifier, project: self)
12
14
  end
13
15
 
14
16
  def latest_revision(branch = '')
15
17
  branch ||= 'master'
16
- req = Request.new(self.class.member_path(self.permalink) + "/repository/latest_revision?branch=#{branch}").make
18
+ req = Request.new(self.class.member_path(permalink) + "/repository/latest_revision?branch=#{branch}").make
17
19
  parsed = JSON.parse(req.output)
18
20
  parsed['ref']
19
21
  end
20
22
 
21
- ## Create a deployment in this project (and queue it to run)
22
- def deploy(server, start_revision, end_revision)
23
+ # Create a deployment in this project (and queue it to run)
24
+ def deploy(server, start_revision, end_revision, config_files_only: false)
23
25
  run_deployment(server, start_revision, end_revision) do |d|
24
26
  d.mode = 'queue'
27
+ d.config_files_deployment = '1' if config_files_only
25
28
  end
26
29
  end
27
30
 
28
- ##
31
+ def config_files_deployment(server)
32
+ deploy(server, nil, nil, config_files_only: true)
33
+ end
34
+
35
+ # Create a deployment preview
29
36
  def preview(server, start_revision, end_revision)
30
37
  run_deployment(server, start_revision, end_revision) do |d|
31
38
  d.mode = 'preview'
@@ -34,11 +41,11 @@ module Deploy
34
41
 
35
42
  ## Return all servers for this project
36
43
  def servers
37
- Server.find(:all, :project => self)
44
+ Server.find(:all, project: self)
38
45
  end
39
46
 
40
47
  def server_groups
41
- ServerGroup.find(:all, :project => self)
48
+ ServerGroup.find(:all, project: self)
42
49
  end
43
50
 
44
51
  private
@@ -1,28 +1,32 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
4
  class Server < Resource
3
5
 
4
6
  class << self
7
+
5
8
  def collection_path(params = {})
6
9
  "projects/#{params[:project].permalink}/servers"
7
10
  end
8
11
 
9
- def member_path(id, params = {})
12
+ def member_path(_id, params = {})
10
13
  "projects/#{params[:project].permalink}/servers/#{identifier}"
11
14
  end
15
+
12
16
  end
13
17
 
14
18
  def default_params
15
- {:project => self.project}
19
+ { project: project }
16
20
  end
17
21
 
18
22
  def to_s
19
- Array.new.tap do |a|
20
- a << self.name
21
- a << "(branch: #{self.preferred_branch})" if self.preferred_branch
22
- if self.last_revision
23
- a << "(currently: #{self.last_revision})"
23
+ [].tap do |a|
24
+ a << name
25
+ a << "(branch: #{preferred_branch})" if preferred_branch
26
+ if last_revision
27
+ a << "(currently: #{last_revision})"
24
28
  else
25
- a << "(currently undeployed)"
29
+ a << '(currently undeployed)'
26
30
  end
27
31
  end.join(' ')
28
32
  end
@@ -1,32 +1,36 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
4
  class ServerGroup < Resource
3
5
 
4
6
  class << self
7
+
5
8
  def collection_path(params = {})
6
9
  "projects/#{params[:project].permalink}/server_groups"
7
10
  end
8
11
 
9
- def member_path(id, params = {})
12
+ def member_path(_id, params = {})
10
13
  "projects/#{params[:project].permalink}/server_groups/#{identifier}"
11
14
  end
15
+
12
16
  end
13
17
 
14
18
  def default_params
15
- {:project => self.project}
19
+ { project: project }
16
20
  end
17
21
 
18
22
  def servers
19
- @servers ||= self.attributes['servers'].map {|server_attr| Deploy::Server.send(:create_object, server_attr) }
23
+ @servers ||= attributes['servers'].map { |server_attr| Deploy::Server.send(:create_object, server_attr) }
20
24
  end
21
25
 
22
26
  def to_s
23
- Array.new.tap do |a|
24
- a << self.name
25
- a << "(branch: #{self.preferred_branch})" if self.preferred_branch
26
- if self.last_revision
27
- a << "(currently: #{self.last_revision})"
27
+ [].tap do |a|
28
+ a << name
29
+ a << "(branch: #{preferred_branch})" if preferred_branch
30
+ if last_revision
31
+ a << "(currently: #{last_revision})"
28
32
  else
29
- a << "(currently undeployed)"
33
+ a << '(currently undeployed)'
30
34
  end
31
35
  end.join(' ')
32
36
  end
@@ -1,3 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Deploy
2
- VERSION = "2.0.4".freeze
4
+
5
+ VERSION_FILE_ROOT = File.expand_path('../../VERSION', __dir__)
6
+ if File.file?(VERSION_FILE_ROOT)
7
+ VERSION = File.read(VERSION_FILE_ROOT).strip.sub(/\Av/, '')
8
+ else
9
+ VERSION = '0.0.0.dev'
10
+ end
11
+
3
12
  end
data/lib/deploy.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rubygems'
2
4
  require 'bundler'
3
5
 
@@ -25,7 +27,9 @@ require 'deploy/resources/server_group'
25
27
  require 'deploy/version'
26
28
 
27
29
  module Deploy
30
+
28
31
  class << self
32
+
29
33
  def configure
30
34
  @configuration ||= Configuration.new
31
35
  yield @configuration if block_given?
@@ -39,5 +43,7 @@ module Deploy
39
43
  def configuration_file=(file_location)
40
44
  @configuration = Configuration.from_file(file_location)
41
45
  end
46
+
42
47
  end
48
+
43
49
  end
metadata CHANGED
@@ -1,43 +1,42 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: deployhq
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.4
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
- - Dan Wentworth
8
- autorequire:
7
+ - Adam Cooke
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2019-07-18 00:00:00.000000000 Z
10
+ date: 2025-01-08 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
- name: json
13
+ name: highline
15
14
  requirement: !ruby/object:Gem::Requirement
16
15
  requirements:
17
16
  - - "~>"
18
17
  - !ruby/object:Gem::Version
19
- version: '1.8'
18
+ version: '2.1'
20
19
  type: :runtime
21
20
  prerelease: false
22
21
  version_requirements: !ruby/object:Gem::Requirement
23
22
  requirements:
24
23
  - - "~>"
25
24
  - !ruby/object:Gem::Version
26
- version: '1.8'
25
+ version: '2.1'
27
26
  - !ruby/object:Gem::Dependency
28
- name: highline
27
+ name: json
29
28
  requirement: !ruby/object:Gem::Requirement
30
29
  requirements:
31
30
  - - "~>"
32
31
  - !ruby/object:Gem::Version
33
- version: '2.0'
32
+ version: '2.6'
34
33
  type: :runtime
35
34
  prerelease: false
36
35
  version_requirements: !ruby/object:Gem::Requirement
37
36
  requirements:
38
37
  - - "~>"
39
38
  - !ruby/object:Gem::Version
40
- version: '2.0'
39
+ version: '2.6'
41
40
  - !ruby/object:Gem::Dependency
42
41
  name: websocket-eventmachine-client
43
42
  requirement: !ruby/object:Gem::Requirement
@@ -52,10 +51,10 @@ dependencies:
52
51
  - - "~>"
53
52
  - !ruby/object:Gem::Version
54
53
  version: '1.2'
55
- description: |2
56
- API and CLI client for the DeployHQ deployment platform. Provides the
57
- deployhq executable.
58
- email: dan@atech.io
54
+ description: API and CLI client for the DeployHQ deployment platform. Provides the
55
+ deployhq executable.
56
+ email:
57
+ - adam@k.io
59
58
  executables:
60
59
  - deployhq
61
60
  extensions: []
@@ -77,11 +76,10 @@ files:
77
76
  - lib/deploy/resources/server.rb
78
77
  - lib/deploy/resources/server_group.rb
79
78
  - lib/deploy/version.rb
80
- homepage: https://www.deployhq.com
79
+ homepage: https://github.com/krystal/deployhq-lib
81
80
  licenses:
82
81
  - MIT
83
82
  metadata: {}
84
- post_install_message:
85
83
  rdoc_options: []
86
84
  require_paths:
87
85
  - lib
@@ -89,15 +87,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
89
87
  requirements:
90
88
  - - ">="
91
89
  - !ruby/object:Gem::Version
92
- version: '0'
90
+ version: '2.7'
93
91
  required_rubygems_version: !ruby/object:Gem::Requirement
94
92
  requirements:
95
93
  - - ">="
96
94
  - !ruby/object:Gem::Version
97
95
  version: '0'
98
96
  requirements: []
99
- rubygems_version: 3.0.3
100
- signing_key:
97
+ rubygems_version: 3.6.2
101
98
  specification_version: 4
102
99
  summary: API and CLI client for the DeployHQ
103
100
  test_files: []