broadside 1.0.3 → 1.1.0.pre

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
  SHA1:
3
- metadata.gz: 0536213915fa9c027fe33ff15b4e9bec02a07b15
4
- data.tar.gz: 9ae58ab78407da3477ebb1f2eee07264b7b7477a
3
+ metadata.gz: dd26f89e64ffb9a89fbeba5e5b51a72b4bd8588b
4
+ data.tar.gz: 3d1d2f828a45cb8968851e37ef5dbd9ed5d5e01d
5
5
  SHA512:
6
- metadata.gz: 374b5c4d34b93cc0c357d39dce660c4d617895e5183bfb5bb30e17977be45dbe0b31b5dee0c04046f8eb27faf5bba984466c9b8b6380b4c8f0188c2ef8ae7838
7
- data.tar.gz: 2a6fa73a8ce47272c3613d35eccfb04fe55677b294aebeeab99dc95dfe2c4cd03d328f416946db290b7617982e6b1435d911e1c287656e5706b14b4ffcb7a59a
6
+ metadata.gz: 6b4ddb6d9f87222b23fa9f626d96d0eb3ffd4f48e5b351bb71ea154e18f43f79eb80910629b0d0400b222b00b820f2beb802ea7baf1bcc49a4ce46fa5a1450fc
7
+ data.tar.gz: 993493358dca3151d56f3a8e7b200a804b7c16297dea2c1c0bb9e722d0c9a68bf3d8a65d659caae37d00ebeeed32ef75ce32a04b2ae01a51f28f023f04abe541
data/CHANGELOG.md CHANGED
@@ -1,3 +1,6 @@
1
+ # 1.1.0
2
+ - [#16](https://github.com/lumoslabs/broadside/pull/16): Add bootstrap command; add specs
3
+
1
4
  # 1.0.3
2
5
  - [#12](https://github.com/lumoslabs/broadside/issues/12): Fix isssue with not being to use ssh, bash, logtail commands without specifying instance index
3
6
 
data/README.md CHANGED
@@ -29,16 +29,36 @@ Broadside.configure do |config|
29
29
  scale: 15,
30
30
  command: ['bundle', 'exec', 'rake', 'resque:work'],
31
31
  env_file: '../.env.production'
32
- }
32
+ },
33
33
  staging_web: {
34
34
  scale: 1,
35
35
  command: ['bundle', 'exec', 'puma'],
36
36
  env_file: '../.env.staging'
37
- }
37
+ },
38
38
  staging_worker: {
39
39
  scale: 1,
40
40
  command: ['bundle', 'exec', 'rake', 'resque:work'],
41
41
  env_file: '../.env.staging'
42
+ },
43
+ # Example with a task_definition and service configuration which you use to bootstrap a service and
44
+ # initial task definition
45
+ game_save_as_json_blob_stream: {
46
+ scale: 1,
47
+ command: ['java', '-cp', '*:.', 'path.to.MyClass'],
48
+ env_file: '.env.production',
49
+ service_config: {
50
+ deployment_configuration: {
51
+ minimum_healthy_percent: 0.5,
52
+ }
53
+ },
54
+ task_definition_config: {
55
+ container_definitions: [
56
+ {
57
+ cpu: 1,
58
+ memory: 2000,
59
+ }
60
+ ]
61
+ }
42
62
  }
43
63
  }
44
64
  end
data/bin/broadside CHANGED
@@ -42,6 +42,11 @@ accept Fixnum do |val|
42
42
  val.to_i
43
43
  end
44
44
 
45
+ desc 'Bootstrap your service and task definition.'
46
+ command :bootstrap do |b|
47
+ add_shared_deploy_configs(b)
48
+ end
49
+
45
50
  desc 'Deploy your application.'
46
51
  command :deploy do |d|
47
52
  d.desc 'Deploys without running migrations'
data/broadside.gemspec CHANGED
@@ -17,10 +17,12 @@ Gem::Specification.new do |spec|
17
17
  spec.executables = ['broadside']
18
18
  spec.require_paths = ["lib"]
19
19
 
20
+ spec.add_dependency 'activesupport', '>= 3', '< 5'
20
21
  spec.add_dependency 'aws-sdk', '~> 2.3'
21
- spec.add_dependency 'rainbow', '~> 2.1'
22
- spec.add_dependency 'gli', '~> 2.13'
23
22
  spec.add_dependency 'dotenv', '>= 0.9.0'
23
+ spec.add_dependency 'gli', '~> 2.13'
24
+ spec.add_dependency 'rainbow', '~> 2.1'
25
+
24
26
  spec.add_development_dependency 'rspec'
25
27
  spec.add_development_dependency 'bundler', '~> 1.9'
26
28
  spec.add_development_dependency 'fakefs'
data/lib/broadside.rb CHANGED
@@ -4,10 +4,10 @@ require 'broadside/configuration'
4
4
  require 'broadside/configuration/struct'
5
5
  require 'broadside/configuration/aws'
6
6
  require 'broadside/configuration/base'
7
- require 'broadside/configuration/deploy'
8
- require 'broadside/configuration/ecs'
7
+ require 'broadside/configuration/deploy_config'
8
+ require 'broadside/configuration/ecs_config'
9
9
  require 'broadside/deploy'
10
- require 'broadside/deploy/ecs'
10
+ require 'broadside/deploy/ecs_deploy'
11
11
  require 'broadside/version'
12
12
 
13
13
  module Broadside
@@ -22,14 +22,18 @@ module Broadside
22
22
  :env_vars,
23
23
  :command,
24
24
  :instance,
25
- :predeploy_commands
25
+ :predeploy_commands,
26
+ :service_config,
27
+ :task_definition_config
26
28
  )
27
29
 
28
30
  TARGET_ATTRIBUTE_VALIDATIONS = {
29
31
  scale: ->(target_attribute) { validate_types([Fixnum], target_attribute) },
30
32
  env_file: ->(target_attribute) { validate_types([String], target_attribute) },
31
33
  command: ->(target_attribute) { validate_types([Array, NilClass], target_attribute) },
32
- predeploy_commands: ->(target_attribute) { validate_predeploy(target_attribute) }
34
+ predeploy_commands: ->(target_attribute) { validate_predeploy(target_attribute) },
35
+ service_config: ->(target_attribute) { validate_types([Hash, NilClass], target_attribute) },
36
+ task_definition_config: ->(target_attribute) { validate_types([Hash, NilClass], target_attribute) }
33
37
  }
34
38
 
35
39
  def initialize
@@ -45,6 +49,8 @@ module Broadside
45
49
  @command = nil
46
50
  @predeploy_commands = DEFAULT_PREDEPLOY_COMMANDS
47
51
  @instance = 0
52
+ @service_config = nil
53
+ @task_definition_config = nil
48
54
  end
49
55
 
50
56
  # Validates format of deploy targets
@@ -86,6 +92,8 @@ module Broadside
86
92
  @scale ||= @targets[@target][:scale]
87
93
  @command = @targets[@target][:command]
88
94
  @predeploy_commands = @targets[@target][:predeploy_commands] if @targets[@target][:predeploy_commands]
95
+ @service_config = @targets[@target][:service_config]
96
+ @task_definition_config = @targets[@target][:task_definition_config]
89
97
  end
90
98
 
91
99
  private
@@ -100,14 +108,12 @@ module Broadside
100
108
 
101
109
  def self.validate_predeploy(target_attribute)
102
110
  return nil if target_attribute.nil?
103
-
104
111
  return 'predeploy_commands must be an array' unless target_attribute.is_a?(Array)
105
112
 
106
- target_attribute.each do |command|
107
- return "predeploy_command '#{command}' must be an array" unless command.is_a?(Array)
113
+ messages = target_attribute.reject { |cmd| cmd.is_a?(Array) }.map do |command|
114
+ "predeploy_command '#{command}' must be an array" unless command.is_a?(Array)
108
115
  end
109
-
110
- nil
116
+ messages.empty? ? nil : messages.join(', ')
111
117
  end
112
118
  end
113
119
  end
@@ -92,7 +92,7 @@ module Broadside
92
92
  end
93
93
 
94
94
  def gen_ssh_cmd(ip, options = { tty: false })
95
- opts = @deploy_config.ssh
95
+ opts = @deploy_config.ssh || {}
96
96
  cmd = 'ssh -o StrictHostKeyChecking=no'
97
97
  cmd << ' -t -t' if options[:tty]
98
98
  cmd << " -i #{opts[:keyfile]}" if opts[:keyfile]
@@ -1,3 +1,4 @@
1
+ require 'active_support/core_ext/hash'
1
2
  require 'aws-sdk'
2
3
  require 'open3'
3
4
  require 'pp'
@@ -6,15 +7,23 @@ require 'shellwords'
6
7
 
7
8
  module Broadside
8
9
  class EcsDeploy < Deploy
10
+
11
+ DEFAULT_DESIRED_COUNT = 0
12
+ DEFAULT_CONTAINER_DEFINITION = {
13
+ cpu: 1,
14
+ essential: true,
15
+ memory: 1000
16
+ }
17
+
9
18
  def initialize(opts)
10
19
  super(opts)
11
20
  config.ecs.verify(:cluster, :poll_frequency)
12
- check_service_existence
13
21
  end
14
22
 
15
23
  def deploy
16
24
  super do
17
- update_task
25
+ exception "Service #{family} does not exist!" unless service_exists?
26
+ update_task_revision
18
27
 
19
28
  begin
20
29
  update_service
@@ -22,17 +31,34 @@ module Broadside
22
31
  error 'Caught interrupt signal, rolling back...'
23
32
  rollback(1)
24
33
  error 'Deployment did not finish successfully.'
25
- abort
34
+ raise
26
35
  rescue StandardError => e
27
36
  error e.inspect, "\n", e.backtrace.join("\n")
28
37
  error 'Deploy failed! Rolling back...'
29
38
  rollback(1)
30
39
  error 'Deployment did not finish successfully.'
31
- abort
40
+ raise
32
41
  end
33
42
  end
34
43
  end
35
44
 
45
+ def bootstrap
46
+ unless get_latest_task_def_id
47
+ # Right now this creates a useless first revision and then update_task_revision will create a 2nd one
48
+ raise ArgumentError, "No first task definition and cannot create one" unless @deploy_config.task_definition_config
49
+
50
+ info "Creating an initial task definition for '#{family}' from the config..."
51
+ create_task_definition(family, @deploy_config.task_definition_config)
52
+ end
53
+
54
+ unless service_exists?
55
+ raise ArgumentError, "Service doesn't exist and cannot be created" unless @deploy_config.service_config
56
+
57
+ info "Service '#{family}' doesn't exist, creating..."
58
+ create_service(family, @deploy_config.service_config)
59
+ end
60
+ end
61
+
36
62
  def rollback(count = @deploy_config.rollback)
37
63
  super do
38
64
  begin
@@ -53,7 +79,7 @@ module Broadside
53
79
 
54
80
  def run
55
81
  super do
56
- update_task
82
+ update_task_revision
57
83
 
58
84
  begin
59
85
  run_command(@deploy_config.command)
@@ -66,7 +92,7 @@ module Broadside
66
92
  # runs before deploy commands using the latest task definition
67
93
  def run_predeploy
68
94
  super do
69
- update_task
95
+ update_task_revision
70
96
 
71
97
  begin
72
98
  @deploy_config.predeploy_commands.each do |command|
@@ -94,7 +120,7 @@ module Broadside
94
120
 
95
121
  def logtail
96
122
  super do
97
- ip = get_running_instance_ip_at_index!(@deploy_config.instance)
123
+ ip = get_running_instance_ips.fetch(@deploy_config.instance)
98
124
  debug "Tailing logs for running container at ip #{ip}..."
99
125
  search_pattern = Shellwords.shellescape(family)
100
126
  cmd = "docker logs -f --tail=10 `docker ps -n 1 --quiet --filter name=#{search_pattern}`"
@@ -105,7 +131,7 @@ module Broadside
105
131
 
106
132
  def ssh
107
133
  super do
108
- ip = get_running_instance_ip_at_index!(@deploy_config.instance)
134
+ ip = get_running_instance_ips.fetch(@deploy_config.instance)
109
135
  debug "Establishing an SSH connection to ip #{ip}..."
110
136
  exec gen_ssh_cmd(ip)
111
137
  end
@@ -113,7 +139,7 @@ module Broadside
113
139
 
114
140
  def bash
115
141
  super do
116
- ip = get_running_instance_ip_at_index!(@deploy_config.instance)
142
+ ip = get_running_instance_ips.fetch(@deploy_config.instance)
117
143
  debug "Running bash for running container at ip #{ip}..."
118
144
  search_pattern = Shellwords.shellescape(family)
119
145
  cmd = "docker exec -i -t `docker ps -n 1 --quiet --filter name=#{search_pattern}` bash"
@@ -124,49 +150,65 @@ module Broadside
124
150
 
125
151
  private
126
152
 
127
- def get_running_instance_ip_at_index(index)
128
- ips = get_running_instance_ips
129
- ips.size > index ? ips[index] : false
130
- end
131
-
132
- def get_running_instance_ip_at_index!(index)
133
- ip = get_running_instance_ip_at_index(index)
134
- return ip if ip
135
- exception 'Instance index greater than available instance count.'
136
- end
137
-
138
153
  # removes latest n task definitions
139
154
  def deregister_tasks(count)
140
- get_task_def_ids.last(count).each do |td_id|
155
+ get_task_definition_arns.last(count).each do |td_id|
141
156
  ecs_client.deregister_task_definition({task_definition: td_id})
142
157
  debug "Deregistered #{td_id}"
143
158
  end
144
159
  end
145
160
 
146
161
  # creates a new task revision using current directory's env vars and provided tag
147
- def update_task
148
- debug "Creating a new task definition..."
162
+ def update_task_revision
149
163
  new_task_def = create_new_task_revision
150
164
 
151
- container_def = new_task_def[:container_definitions].select { |c| c[:name] == family }.first
152
- container_def[:environment] = @deploy_config.env_vars
153
- container_def[:image] = image_tag
154
- container_def[:command] = @deploy_config.command
165
+ new_task_def[:container_definitions].select { |c| c[:name] == family }.first.tap do |container_def|
166
+ container_def[:environment] = @deploy_config.env_vars
167
+ container_def[:image] = image_tag
168
+ container_def[:command] = @deploy_config.command
169
+ end
155
170
 
171
+ debug "Creating a new task definition..."
156
172
  new_task_def_id = ecs_client.register_task_definition(new_task_def).task_definition.task_definition_arn
157
173
  debug "Successfully created #{new_task_def_id}"
158
174
  end
159
175
 
176
+ def create_service(name, options = {})
177
+ ecs_client.create_service(
178
+ {
179
+ cluster: config.ecs.cluster,
180
+ desired_count: DEFAULT_DESIRED_COUNT,
181
+ service_name: name,
182
+ task_definition: name
183
+ }.deep_merge(options)
184
+ )
185
+ end
186
+
187
+ def create_task_definition(name, options = {})
188
+ # Deep merge doesn't work with arrays, so build the hash and merge later
189
+ container_definitions = DEFAULT_CONTAINER_DEFINITION.merge(
190
+ name: name,
191
+ command: @deploy_config.command,
192
+ environment: @deploy_config.env_vars,
193
+ image: image_tag,
194
+ ).merge(options[:container_definitions].first || {})
195
+
196
+ ecs_client.register_task_definition(
197
+ { family: name }.deep_merge(options).merge(container_definitions: [container_definitions])
198
+ )
199
+ end
200
+
160
201
  # reloads the service using the latest task definition
161
202
  def update_service
162
203
  td = get_latest_task_def_id
163
204
  debug "Updating #{family} with scale=#{@deploy_config.scale} using task #{td}..."
164
- resp = ecs_client.update_service({
205
+ resp = ecs_client.update_service({
165
206
  cluster: config.ecs.cluster,
166
207
  service: family,
167
208
  task_definition: get_latest_task_def_id,
168
209
  desired_count: @deploy_config.scale
169
210
  })
211
+
170
212
  if resp.successful?
171
213
  begin
172
214
  ecs_client.wait_until(:services_stable, {cluster: config.ecs.cluster, services: [family]}) do |w|
@@ -208,6 +250,7 @@ module Broadside
208
250
  count: 1,
209
251
  started_by: "before_deploy:#{command_name}"[0...36]
210
252
  })
253
+
211
254
  if resp.successful?
212
255
  task_id = resp.tasks[0].task_arn
213
256
  debug "Launched #{command_name} task #{task_id}"
@@ -221,7 +264,7 @@ module Broadside
221
264
  end
222
265
  debug 'Task finished running, getting logs...'
223
266
  info "#{command_name} task container logs:\n#{get_container_logs(task_id)}"
224
- if(code = get_task_exit_code(task_id)) == 0
267
+ if (code = get_task_exit_code(task_id)) == 0
225
268
  debug "#{command_name} task #{task_id} exited with status code 0"
226
269
  else
227
270
  exception "#{command_name} task #{task_id} exited with a non-zero status code #{code}!"
@@ -259,7 +302,7 @@ module Broadside
259
302
  def get_running_instance_ips(task_ids = nil)
260
303
  task_arns = nil
261
304
  if task_ids.nil?
262
- task_arns = get_tasks
305
+ task_arns = get_task_arns
263
306
  if task_arns.empty?
264
307
  exception "No running tasks found for '#{family}' on cluster '#{config.ecs.cluster}' !"
265
308
  end
@@ -277,44 +320,32 @@ module Broadside
277
320
  ec2_instance_ids = container_instances.map { |ci| ci.ec2_instance_id }
278
321
  reservations = ec2_client.describe_instances({instance_ids: ec2_instance_ids}).reservations
279
322
  instances = reservations.map { |r| r.instances }.flatten
280
- private_ips = instances.map { |i| i.private_ip_address }
281
- private_ips
323
+
324
+ instances.map { |i| i.private_ip_address }
282
325
  end
283
326
 
284
327
  def get_latest_task_def
285
328
  ecs_client.describe_task_definition({task_definition: get_latest_task_def_id}).task_definition.to_h
286
329
  end
287
330
 
288
- def get_tasks
289
- # used for pagination if > 100 tasks
290
- next_token = nil
291
- tasks = []
292
- loop do
293
- resp = ecs_client.list_tasks({cluster: config.ecs.cluster, family: family, next_token: next_token})
294
- next_token = resp.next_token
295
- tasks += resp.task_arns
296
- break if next_token.nil?
297
- end
331
+ def get_task_arns
332
+ all_results(:list_tasks, :task_arns, { cluster: config.ecs.cluster, family: family })
333
+ end
298
334
 
299
- tasks
335
+ def get_task_definition_arns
336
+ all_results(:list_task_definitions, :task_definition_arns, { family_prefix: family })
300
337
  end
301
338
 
302
- def get_task_def_ids
303
- # used for pagination if > 100 task_definition ids
304
- next_token = nil
305
- task_def_ids = []
306
- loop do
307
- resp = ecs_client.list_task_definitions({family_prefix: family, next_token: next_token})
308
- next_token = resp.next_token
309
- task_def_ids += resp.task_definition_arns
310
- break if next_token.nil?
311
- end
339
+ def list_task_definition_families
340
+ all_results(:list_task_definition_families, :families)
341
+ end
312
342
 
313
- task_def_ids
343
+ def list_services
344
+ all_results(:list_services, :service_arns, { cluster: config.ecs.cluster })
314
345
  end
315
346
 
316
347
  def get_latest_task_def_id
317
- get_task_def_ids.last
348
+ get_task_definition_arns.last
318
349
  end
319
350
 
320
351
  def create_new_task_revision
@@ -326,6 +357,11 @@ module Broadside
326
357
  task_def
327
358
  end
328
359
 
360
+ def service_exists?
361
+ services = ecs_client.describe_services({ cluster: config.ecs.cluster, services: [family] })
362
+ services.failures.empty? && !services.services.empty?
363
+ end
364
+
329
365
  def ecs_client
330
366
  @ecs_client ||= Aws::ECS::Client.new({
331
367
  region: config.aws.region,
@@ -340,11 +376,16 @@ module Broadside
340
376
  })
341
377
  end
342
378
 
343
- def check_service_existence
344
- resp = ecs_client.describe_services({cluster: config.ecs.cluster, services: [family]})
345
- unless resp.failures.empty?
346
- exception "Could not find ECS service '#{family}' in cluster '#{config.ecs.cluster}' !"
379
+ def all_results(method, key, args = {})
380
+ page = ecs_client.public_send(method, args)
381
+ results = page.send(key)
382
+
383
+ while page.next_token
384
+ page = ecs.send(method, args.merge(next_token: page.next_token))
385
+ results += page.send(key)
347
386
  end
387
+
388
+ results
348
389
  end
349
390
  end
350
391
  end
@@ -1,3 +1,3 @@
1
1
  module Broadside
2
- VERSION = '1.0.3'
2
+ VERSION = '1.1.0.pre'
3
3
  end
metadata CHANGED
@@ -1,15 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: broadside
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.3
4
+ version: 1.1.0.pre
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthew Leung
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-08-25 00:00:00.000000000 Z
11
+ date: 2016-10-01 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '5'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: '3'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '5'
13
33
  - !ruby/object:Gem::Dependency
14
34
  name: aws-sdk
15
35
  requirement: !ruby/object:Gem::Requirement
@@ -25,19 +45,19 @@ dependencies:
25
45
  - !ruby/object:Gem::Version
26
46
  version: '2.3'
27
47
  - !ruby/object:Gem::Dependency
28
- name: rainbow
48
+ name: dotenv
29
49
  requirement: !ruby/object:Gem::Requirement
30
50
  requirements:
31
- - - "~>"
51
+ - - ">="
32
52
  - !ruby/object:Gem::Version
33
- version: '2.1'
53
+ version: 0.9.0
34
54
  type: :runtime
35
55
  prerelease: false
36
56
  version_requirements: !ruby/object:Gem::Requirement
37
57
  requirements:
38
- - - "~>"
58
+ - - ">="
39
59
  - !ruby/object:Gem::Version
40
- version: '2.1'
60
+ version: 0.9.0
41
61
  - !ruby/object:Gem::Dependency
42
62
  name: gli
43
63
  requirement: !ruby/object:Gem::Requirement
@@ -53,19 +73,19 @@ dependencies:
53
73
  - !ruby/object:Gem::Version
54
74
  version: '2.13'
55
75
  - !ruby/object:Gem::Dependency
56
- name: dotenv
76
+ name: rainbow
57
77
  requirement: !ruby/object:Gem::Requirement
58
78
  requirements:
59
- - - ">="
79
+ - - "~>"
60
80
  - !ruby/object:Gem::Version
61
- version: 0.9.0
81
+ version: '2.1'
62
82
  type: :runtime
63
83
  prerelease: false
64
84
  version_requirements: !ruby/object:Gem::Requirement
65
85
  requirements:
66
- - - ">="
86
+ - - "~>"
67
87
  - !ruby/object:Gem::Version
68
- version: 0.9.0
88
+ version: '2.1'
69
89
  - !ruby/object:Gem::Dependency
70
90
  name: rspec
71
91
  requirement: !ruby/object:Gem::Requirement
@@ -131,11 +151,11 @@ files:
131
151
  - lib/broadside/configuration.rb
132
152
  - lib/broadside/configuration/aws.rb
133
153
  - lib/broadside/configuration/base.rb
134
- - lib/broadside/configuration/deploy.rb
135
- - lib/broadside/configuration/ecs.rb
154
+ - lib/broadside/configuration/deploy_config.rb
155
+ - lib/broadside/configuration/ecs_config.rb
136
156
  - lib/broadside/configuration/struct.rb
137
157
  - lib/broadside/deploy.rb
138
- - lib/broadside/deploy/ecs.rb
158
+ - lib/broadside/deploy/ecs_deploy.rb
139
159
  - lib/broadside/error.rb
140
160
  - lib/broadside/utils.rb
141
161
  - lib/broadside/version.rb
@@ -154,9 +174,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
154
174
  version: '0'
155
175
  required_rubygems_version: !ruby/object:Gem::Requirement
156
176
  requirements:
157
- - - ">="
177
+ - - ">"
158
178
  - !ruby/object:Gem::Version
159
- version: '0'
179
+ version: 1.3.1
160
180
  requirements: []
161
181
  rubyforge_project:
162
182
  rubygems_version: 2.2.3