belt 0.6.6 → 0.6.8
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 +4 -4
- data/CHANGELOG.md +27 -0
- data/lib/belt/cli/deploy_command.rb +21 -9
- data/lib/belt/cli/tables_command.rb +87 -5
- data/lib/belt/docs/deployment.md +10 -2
- data/lib/belt/docs/models.md +20 -0
- data/lib/belt/models/ttl_macro.rb +31 -0
- data/lib/belt/version.rb +1 -1
- data/lib/belt.rb +1 -0
- data/lib/templates/new_app/AGENTS.md.erb +5 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5c8fdcdc85f77c9538860db16ba868045f1a4482487ce7cfbf6b3e1921e9c793
|
|
4
|
+
data.tar.gz: 996b9b570963202a4b9acde7fdaa4e83550606a7e6ba9ba89cf20dabff1c5cf7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3dbbf13ab635583594d630355888e2197f8a07052348eee39f47a1c328fba39392df21c88f12a8ab34252de920ecf711ba1915785de606a527afc79299ed69e8
|
|
7
|
+
data.tar.gz: e2f3a01545969526003d72e5c0b486e412c852ef8f6cdd6220ad92be5c6771dba8e0e3f5a1880ed691c72ad9e27a5e0caf11a2916717fcdf74c6e81fe05e871b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.6.8
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **`ttl_attribute` model macro.** `ttl_attribute :expires_at` on a model makes
|
|
8
|
+
`belt setup tables` emit `ttl { attribute_name = "expiresAt", enabled = true }`
|
|
9
|
+
for its table. A string is used verbatim. `belt explain models`. (Fizzy #1796)
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **`belt setup tables` no longer silently drops `ttl` blocks.** A hand-added `ttl`,
|
|
14
|
+
or any other table block or setting the models don't produce (`stream_enabled`,
|
|
15
|
+
`server_side_encryption`, …), now counts as dropped infrastructure like a
|
|
16
|
+
hand-added GSI. Interactive runs prompt, and generator auto-syncs (`belt g policies`
|
|
17
|
+
and friends) skip the file. Hand-written comments the regen removes are now
|
|
18
|
+
reported instead of vanishing quietly. (Fizzy #1796)
|
|
19
|
+
|
|
20
|
+
## 0.6.7
|
|
21
|
+
|
|
22
|
+
### Changed
|
|
23
|
+
|
|
24
|
+
- **Non-prod deploys auto-approve by default.** `belt deploy <env>` no longer
|
|
25
|
+
prompts for confirmation when the environment isn't `prod`/`production` — the
|
|
26
|
+
Terraform plan is applied straight away. `prod` still prompts unless you pass
|
|
27
|
+
`--auto`. Pass `--confirm` (alias `--no-auto`) to force the prompt on any
|
|
28
|
+
environment. No more typing `--auto` on every dev deploy.
|
|
29
|
+
|
|
3
30
|
## 0.6.6
|
|
4
31
|
|
|
5
32
|
### Added
|
|
@@ -32,6 +32,7 @@ module Belt
|
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
auto_approve = false
|
|
35
|
+
force_confirm = false
|
|
35
36
|
rebuild = false
|
|
36
37
|
skip_backup = false
|
|
37
38
|
backup_only = false
|
|
@@ -42,6 +43,8 @@ module Belt
|
|
|
42
43
|
case arg
|
|
43
44
|
when '--auto', '--yes', '-y'
|
|
44
45
|
auto_approve = true
|
|
46
|
+
when '--confirm', '--no-auto'
|
|
47
|
+
force_confirm = true
|
|
45
48
|
when '--rebuild'
|
|
46
49
|
rebuild = true
|
|
47
50
|
when '--skip-backup', '--no-backup'
|
|
@@ -69,13 +72,14 @@ module Belt
|
|
|
69
72
|
puts 'Usage: belt deploy [environment] [options]'
|
|
70
73
|
puts "\nDefaults to BELT_ENV or the first available environment."
|
|
71
74
|
puts "\nOptions:"
|
|
72
|
-
puts ' --auto, --yes, -y Skip confirmation prompt (auto-
|
|
75
|
+
puts ' --auto, --yes, -y Skip confirmation prompt (prod only; non-prod auto-approves)'
|
|
76
|
+
puts ' --confirm, --no-auto Force the confirmation prompt even for non-prod envs'
|
|
73
77
|
puts ' --rebuild Rebuild and push Lambda code directly (bypasses Terraform)'
|
|
74
78
|
puts ' -h, --help Show this help'
|
|
75
79
|
puts "\nExamples:"
|
|
76
|
-
puts ' belt deploy # Deploy dev (or BELT_ENV)'
|
|
77
|
-
puts ' belt deploy prod # Deploy to prod'
|
|
78
|
-
puts ' belt deploy
|
|
80
|
+
puts ' belt deploy # Deploy dev (or BELT_ENV), no prompt'
|
|
81
|
+
puts ' belt deploy prod # Deploy to prod (prompts)'
|
|
82
|
+
puts ' belt deploy prod --auto # Deploy prod without confirmation'
|
|
79
83
|
puts ' belt deploy --rebuild # Fast code push (no infra changes)'
|
|
80
84
|
puts ' belt deploy frontend dev # Deploy frontend(s)'
|
|
81
85
|
puts ' belt deploy frontend dev --frontend ops'
|
|
@@ -84,6 +88,10 @@ module Belt
|
|
|
84
88
|
end
|
|
85
89
|
end
|
|
86
90
|
|
|
91
|
+
# Non-prod environments auto-approve by default — prod always prompts
|
|
92
|
+
# unless --auto is explicit. Pass --confirm to force the prompt anywhere.
|
|
93
|
+
auto_approve = true if !force_confirm && !%w[prod production].include?(env)
|
|
94
|
+
|
|
87
95
|
options = { auto_approve: auto_approve, skip_migrations: skip_migrations, extra_args: filtered_args }
|
|
88
96
|
if backup_only
|
|
89
97
|
new(env, **options, skip_backup: false).run_backup_only
|
|
@@ -108,13 +116,16 @@ module Belt
|
|
|
108
116
|
4. Build sidecar Lambda zips Terraform needs at plan time
|
|
109
117
|
5. terraform init (initialize providers/modules)
|
|
110
118
|
6. terraform plan (preview changes)
|
|
111
|
-
7. Prompt for confirmation (
|
|
119
|
+
7. Prompt for confirmation (prod only; non-prod auto-approves)
|
|
112
120
|
8. terraform apply (deploy changes)
|
|
113
121
|
9. Nested envs: share parent Cognito + copy DynamoDB if empty
|
|
114
122
|
10. Run pending data migrations in db/migrate (see `belt db:migrate`)
|
|
115
123
|
|
|
116
124
|
Options:
|
|
117
|
-
--auto, --yes, -y Skip confirmation prompt (auto-approve)
|
|
125
|
+
--auto, --yes, -y Skip confirmation prompt (auto-approve). Non-prod
|
|
126
|
+
environments auto-approve by default, so this is only
|
|
127
|
+
needed for prod.
|
|
128
|
+
--confirm, --no-auto Force the confirmation prompt even for non-prod envs
|
|
118
129
|
--rebuild Rebuild and push Lambda code directly (bypasses Terraform).
|
|
119
130
|
Much faster for code-only changes — packages gems via Docker,
|
|
120
131
|
zips, and pushes with `aws lambda update-function-code`.
|
|
@@ -140,9 +151,10 @@ module Belt
|
|
|
140
151
|
end
|
|
141
152
|
|
|
142
153
|
Examples:
|
|
143
|
-
belt deploy # Deploy dev (or BELT_ENV)
|
|
144
|
-
belt deploy prod # Deploy to prod
|
|
145
|
-
belt deploy
|
|
154
|
+
belt deploy # Deploy dev (or BELT_ENV), no prompt
|
|
155
|
+
belt deploy prod # Deploy to prod (prompts for confirmation)
|
|
156
|
+
belt deploy prod --auto # Deploy to prod without confirmation (CI mode)
|
|
157
|
+
belt deploy dev --confirm # Force the confirmation prompt on dev
|
|
146
158
|
belt deploy --rebuild # Fast code push to dev (no infra changes)
|
|
147
159
|
belt deploy prod --rebuild # Fast code push to prod
|
|
148
160
|
belt deploy prod --skip-backup # Skip backups for this deploy
|
|
@@ -9,6 +9,8 @@ module Belt
|
|
|
9
9
|
class TablesCommand
|
|
10
10
|
MODULE_DIR = 'infrastructure/modules/app'
|
|
11
11
|
MODELS_DIR = 'lambda/models'
|
|
12
|
+
# Table blocks the drop check compares some other way (see #table_settings).
|
|
13
|
+
DERIVED_BLOCKS = %w[attribute global_secondary_index].freeze
|
|
12
14
|
|
|
13
15
|
def self.run(args)
|
|
14
16
|
# Environment argument accepted for backwards compatibility but unused —
|
|
@@ -99,7 +101,16 @@ module Belt
|
|
|
99
101
|
# Deduplicate by index name
|
|
100
102
|
indexes.uniq! { |idx| idx[:name] }
|
|
101
103
|
|
|
102
|
-
{ name: model_name, indexes: indexes }
|
|
104
|
+
{ name: model_name, indexes: indexes, ttl: extract_ttl_attribute(content) }
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# `ttl_attribute :expires_at` (Belt::Models::TtlMacro). A symbol is camelCased the
|
|
108
|
+
# way ActiveItem writes it; a string is the DynamoDB attribute name verbatim.
|
|
109
|
+
def extract_ttl_attribute(content)
|
|
110
|
+
match = uncommented(content).match(/^\s*ttl_attribute[\s(]+(?::(\w+)|['"]([^'"]+)['"])/)
|
|
111
|
+
return nil unless match
|
|
112
|
+
|
|
113
|
+
match[1] ? Belt::Inflector.camelize_lower(match[1]) : match[2]
|
|
103
114
|
end
|
|
104
115
|
|
|
105
116
|
def extract_indexes(content)
|
|
@@ -180,6 +191,8 @@ module Belt
|
|
|
180
191
|
if existing_content
|
|
181
192
|
dropped = detect_dropped_infrastructure(existing_content, new_content)
|
|
182
193
|
return if dropped.any? && !safe_to_overwrite?(dest, dropped)
|
|
194
|
+
|
|
195
|
+
warn_dropped_comments(dest, dropped_comments(existing_content, new_content))
|
|
183
196
|
end
|
|
184
197
|
|
|
185
198
|
File.write(dest, new_content)
|
|
@@ -215,11 +228,63 @@ module Belt
|
|
|
215
228
|
old_gsis = gsi_names(existing_content, label)
|
|
216
229
|
new_gsis = gsi_names(new_content, label)
|
|
217
230
|
dropped.concat((old_gsis - new_gsis).map { |gsi| "GSI \"#{gsi}\" on table \"#{label}\"" })
|
|
231
|
+
dropped.concat(dropped_table_settings(existing_content, new_content, label))
|
|
218
232
|
end
|
|
219
233
|
|
|
220
234
|
dropped
|
|
221
235
|
end
|
|
222
236
|
|
|
237
|
+
# Nested blocks (`ttl`, `server_side_encryption`, …) and settings (`stream_enabled`,
|
|
238
|
+
# …) a table has today that the regenerated table wouldn't. A hand-added ttl block
|
|
239
|
+
# is the usual one — dropping it turns expiry off and rows quietly pile up.
|
|
240
|
+
def dropped_table_settings(existing_content, new_content, label)
|
|
241
|
+
old_settings = table_settings(table_block(existing_content, label))
|
|
242
|
+
new_settings = table_settings(table_block(new_content, label))
|
|
243
|
+
|
|
244
|
+
(old_settings.keys - new_settings.keys).map do |key|
|
|
245
|
+
"#{old_settings[key]} on table \"#{label}\""
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
|
|
249
|
+
# Map of identity → description for every top-level setting in a table body.
|
|
250
|
+
# `attribute` and `global_secondary_index` are compared separately (GSIs) or are
|
|
251
|
+
# derived from them (attributes), so they're left out here.
|
|
252
|
+
def table_settings(block)
|
|
253
|
+
return {} unless block
|
|
254
|
+
|
|
255
|
+
settings = {}
|
|
256
|
+
depth = 0
|
|
257
|
+
block.each_line do |line|
|
|
258
|
+
code = line.sub(/#.*/, '').strip
|
|
259
|
+
if depth.zero?
|
|
260
|
+
if (name = code[/\A(\w+)\s*\{/, 1])
|
|
261
|
+
settings.merge!(block_setting(name, block, line)) unless DERIVED_BLOCKS.include?(name)
|
|
262
|
+
elsif (name = code[/\A(\w+)\s*=/, 1])
|
|
263
|
+
settings[name] = "setting \"#{name}\""
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
depth += code.count('{') - code.count('}')
|
|
267
|
+
end
|
|
268
|
+
settings
|
|
269
|
+
end
|
|
270
|
+
|
|
271
|
+
def block_setting(name, block, line)
|
|
272
|
+
return { name => "block \"#{name}\"" } unless name == 'ttl'
|
|
273
|
+
|
|
274
|
+
body = block[block.index(line)..][/\{(.*?)\}/m, 1].to_s
|
|
275
|
+
attr = body[/attribute_name\s*=\s*"([^"]+)"/, 1]
|
|
276
|
+
{ "ttl:#{attr}" => "ttl on \"#{attr}\"" }
|
|
277
|
+
end
|
|
278
|
+
|
|
279
|
+
# Hand-written comments can't be re-derived either. They're not infrastructure,
|
|
280
|
+
# so losing them doesn't block the write, but it shouldn't happen silently.
|
|
281
|
+
def dropped_comments(existing_content, new_content)
|
|
282
|
+
# The leading banner is Belt's own and changes between versions — skip it.
|
|
283
|
+
body = existing_content.lines.drop_while { |l| l.strip.empty? || l.lstrip.start_with?('#') }
|
|
284
|
+
body.map(&:strip).select { |l| l.start_with?('#', '//') } -
|
|
285
|
+
new_content.lines.map(&:strip)
|
|
286
|
+
end
|
|
287
|
+
|
|
223
288
|
# Resource labels for every aws_dynamodb_table block in the content.
|
|
224
289
|
def table_labels(content)
|
|
225
290
|
content.scan(/resource\s+"aws_dynamodb_table"\s+"([^"]+)"/).flatten
|
|
@@ -280,19 +345,28 @@ module Belt
|
|
|
280
345
|
def warn_dropped(dest, dropped)
|
|
281
346
|
puts "\n⚠ Regenerating #{dest} would DROP infrastructure not derived from your models:"
|
|
282
347
|
dropped.each { |d| puts " • #{d}" }
|
|
283
|
-
puts "\n This usually means a table or
|
|
284
|
-
puts ' Belt only tracks
|
|
348
|
+
puts "\n This usually means a table, GSI, or setting (e.g. ttl) was added to dynamodb.tf by hand."
|
|
349
|
+
puts ' Belt only tracks what it can read from lambda/models/*.rb (indexes, belongs_to,'
|
|
350
|
+
puts ' cognito_authenticatable, ttl_attribute),'
|
|
285
351
|
puts ' so a hand-added definition is invisible to the generator and gets overwritten.'
|
|
286
352
|
end
|
|
287
353
|
|
|
354
|
+
def warn_dropped_comments(dest, comments)
|
|
355
|
+
return if comments.empty?
|
|
356
|
+
|
|
357
|
+
puts " ⚠ #{dest}: removed #{comments.size} hand-written comment line(s) " \
|
|
358
|
+
'(the file is regenerated — put notes on the model instead)'
|
|
359
|
+
end
|
|
360
|
+
|
|
288
361
|
def render_dynamodb(models)
|
|
289
362
|
blocks = models.map { |m| render_table(m) }
|
|
290
363
|
"# Auto-generated by Belt from model definitions in lambda/models/*.rb\n" \
|
|
291
364
|
"#\n" \
|
|
292
365
|
"# Do NOT edit manually. `belt setup tables` overwrites this whole file from\n" \
|
|
293
366
|
"# your models. Any table or GSI added here by hand (that a model doesn't\n" \
|
|
294
|
-
"# declare) will be DROPPED on the next regeneration
|
|
295
|
-
"# model via indexes(), belongs_to, or
|
|
367
|
+
"# declare) will be DROPPED on the next regeneration, as will ttl blocks and\n" \
|
|
368
|
+
"# comments. Define indexes on the model via indexes(), belongs_to, or\n" \
|
|
369
|
+
"# cognito_authenticatable, and TTL via ttl_attribute, instead.\n\n#{blocks.join("\n\n")}\n"
|
|
296
370
|
end
|
|
297
371
|
|
|
298
372
|
def render_table(model)
|
|
@@ -360,6 +434,14 @@ module Belt
|
|
|
360
434
|
lines << ' }'
|
|
361
435
|
end
|
|
362
436
|
|
|
437
|
+
if model[:ttl]
|
|
438
|
+
lines << ''
|
|
439
|
+
lines << ' ttl {'
|
|
440
|
+
lines << " attribute_name = \"#{model[:ttl]}\""
|
|
441
|
+
lines << ' enabled = true'
|
|
442
|
+
lines << ' }'
|
|
443
|
+
end
|
|
444
|
+
|
|
363
445
|
lines << ''
|
|
364
446
|
lines << ' point_in_time_recovery {'
|
|
365
447
|
lines << ' enabled = var.enable_pitr'
|
data/lib/belt/docs/deployment.md
CHANGED
|
@@ -7,13 +7,21 @@ Lambda packaging, and pre-deploy backups.
|
|
|
7
7
|
## Quick Deploy
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
belt deploy <env> # init → plan → apply
|
|
11
|
-
belt deploy prod
|
|
10
|
+
belt deploy <env> # init → plan → apply
|
|
11
|
+
belt deploy prod # prod prompts for confirmation
|
|
12
|
+
belt deploy prod --auto # skip prod's confirmation prompt (CI)
|
|
13
|
+
belt deploy dev # non-prod auto-approves — no prompt
|
|
14
|
+
belt deploy dev --confirm # force the prompt on a non-prod env
|
|
12
15
|
belt deploy prod --skip-backup # skip pre-deploy backup
|
|
13
16
|
belt deploy --backup-only # create recovery point without deploying
|
|
14
17
|
belt deploy dev --skip-migrations # don't run pending db/migrate migrations
|
|
15
18
|
```
|
|
16
19
|
|
|
20
|
+
Non-prod environments auto-approve the Terraform plan by default — only `prod`
|
|
21
|
+
(and `production`) prompt. Pass `--confirm` (alias `--no-auto`) to force the
|
|
22
|
+
prompt anywhere; `--auto` still works everywhere and is what you want in CI for
|
|
23
|
+
prod.
|
|
24
|
+
|
|
17
25
|
## First-Time Setup
|
|
18
26
|
|
|
19
27
|
```bash
|
data/lib/belt/docs/models.md
CHANGED
|
@@ -144,6 +144,26 @@ ActiveItem::Transaction.write do |tx|
|
|
|
144
144
|
end
|
|
145
145
|
```
|
|
146
146
|
|
|
147
|
+
## Time To Live (TTL)
|
|
148
|
+
|
|
149
|
+
Let DynamoDB expire rows by declaring the TTL attribute on the model:
|
|
150
|
+
|
|
151
|
+
```ruby
|
|
152
|
+
class Session < ApplicationRecord
|
|
153
|
+
ttl_attribute :expires_at # stored as expiresAt; must hold epoch seconds
|
|
154
|
+
end
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
`belt setup tables` emits the matching `ttl { attribute_name = "expiresAt" }` block in
|
|
158
|
+
`dynamodb.tf`. A symbol is camelCased the way ActiveItem writes it; pass a string
|
|
159
|
+
(`ttl_attribute 'expires_at_epoch'`) to use the DynamoDB attribute name as-is.
|
|
160
|
+
|
|
161
|
+
Don't add `ttl` (or any other block) to `dynamodb.tf` by hand. The generator overwrites
|
|
162
|
+
the whole file from your models. If a regeneration would drop a hand-added table, GSI,
|
|
163
|
+
`ttl` or other table setting, `belt setup tables` asks before overwriting, and a
|
|
164
|
+
generator's auto-sync skips the file. Comments in the file are lost too (Belt prints a
|
|
165
|
+
warning), so put notes on the model.
|
|
166
|
+
|
|
147
167
|
## Generating Models
|
|
148
168
|
|
|
149
169
|
```bash
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'activeitem'
|
|
4
|
+
require_relative '../inflector'
|
|
5
|
+
|
|
6
|
+
module Belt
|
|
7
|
+
module Models
|
|
8
|
+
# Declares the DynamoDB Time To Live attribute for a model's table:
|
|
9
|
+
#
|
|
10
|
+
# class Session < ApplicationRecord
|
|
11
|
+
# ttl_attribute :expires_at # → ttl { attribute_name = "expiresAt" }
|
|
12
|
+
# end
|
|
13
|
+
#
|
|
14
|
+
# DynamoDB does the expiring, so at runtime this only records the name. The point
|
|
15
|
+
# is that `belt setup tables` reads it and emits the `ttl { }` block — a block
|
|
16
|
+
# added straight into dynamodb.tf would be dropped by the next regeneration.
|
|
17
|
+
#
|
|
18
|
+
# A symbol is camelCased the way ActiveItem stores it (`:expires_at` → `expiresAt`).
|
|
19
|
+
# Pass a string to use the DynamoDB attribute name verbatim (e.g. when the model
|
|
20
|
+
# remaps it with dynamo_attribute_map).
|
|
21
|
+
module TtlMacro
|
|
22
|
+
def ttl_attribute(name = nil)
|
|
23
|
+
return @ttl_attribute if name.nil?
|
|
24
|
+
|
|
25
|
+
@ttl_attribute = name.is_a?(Symbol) ? Belt::Inflector.camelize_lower(name.to_s) : name.to_s
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
ActiveItem::Base.extend(Belt::Models::TtlMacro)
|
data/lib/belt/version.rb
CHANGED
data/lib/belt.rb
CHANGED
|
@@ -57,6 +57,11 @@ belt apply <env>
|
|
|
57
57
|
|
|
58
58
|
This creates: model, controller (with all CRUD actions), route entry, and DynamoDB schema.
|
|
59
59
|
|
|
60
|
+
`infrastructure/modules/app/dynamodb.tf` is generated. Declare everything on the model:
|
|
61
|
+
GSIs via `indexes(...)` / `belongs_to`, TTL via `ttl_attribute :expires_at`. Anything
|
|
62
|
+
you add to the `.tf` by hand (a `ttl` block, a comment) gets dropped the next time it's
|
|
63
|
+
regenerated.
|
|
64
|
+
|
|
60
65
|
### Add a model only (no API endpoint)
|
|
61
66
|
|
|
62
67
|
```bash
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: belt
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.6.
|
|
4
|
+
version: 0.6.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stowzilla
|
|
@@ -186,6 +186,7 @@ files:
|
|
|
186
186
|
- lib/belt/inflector.rb
|
|
187
187
|
- lib/belt/lambda_handler.rb
|
|
188
188
|
- lib/belt/migration.rb
|
|
189
|
+
- lib/belt/models/ttl_macro.rb
|
|
189
190
|
- lib/belt/observability.rb
|
|
190
191
|
- lib/belt/parameters.rb
|
|
191
192
|
- lib/belt/rendering.rb
|