putpaws 0.1.3 → 0.1.5

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: f0adf3a9b8987d214af5c9a2c8348554ef7a34a47bc4ff55a1ea677c628d3fa2
4
- data.tar.gz: 15edd0ace3e1eeded5bc3687fc0f7b02e3189f50bf78255d708308818e861fa1
3
+ metadata.gz: 6b0c08e32fd66d0f401c637c162bb7d2e408beb0110e433fec09d2a5853e0372
4
+ data.tar.gz: faeacb4b1476fd8247f627e32640ddaaac55e906754bba8e0155adc35a624225
5
5
  SHA512:
6
- metadata.gz: 124c94a1b9b20738b48a2de2fe124847930d7ac4fdc921ae7519fa3b8bbe678a5743514258bbffabb3815aa933377f21ea388ee31600a8e211be49ad76af147c
7
- data.tar.gz: afabd0af48a055ddd0ee8a7e4604700d0fc9b810978a181e6513569d53d9f410ee62cf83e05d34f5ffdb1fdb3c2d42e8c03ded2815316e529df4f568b48d9744
6
+ metadata.gz: 8f43a0329c4b6705b72c235687f0ba9f3a038a1314c32dca0dcfb83f26f28326b0e7ae7d2d1cb13267674626ccd47786100b574b17fa95119606ebcf960b1193
7
+ data.tar.gz: 3488ea35bc10ce0ed4449ed0ca1ec97836f22535d246662f3d3f729779fc12d1e67b5a231cc28acc7fa9c816c369a59a37e6f5a9d5bda45c97fa9e9e70fc0291
data/README.md CHANGED
@@ -55,6 +55,14 @@ or a new one is created for the service when left empty on `ready`.
55
55
  When the service step completes, the new service is reflected into
56
56
  `.putpaws/application.json` and `.putpaws/infra.json` (diff is shown and confirmed),
57
57
  so `ecs:attach`, `ecs:shell`, `ecs:run` and `log:*` work immediately.
58
+ One entry is written per task definition of the preset, keyed by the task definition
59
+ family `{service_name}-{suffix}` (Ex: `awesome-api-staging-app` / `awesome-api-staging-web`),
60
+ each pointing at the `infra.target` of the same name. Only the entry of the preset's
61
+ `service_task_definition` carries `service` (for `ecs:deploy` / `ecs:attach`); the others have
62
+ `service: null` and are meant for one-off tasks (`ecs:run` / `ecs:shell` / scheduler),
63
+ so `db:migrate` keeps running on the plain `app` task definition even when the service
64
+ runs `web` (nginx + app). `infra.network` is written once as `{service_name}`.
65
+ Existing keys are never deleted; remove stale ones by hand.
58
66
  Secrets are handled by reference only: task definitions point to existing
59
67
  SSM parameters (Ex: `/{service_name}/RAILS_MASTER_KEY`) and putpaws never touches the values.
60
68
 
@@ -182,6 +190,15 @@ so you can identify them on the AWS console and on the task list of `ecs:attach`
182
190
  `ecs:run` and `ecs:shell` require `network` and `target` in `.putpaws/application.json`,
183
191
  which refer to the `network` / `target` sections of `.putpaws/infra.json` (the same ones used by scheduler).
184
192
 
193
+ ### CodeBuild
194
+
195
+ Start the CI build. By default it is fire-and-forget; pass `wait=true` to wait
196
+ until the build completes (phases are printed) and exit non-zero on failure.
197
+
198
+ ```
199
+ bundle exec putpaws awesome-api-staging code_build:build branch=main wait=true
200
+ ```
201
+
185
202
  ### CloudWatch Logs
186
203
 
187
204
  `tail -f`
@@ -216,19 +233,35 @@ gem 'putpaws'
216
233
 
217
234
  `.putpaws/application.json`
218
235
 
236
+ Keys are free-form names you pass to the CLI. The ones written by `putpaws up` follow
237
+ `{service_name}-{suffix}`: `-app` for one-off tasks (`service: null`), `-web` for the
238
+ long-running service.
239
+
219
240
  ```
220
241
  {
221
- "awesome-api-staging": {
242
+ "awesome-api-staging-app": {
222
243
  "region": "ap-northeast-1",
223
244
  "cluster": "cluster-staging",
224
245
  "service": null,
225
- "task_name_prefix": "awesome-api",
226
- "log_group_prefix": "/ecs/awesome/awesome-api-staging",
246
+ "task_name_prefix": "awesome-api-staging-app",
247
+ "log_group_prefix": "/ecs/awesome-api-staging",
248
+ "log_region": null,
249
+ "build_log_group_prefix": "/aws/codebuild/awesome-api-staging",
250
+ "build_project_name_prefix": "awesome-api-staging",
251
+ "network": "awesome-api-staging",
252
+ "target": "awesome-api-staging-app"
253
+ },
254
+ "awesome-api-staging-web": {
255
+ "region": "ap-northeast-1",
256
+ "cluster": "cluster-staging",
257
+ "service": "awesome-api-staging",
258
+ "task_name_prefix": "awesome-api-staging-web",
259
+ "log_group_prefix": "/ecs/awesome-api-staging",
227
260
  "log_region": null,
228
261
  "build_log_group_prefix": "/aws/codebuild/awesome-api-staging",
229
262
  "build_project_name_prefix": "awesome-api-staging",
230
- "network": "awesome-private-staging",
231
- "target": "awesome-staging"
263
+ "network": "awesome-api-staging",
264
+ "target": "awesome-api-staging-web"
232
265
  },
233
266
  "awesome-api-production": {
234
267
  "region": "ap-northeast-1",
@@ -41,6 +41,23 @@ module Putpaws::CodeBuild
41
41
  codebuild_client.start_build(**params)
42
42
  end
43
43
 
44
+ def wait_until_build_complete(build_id, timeout: 3600, interval: 10)
45
+ deadline = Time.now + timeout
46
+ last_phase = nil
47
+ loop do
48
+ res = codebuild_client.batch_get_builds(ids: [build_id])
49
+ build = res.builds.first
50
+ raise "Build not found: #{build_id}" unless build
51
+ if build.current_phase != last_phase
52
+ last_phase = build.current_phase
53
+ puts " phase: #{last_phase}"
54
+ end
55
+ return build if build.build_status != 'IN_PROGRESS'
56
+ raise "Timed out waiting for build to complete: #{build_id}" if Time.now > deadline
57
+ sleep interval
58
+ end
59
+ end
60
+
44
61
  def build_source_version(type:, version:)
45
62
  type = type.to_sym
46
63
  if type == :branch
@@ -15,7 +15,7 @@ namespace :code_build do
15
15
  set :codebuild_project, codebuild_project
16
16
  end
17
17
 
18
- desc "Start build."
18
+ desc "Start build. Pass wait=true to wait until the build completes and fail on error. (Ex) branch=main wait=true"
19
19
  task build: :set_project do
20
20
  aws = Putpaws::CodeBuild::ProjectCommand.config(fetch(:app))
21
21
 
@@ -30,10 +30,22 @@ namespace :code_build do
30
30
  end
31
31
  codebuild_project = fetch(:codebuild_project)
32
32
  aws.codebuild_project = codebuild_project
33
- aws.start_build_with_specific_version(
34
- source_version: source_version,
35
- environment_variables: ENV['env'] ? JSON.parse(ENV['env']) : {},
33
+ res = aws.start_build_with_specific_version(
34
+ source_version: source_version,
35
+ environment_variables: ENV['env'] ? JSON.parse(ENV['env']) : {},
36
36
  buildspec_override: ENV['buildspec']
37
37
  )
38
+ build = res.build
39
+ puts "Build started: #{build.id}"
40
+
41
+ if ENV['wait']
42
+ puts "Waiting for the build to complete..."
43
+ build = aws.wait_until_build_complete(build.id)
44
+ if build.build_status == 'SUCCEEDED'
45
+ puts "Build succeeded: #{build.id}"
46
+ else
47
+ raise "Build #{build.build_status.downcase}: #{build.id}"
48
+ end
49
+ end
38
50
  end
39
51
  end
@@ -8,6 +8,15 @@ module Putpaws
8
8
  # Reflects provisioned resources into .putpaws/application.json and
9
9
  # .putpaws/infra.json. Only the keys of the target service are touched.
10
10
  # Shows a diff and asks for confirmation before writing.
11
+ #
12
+ # One application entry and one infra.target entry are written per task
13
+ # definition of the preset, keyed by the task definition family
14
+ # (`<service_name>-<suffix>`). The entry whose suffix is the preset's
15
+ # `service_task_definition` carries `service` so that ecs:deploy /
16
+ # ecs:attach address the long-running service; the others are for
17
+ # one-off tasks (ecs:run / ecs:shell / scheduler) and have `service: null`.
18
+ # infra.network is written once per service as it does not depend on the
19
+ # task definition.
11
20
  class ConfigWriter
12
21
  attr_reader :config, :state, :prompt, :io
13
22
  def initialize(config:, state:, prompt:, io: $stdout)
@@ -17,17 +26,18 @@ module Putpaws
17
26
  @io = io
18
27
  end
19
28
 
20
- def application_entry
29
+ def application_entry(entry)
30
+ family = config.task_definition_family(entry[:suffix])
21
31
  {
22
32
  region: config.region,
23
33
  cluster: config.cluster_name,
24
- service: config.service_name,
25
- task_name_prefix: config.service_name,
34
+ service: service_entry?(entry) ? config.service_name : nil,
35
+ task_name_prefix: family,
26
36
  log_group_prefix: config.log_group,
27
37
  build_log_group_prefix: config.build_log_group,
28
38
  build_project_name_prefix: config.build_project_name,
29
39
  network: config.service_name,
30
- target: config.service_name,
40
+ target: family,
31
41
  }
32
42
  end
33
43
 
@@ -39,25 +49,32 @@ module Putpaws
39
49
  }
40
50
  end
41
51
 
42
- def target_entry
52
+ def target_entry(entry)
43
53
  {
44
54
  # Used by EventBridge Scheduler (scheduler:deploy).
45
55
  scheduler_role: config.roles[:scheduler_role_arn],
46
56
  cluster: state.resources[:cluster_arn],
47
57
  # Revision-less on purpose: always run the latest ACTIVE revision.
48
- task_definition: config.service_task_definition_family,
49
- container_name: config.service_container_name,
58
+ task_definition: config.task_definition_family(entry[:suffix]),
59
+ container_name: entry[:container_name] || 'app',
50
60
  }
51
61
  end
52
62
 
53
63
  def apply!
54
- write_key(path('application.json'), [config.service_name.to_sym], application_entry)
55
64
  write_key(path('infra.json'), [:network, config.service_name.to_sym], network_entry)
56
- write_key(path('infra.json'), [:target, config.service_name.to_sym], target_entry)
65
+ config.preset.task_definitions.each do |entry|
66
+ key = config.task_definition_family(entry[:suffix]).to_sym
67
+ write_key(path('application.json'), [key], application_entry(entry))
68
+ write_key(path('infra.json'), [:target, key], target_entry(entry))
69
+ end
57
70
  end
58
71
 
59
72
  private
60
73
 
74
+ def service_entry?(entry)
75
+ entry[:suffix] == config.preset.service_task_definition
76
+ end
77
+
61
78
  def path(basename)
62
79
  Pathname.new(config.path_prefix).join(basename)
63
80
  end
@@ -1,3 +1,3 @@
1
1
  module Putpaws
2
- VERSION = "0.1.3"
2
+ VERSION = "0.1.5"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: putpaws
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - metheglin