hecks 3.4.1 → 3.5.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 +4 -4
- data/lib/hecks/adapters/driven/memory/shared_elements.rb +121 -17
- data/lib/hecks/deploy/bluebook/deploy.bluebook +1630 -0
- data/lib/hecks/deploy/bluebook/deploy.hecksagon +65 -0
- data/lib/hecks/deploy/oidc.json +240 -0
- data/lib/hecks/doors/cli_runner.rb +13 -4
- data/lib/hecks/doors/launcher_options.rb +14 -2
- data/lib/hecks/hecks/adapters/bluebook_report.rb +91 -0
- data/lib/hecks/hecks/adapters/deploy_plans.rb +49 -0
- data/lib/hecks/hecks/adapters/deploy_toolchain.rb +379 -8
- data/lib/hecks/hecks/adapters/first_admin.rb +8 -1
- data/lib/hecks/hecks/adapters/git.rb +29 -0
- data/lib/hecks/hecks/adapters/in_process_operations.rb +6 -2
- data/lib/hecks/hecks/adapters/site_toolchain.rb +8 -8
- data/lib/hecks/hecks/custodian.bluebook +23 -2
- data/lib/hecks/hecks/hecks.hecksagon +66 -0
- data/lib/hecks/hecks/hecks.world +6 -1
- data/lib/hecks/hecks/site.world +4 -2
- data/lib/hecks/projections/deploy/box/hosting.rb +13 -3
- data/lib/hecks/projections/deploy/box/roll_recipe.rb +62 -0
- data/lib/hecks/projections/deploy/box/templates/deploy-box.sh.tmpl +10 -3
- data/lib/hecks/projections/deploy/box/templates/deploy-service.services-roll.part +2 -2
- data/lib/hecks/projections/deploy/box/templates/deploy-service.sh.tmpl +16 -4
- data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef-roll.part +6 -6
- data/lib/hecks/projections/deploy/box/templates/deploy-service.taskdef.part +1 -1
- data/lib/hecks/projections/deploy/box/templates/hosting.mk.tmpl +11 -5
- data/lib/hecks/projections/deploy/box/templates/restore-to-rds.sh.tmpl +8 -3
- data/lib/hecks/projections/deploy/box/templates/verify-copy.sh.tmpl +2 -2
- data/lib/hecks/projections/deploy/box.rb +26 -13
- data/lib/hecks/projections/site/admin.rb +140 -0
- data/lib/hecks/projections/site/admin_cms/templates.rb +388 -0
- data/lib/hecks/projections/site/admin_cms.rb +72 -0
- data/lib/hecks/projections/site/payload/fields.rb +234 -0
- data/lib/hecks/projections/site/payload/lifecycle.rb +191 -0
- data/lib/hecks/projections/site/payload/model.rb +128 -0
- data/lib/hecks/projections/site/payload/specs.rb +179 -0
- data/lib/hecks/projections/site/payload_driver.rb +93 -0
- data/lib/hecks/projections/site/root_rows.rb +59 -0
- data/lib/hecks/projections/site/site_admin.rb +292 -0
- data/lib/hecks/projections/site/site_host/templates.rb +165 -0
- data/lib/hecks/projections/site/site_host.rb +58 -0
- data/lib/hecks/projections/site/site_root.rb +179 -0
- data/lib/hecks/runtime/value.rb +7 -0
- data/lib/hecks/site/bluebook/site.bluebook +13 -2
- data/lib/hecks/tools/site_routes.rb +78 -8
- data/lib/hecks/version.rb +1 -1
- data/rust/host/HECKS_RELEASE +1 -1
- metadata +18 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 84b8798a316a3928051f7d6b5aa8baf4ab875e228778303cafeb6e591ada6369
|
|
4
|
+
data.tar.gz: 72bbefbce9a00405f7d1c8e7a3d0f99dcdf1fdf5f6cb8334e96b3f03cb944b4a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 82d1b5ea4652ccb5c4ce3788ea20a010e9466022853f5b187a6bb24db2a39d584337e7b6443ea3aa1cb9ed746b79863b41c40ec1ab0ba4312ad6e0dc64fb6cd5
|
|
7
|
+
data.tar.gz: d2d3d2e6b553e1d3d4ffcf98e9007af02d8f80a6bd0ffd022be797adf1571c7328a8e6e79a2b05aa407ec5086fb84e82bd00ce842c4e2dae3b2145510143a8ec
|
|
@@ -9,9 +9,12 @@ module Hecks
|
|
|
9
9
|
# Lets a Memory save of a growing `list_of` copy and hydrate only the elements it has not
|
|
10
10
|
# seen. A hydrated composite element is frozen, so its codec copy (the journal form) and
|
|
11
11
|
# its hydrated form are each computed once, frozen, and shared by every journal entry and
|
|
12
|
-
# record that holds it.
|
|
13
|
-
# through a
|
|
14
|
-
#
|
|
12
|
+
# record that holds it. A single value-object attribute that holds a list, directly or
|
|
13
|
+
# through a nested value object, shares the same way: the hydrated `Runtime::Value` is
|
|
14
|
+
# copied once, and a later version of it reuses the copies of the list elements it still
|
|
15
|
+
# holds. Shared nodes are immutable, so a caller cannot reach the journal through a
|
|
16
|
+
# returned instance. Everything else in the state goes through `StateCodec` whole. The
|
|
17
|
+
# tables are weak and identity-keyed: a cache, never the only holder.
|
|
15
18
|
class SharedElements
|
|
16
19
|
# @param aggregate [Bluebook::Aggregate] the aggregate whose state this shares elements of
|
|
17
20
|
def initialize(aggregate)
|
|
@@ -25,6 +28,7 @@ module Hecks
|
|
|
25
28
|
def reset!
|
|
26
29
|
@journal = ObjectSpace::WeakMap.new # live element => frozen decoded copy
|
|
27
30
|
@live = ObjectSpace::WeakMap.new # frozen decoded copy => hydrated element
|
|
31
|
+
@copies = ObjectSpace::WeakMap.new # frozen value-object copy this table built => true
|
|
28
32
|
self
|
|
29
33
|
end
|
|
30
34
|
|
|
@@ -36,11 +40,13 @@ module Hecks
|
|
|
36
40
|
# are frozen and shared with every other copy that holds them, nothing else is shared
|
|
37
41
|
# with `state`
|
|
38
42
|
def journal_state(state)
|
|
39
|
-
lists
|
|
40
|
-
|
|
43
|
+
lists = shareable_lists(state)
|
|
44
|
+
values = journal_values(state)
|
|
45
|
+
return Ports::Persistence::StateCodec.copy(@aggregate, state) if lists.empty? && values.empty?
|
|
41
46
|
|
|
42
|
-
copied = Ports::Persistence::StateCodec.copy(@aggregate, placeholders(state, lists))
|
|
47
|
+
copied = Ports::Persistence::StateCodec.copy(@aggregate, placeholders(state, lists, values))
|
|
43
48
|
lists.each { |name, (attribute, elements)| copied[name] = journal_list(attribute, elements) }
|
|
49
|
+
values.each { |name, (attribute, value)| copied[name] = journal_value(attribute, value) }
|
|
44
50
|
copied
|
|
45
51
|
end
|
|
46
52
|
|
|
@@ -48,12 +54,14 @@ module Hecks
|
|
|
48
54
|
#
|
|
49
55
|
# @param decoded [Hash] a fresh state in the shape `journal_state` returns; its non-shared
|
|
50
56
|
# values are hydrated in place of copies, so it must not be a journal entry's own state
|
|
51
|
-
# @return [Hash{Symbol => Object}] hydrated state, defaults filled; the lists
|
|
52
|
-
#
|
|
57
|
+
# @return [Hash{Symbol => Object}] hydrated state, defaults filled; the lists and value
|
|
58
|
+
# objects it shares are frozen, and nothing mutable is shared with `decoded`
|
|
53
59
|
def live_state(decoded)
|
|
54
|
-
lists
|
|
55
|
-
|
|
60
|
+
lists = shareable_lists(decoded)
|
|
61
|
+
values = live_values(decoded)
|
|
62
|
+
hydrated = Runtime::Instance.hydrate_with_defaults(@aggregate, placeholders(decoded, lists, values))
|
|
56
63
|
lists.each { |name, (attribute, elements)| hydrated[name] = live_list(attribute, elements) }
|
|
64
|
+
values.each { |name, (attribute, copy)| hydrated[name] = live_value(attribute, copy) }
|
|
57
65
|
hydrated
|
|
58
66
|
end
|
|
59
67
|
|
|
@@ -70,26 +78,122 @@ module Hecks
|
|
|
70
78
|
end
|
|
71
79
|
end
|
|
72
80
|
|
|
73
|
-
def composite_lists
|
|
74
|
-
|
|
81
|
+
def composite_lists = list_attributes(@aggregate)
|
|
82
|
+
|
|
83
|
+
def list_attributes(owner)
|
|
84
|
+
owner.attributes.each_with_object({}) do |attribute, found|
|
|
75
85
|
next unless attribute.list? && !attribute.reference? && composite?(attribute)
|
|
76
86
|
|
|
77
87
|
found[attribute.name.to_sym] = attribute
|
|
78
88
|
end
|
|
79
89
|
end
|
|
80
90
|
|
|
91
|
+
# The attributes of the aggregate that hold one value object able to hold a list, by
|
|
92
|
+
# name. A value object with no list in it is small and is left to the codec.
|
|
93
|
+
def growable_values
|
|
94
|
+
@growable_values ||= @aggregate.attributes.each_with_object({}) do |attribute, found|
|
|
95
|
+
next if attribute.list? || attribute.reference?
|
|
96
|
+
|
|
97
|
+
shape = value_object_of(attribute)
|
|
98
|
+
found[attribute.name.to_sym] = attribute if shape && growable?(shape, [])
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def value_object_of(attribute)
|
|
103
|
+
return nil unless @aggregate.respond_to?(:value_object)
|
|
104
|
+
|
|
105
|
+
Runtime::Value.value_object_for(@aggregate, attribute.type.to_s)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def growable?(shape, seen)
|
|
109
|
+
return false if seen.include?(shape)
|
|
110
|
+
|
|
111
|
+
shape.attributes.any? do |attribute|
|
|
112
|
+
next false if attribute.reference?
|
|
113
|
+
next true if attribute.list?
|
|
114
|
+
|
|
115
|
+
nested = value_object_of(attribute)
|
|
116
|
+
nested ? growable?(nested, seen + [shape]) : false
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
# The growable value-object attributes of `state` holding a frozen value of their type.
|
|
121
|
+
def journal_values(state)
|
|
122
|
+
return {} unless state.is_a?(Hash)
|
|
123
|
+
|
|
124
|
+
growable_values.each_with_object({}) do |(name, attribute), found|
|
|
125
|
+
value = state[name]
|
|
126
|
+
found[name] = [attribute, value] if value.is_a?(Runtime::Value) && sharable_value?(attribute, value)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def sharable_value?(attribute, value)
|
|
131
|
+
value.frozen? && value.type_name == value_object_of(attribute).hecks_name
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
# The growable value-object attributes of `decoded` holding a frozen Hash: a copy this
|
|
135
|
+
# table made, or one a caller froze.
|
|
136
|
+
def live_values(decoded)
|
|
137
|
+
return {} unless decoded.is_a?(Hash)
|
|
138
|
+
|
|
139
|
+
growable_values.each_with_object({}) do |(name, attribute), found|
|
|
140
|
+
copy = decoded[name]
|
|
141
|
+
found[name] = [attribute, copy] if copy.is_a?(Hash) && copy.frozen?
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
81
145
|
def composite?(attribute)
|
|
82
146
|
type = attribute.type.to_s
|
|
83
147
|
!Runtime::Value.find_entity(@aggregate, type).nil? ||
|
|
84
148
|
(@aggregate.respond_to?(:value_object) && !Runtime::Value.value_object_for(@aggregate, type).nil?)
|
|
85
149
|
end
|
|
86
150
|
|
|
87
|
-
# `state` with each shared list replaced by nil, which the codec
|
|
88
|
-
# which holds
|
|
89
|
-
def placeholders(state, lists)
|
|
90
|
-
return state if lists.empty?
|
|
151
|
+
# `state` with each shared list and value object replaced by nil, which the codec
|
|
152
|
+
# leaves alone and which holds its place in the key order.
|
|
153
|
+
def placeholders(state, lists, values)
|
|
154
|
+
return state if lists.empty? && values.empty?
|
|
155
|
+
|
|
156
|
+
state.merge(lists.merge(values).transform_values { nil })
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# The frozen codec copy of one value object. A list it holds is rebuilt from the copies
|
|
160
|
+
# of its elements, so a new version of the value costs the new elements, not all of them.
|
|
161
|
+
def journal_value(attribute, value)
|
|
162
|
+
known = @journal[value]
|
|
163
|
+
return known if known
|
|
164
|
+
|
|
165
|
+
fields = value.raw_fields
|
|
166
|
+
lists = value_lists(attribute, fields)
|
|
167
|
+
held = fields.merge(lists.transform_values { nil })
|
|
168
|
+
copy = Ports::Persistence::StateCodec.copy_list_element(@aggregate, attribute, held)
|
|
169
|
+
copy.each_value { |inner| Freezer.deep(inner) }
|
|
170
|
+
lists.each { |name, (list_attribute, elements)| copy[name] = journal_list(list_attribute, elements) }
|
|
171
|
+
@copies[copy.freeze] = true
|
|
172
|
+
@journal[value] = copy
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def value_lists(attribute, fields)
|
|
176
|
+
list_attributes(value_object_of(attribute)).each_with_object({}) do |(name, list_attribute), found|
|
|
177
|
+
elements = fields[name]
|
|
178
|
+
found[name] = [list_attribute, elements] if elements.is_a?(Array)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
# The hydrated value for one frozen copy, its lists rebuilt from the hydrated elements
|
|
183
|
+
# already held.
|
|
184
|
+
def live_value(attribute, copy)
|
|
185
|
+
known = @live[copy]
|
|
186
|
+
return known if known
|
|
187
|
+
|
|
188
|
+
lists = value_lists(attribute, copy)
|
|
189
|
+
fields = copy.merge(lists.to_h { |name, (list_attribute, elements)| [name, live_list(list_attribute, elements)] })
|
|
190
|
+
live = Runtime::Value.trusting_stored_state do
|
|
191
|
+
Runtime::Value.for_attribute(@aggregate, attribute, fields)
|
|
192
|
+
end
|
|
193
|
+
return live unless @copies.key?(copy)
|
|
91
194
|
|
|
92
|
-
|
|
195
|
+
@journal[live] = copy
|
|
196
|
+
@live[copy] = live
|
|
93
197
|
end
|
|
94
198
|
|
|
95
199
|
def journal_list(attribute, elements)
|