tebako-release 0.3.0 → 0.4.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/README.md +6 -1
- data/lib/tebako_release/adapter.rb +13 -0
- data/lib/tebako_release/uploader.rb +82 -28
- data/lib/tebako_release/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6e91116fb240ffb5e0cb7cec20a1753fbd4177b7bd8f3c78adb8c3e260acf718
|
|
4
|
+
data.tar.gz: c5c886163f60c1ef021829015d95a1f3c50b6fc239a22a39cb890324041353d1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 78d61711350a83bc076b26472fab4b468e68368ca6f16f9f4c7bb613149d0a7c9be68821e6646e7469958e24424f59b3b88afd3d45c7b1f01db0b806550d9c69
|
|
7
|
+
data.tar.gz: 44d1ee55d6bf22f2aa8d6dfdacaa27f26a77170faa2d26a45669425879d6b5ece851d0d5e1072855c6f9fa6a7b2269578f1b112a0d62b34fecf2510bd82fa6a8
|
data/README.md
CHANGED
|
@@ -23,7 +23,12 @@ through a small adapter file and pin this gem — they never carry copies.
|
|
|
23
23
|
in-bundle SHA256SUMS; fixed member order, mtime=0 — identical inputs
|
|
24
24
|
yield identical bytes). A factory opts into the bundle-era publish shape
|
|
25
25
|
through its adapter (`bundle_publish? → true`); the per-file shape stays
|
|
26
|
-
the default for pre-bundle lines.
|
|
26
|
+
the default for pre-bundle lines. Bundle-era lines whose consumers
|
|
27
|
+
include the lazy arm additionally opt into co-publish
|
|
28
|
+
(`per_file_alongside_bundle? → true`, spec 36 §3): the staged members
|
|
29
|
+
are served as standalone assets beside the bundle, the shard carries
|
|
30
|
+
the `per_file_assets` witness (runtime-manifest MINOR 2), the facet
|
|
31
|
+
signature declarations return, and the audit expects the union.
|
|
27
32
|
- **`TebakoRelease::Blksum`** — the spec 39 §3 block-group digest sidecar
|
|
28
33
|
(`<image>.blksum.json`: one sha256 per 4 MiB group of env-image bytes,
|
|
29
34
|
the lazy mount's range-GET trust anchor). The uploader derives it
|
|
@@ -55,5 +55,18 @@ module TebakoRelease
|
|
|
55
55
|
def bundle_publish?
|
|
56
56
|
false
|
|
57
57
|
end
|
|
58
|
+
|
|
59
|
+
# Spec 36 §3's co-publish: when true (and bundle_publish? holds), each
|
|
60
|
+
# leg ALSO serves the per-file assets — the exe under its historical
|
|
61
|
+
# spelling, the env image, the windows DLL — as standalone release
|
|
62
|
+
# assets beside the bundle, each with its .sha256 sidecar. The lazy
|
|
63
|
+
# arm (spec 39 §7) range-fetches the image's groups over HTTP, which
|
|
64
|
+
# is impossible inside the gzip stream; the shard gains the additive
|
|
65
|
+
# per_file_assets witness (runtime-manifest MINOR 2) that gates the
|
|
66
|
+
# loaders' lazy arm on bundle-declaring shards. Default off: a
|
|
67
|
+
# factory opts in when its consumers include the lazy arm.
|
|
68
|
+
def per_file_alongside_bundle?
|
|
69
|
+
false
|
|
70
|
+
end
|
|
58
71
|
end
|
|
59
72
|
end
|
|
@@ -437,7 +437,7 @@ module TebakoRelease
|
|
|
437
437
|
nil
|
|
438
438
|
end
|
|
439
439
|
|
|
440
|
-
def manifest_entry(package, image = nil, dll = nil, bundle: nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
440
|
+
def manifest_entry(package, image = nil, dll = nil, bundle: nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
441
441
|
runtime_version, platform = parse_package_filename(package.basename.to_s)
|
|
442
442
|
contract = contract_sidecar(package)
|
|
443
443
|
filename = package.basename.to_s
|
|
@@ -470,6 +470,11 @@ module TebakoRelease
|
|
|
470
470
|
entry[:image] = image_entry(image, blksum) if image
|
|
471
471
|
entry[:dll] = dll_entry(dll, runtime_version, platform) if dll
|
|
472
472
|
entry[:bundle] = bundle_entry(bundle) if bundle
|
|
473
|
+
# Spec 36 §3's co-publish witness (runtime-manifest MINOR 2):
|
|
474
|
+
# true declares the per-file assets are served standalone beside
|
|
475
|
+
# the bundle — the lazy arm's gate on bundle-declaring shards
|
|
476
|
+
# (spec 39 §7). Never emitted on bundle-only lines.
|
|
477
|
+
entry[:per_file_assets] = true if bundle && copublish?
|
|
473
478
|
declare_signatures(entry)
|
|
474
479
|
end
|
|
475
480
|
end
|
|
@@ -530,7 +535,13 @@ module TebakoRelease
|
|
|
530
535
|
return unless signing_enabled?
|
|
531
536
|
|
|
532
537
|
keyid = signing_keyid
|
|
533
|
-
|
|
538
|
+
declare_bundle_signature(entry, keyid) if entry[:bundle]
|
|
539
|
+
# Bundle-only lines serve no other payload asset — declaring the
|
|
540
|
+
# members' .ascs there would be an invalid signing state (spec 09
|
|
541
|
+
# §4). A co-published line (spec 36 §3, the shard's per_file_assets
|
|
542
|
+
# witness) serves the members standalone, so the every-served-name
|
|
543
|
+
# rule covers the exe/image/dll set again.
|
|
544
|
+
return if entry[:bundle] && !entry[:per_file_assets]
|
|
534
545
|
|
|
535
546
|
entry[:signature] = { keyid: keyid, asc: "#{entry[:filename]}.asc" }
|
|
536
547
|
%i[image dll].each do |facet|
|
|
@@ -539,10 +550,10 @@ module TebakoRelease
|
|
|
539
550
|
end
|
|
540
551
|
end
|
|
541
552
|
|
|
542
|
-
# Bundle-era (spec 36 §3): the
|
|
543
|
-
#
|
|
544
|
-
#
|
|
545
|
-
#
|
|
553
|
+
# Bundle-era (spec 36 §3): the bundle's own signature declaration.
|
|
554
|
+
# On bundle-only lines it is the ONLY payload signature — three
|
|
555
|
+
# signatures per leg (bundle, its sidecar, the shard); co-published
|
|
556
|
+
# lines add the per-file declarations on top (declare_signatures).
|
|
546
557
|
def declare_bundle_signature(entry, keyid)
|
|
547
558
|
entry[:bundle][:signature] = { keyid: keyid, asc: "#{entry[:bundle][:filename]}.asc" }
|
|
548
559
|
end
|
|
@@ -832,11 +843,16 @@ module TebakoRelease
|
|
|
832
843
|
# feeds the entry's bundle block and the idempotent skip), upload the
|
|
833
844
|
# bundles as the legs' only payload assets, then the metadata (shard
|
|
834
845
|
# with the bundle block + the bundle's sidecar). The member files
|
|
835
|
-
# themselves never become release assets — the bundle is the unit
|
|
846
|
+
# themselves never become release assets — the bundle is the unit —
|
|
847
|
+
# UNLESS the factory co-publishes (spec 36 §3): then the members are
|
|
848
|
+
# standalone served names beside the bundle (the lazy arm
|
|
849
|
+
# range-fetches the image), still ahead of the shard that witnesses
|
|
850
|
+
# them (a witnessed shard without its assets is the invalid publish).
|
|
836
851
|
def process_bundle_release(release, packages)
|
|
837
852
|
bundles = build_bundles(packages)
|
|
838
853
|
entries = build_manifest_entries(packages, bundles: bundles)
|
|
839
854
|
bundles.each_value { |bundle| upload_package(release, bundle) }
|
|
855
|
+
packages.each { |package| upload_package(release, package) } if copublish?
|
|
840
856
|
upload_blksum_sidecars(release, entries)
|
|
841
857
|
entries.each { |entry| ensure_package_metadata(release, entry) }
|
|
842
858
|
print_settled_summary
|
|
@@ -877,6 +893,14 @@ module TebakoRelease
|
|
|
877
893
|
@config.adapter.bundle_publish?
|
|
878
894
|
end
|
|
879
895
|
|
|
896
|
+
# Spec 36 §3's co-publish mode: a bundle-era line that ALSO serves
|
|
897
|
+
# the per-file assets as standalone release assets (the lazy arm's
|
|
898
|
+
# serving requirement — spec 39 §7). Factory-declared through the
|
|
899
|
+
# adapter, like the era.
|
|
900
|
+
def copublish?
|
|
901
|
+
bundle_publish? && @config.adapter.per_file_alongside_bundle?
|
|
902
|
+
end
|
|
903
|
+
|
|
880
904
|
# AUDIT_ONLY (the coordinator's release job / a publish dry run):
|
|
881
905
|
# strictly read-only — finds the release (never creates one), needs no
|
|
882
906
|
# local packages, uploads nothing, touches no notes; the release's
|
|
@@ -943,20 +967,27 @@ module TebakoRelease
|
|
|
943
967
|
# era: the exe, its .tfs image and its .dll facet. Bundle era (spec 36
|
|
944
968
|
# §3): the bundle is the ONE served payload asset — the entry's
|
|
945
969
|
# exe/image/dll fields are member pins, not served names, so they earn
|
|
946
|
-
# no sidecar
|
|
947
|
-
# served standalone
|
|
970
|
+
# no sidecar — UNLESS the entry carries the co-publish witness, when
|
|
971
|
+
# the members ARE served standalone beside the bundle and earn theirs.
|
|
972
|
+
# Both eras: the derived blksum sidecar (spec 39 §3) IS a served
|
|
973
|
+
# standalone asset, so it earns its own .sha256 sidecar like
|
|
948
974
|
# every served name.
|
|
949
975
|
def metadata_assets(entry)
|
|
950
|
-
served =
|
|
951
|
-
|
|
952
|
-
else
|
|
953
|
-
{ entry[:filename] => entry[:sha256] }
|
|
954
|
-
.merge(facet_metadata(entry, :image))
|
|
955
|
-
.merge(facet_metadata(entry, :dll))
|
|
956
|
-
end
|
|
976
|
+
served = bundle_metadata(entry)
|
|
977
|
+
served.merge!(per_file_metadata(entry)) unless entry[:bundle] && !entry[:per_file_assets]
|
|
957
978
|
served.merge(blksum_metadata(entry))
|
|
958
979
|
end
|
|
959
980
|
|
|
981
|
+
def bundle_metadata(entry)
|
|
982
|
+
entry[:bundle] ? { entry[:bundle][:filename] => entry[:bundle][:sha256] } : {}
|
|
983
|
+
end
|
|
984
|
+
|
|
985
|
+
def per_file_metadata(entry)
|
|
986
|
+
{ entry[:filename] => entry[:sha256] }
|
|
987
|
+
.merge(facet_metadata(entry, :image))
|
|
988
|
+
.merge(facet_metadata(entry, :dll))
|
|
989
|
+
end
|
|
990
|
+
|
|
960
991
|
def facet_metadata(entry, facet)
|
|
961
992
|
block = entry[facet]
|
|
962
993
|
block ? { block[:filename] => block[:sha256] } : {}
|
|
@@ -1183,7 +1214,7 @@ module TebakoRelease
|
|
|
1183
1214
|
|
|
1184
1215
|
exe = [name, "#{name}.exe"].find { |candidate| present.include?(candidate) }
|
|
1185
1216
|
landed, missing = expected_facets(name).partition { |facet| present.include?(facet) }
|
|
1186
|
-
landed, missing = split_blksum_expectation(release, present, name, landed, missing)
|
|
1217
|
+
landed, missing = split_blksum_expectation(served_shard(release, present, name), present, landed, missing)
|
|
1187
1218
|
missing.unshift(name) unless exe
|
|
1188
1219
|
return missing if exe.nil?
|
|
1189
1220
|
|
|
@@ -1194,12 +1225,17 @@ module TebakoRelease
|
|
|
1194
1225
|
# asset; a landed bundle owes its sidecar and the package's shard
|
|
1195
1226
|
# (plus an .asc of each on signing-enabled audits). The declared
|
|
1196
1227
|
# blksum sidecar (spec 39 §3) is a standalone served asset in this
|
|
1197
|
-
# era too — expected, with its own metadata, when the shard pins it
|
|
1228
|
+
# era too — expected, with its own metadata, when the shard pins it —
|
|
1229
|
+
# and a shard carrying the co-publish witness (spec 36 §3's
|
|
1230
|
+
# per_file_assets) owes the standalone per-file assets beside the
|
|
1231
|
+
# bundle.
|
|
1198
1232
|
def missing_bundle_assets(release, present, name, require_signatures: false)
|
|
1199
1233
|
bundle = "#{name}#{Bundler::BUNDLE_SUFFIX}"
|
|
1200
1234
|
return [bundle] unless present.include?(bundle)
|
|
1201
1235
|
|
|
1202
|
-
|
|
1236
|
+
shard = served_shard(release, present, name)
|
|
1237
|
+
landed, missing = split_blksum_expectation(shard, present, [bundle], [])
|
|
1238
|
+
landed, missing = split_copublish_expectation(shard, present, name, landed, missing)
|
|
1203
1239
|
missing + missing_metadata(present, name, landed, require_signatures: require_signatures)
|
|
1204
1240
|
end
|
|
1205
1241
|
|
|
@@ -1212,8 +1248,8 @@ module TebakoRelease
|
|
|
1212
1248
|
# the shard's own gap is the gate's business). A DECLARED sidecar that
|
|
1213
1249
|
# never landed reports its own name only — its sidecar/.asc cascade
|
|
1214
1250
|
# rides the landed set, one error per gap.
|
|
1215
|
-
def split_blksum_expectation(
|
|
1216
|
-
declared =
|
|
1251
|
+
def split_blksum_expectation(shard, present, landed, missing)
|
|
1252
|
+
declared = shard&.dig("image", "blksum", "filename")
|
|
1217
1253
|
return [landed, missing] unless declared
|
|
1218
1254
|
|
|
1219
1255
|
if present.include?(declared)
|
|
@@ -1223,17 +1259,35 @@ module TebakoRelease
|
|
|
1223
1259
|
end
|
|
1224
1260
|
end
|
|
1225
1261
|
|
|
1226
|
-
# The
|
|
1227
|
-
#
|
|
1228
|
-
#
|
|
1229
|
-
|
|
1262
|
+
# The shard-witnessed co-publish expectation (spec 36 §3): a shard
|
|
1263
|
+
# carrying per_file_assets: true owes the standalone per-file assets —
|
|
1264
|
+
# the exe (either spelling), the image, the windows DLL — beside the
|
|
1265
|
+
# bundle; each landed member earns its metadata through the landed
|
|
1266
|
+
# set. An unwitnessed shard expects nothing (bundle-only lines audit
|
|
1267
|
+
# green), and a missing exe reports its own gap only, never a
|
|
1268
|
+
# cascade (the one-error-per-gap rule).
|
|
1269
|
+
def split_copublish_expectation(shard, present, name, landed, missing)
|
|
1270
|
+
return [landed, missing] unless shard && shard["per_file_assets"] == true
|
|
1271
|
+
|
|
1272
|
+
exe = [name, "#{name}.exe"].find { |candidate| present.include?(candidate) }
|
|
1273
|
+
facets_landed, facets_missing = expected_facets(name).partition { |facet| present.include?(facet) }
|
|
1274
|
+
gaps = facets_missing
|
|
1275
|
+
gaps = [name] + gaps unless exe
|
|
1276
|
+
[landed + [exe, *facets_landed].compact, missing + gaps]
|
|
1277
|
+
end
|
|
1278
|
+
|
|
1279
|
+
# The package's served shard as parsed JSON — the declarations' only
|
|
1280
|
+
# authority (the additive keys gate the audit's expectations). nil
|
|
1281
|
+
# when the shard never landed (its own gap is the gate's business) or
|
|
1282
|
+
# cannot be read (loudly — the audit never guesses an expectation).
|
|
1283
|
+
def served_shard(release, present, name)
|
|
1230
1284
|
shard = "#{name}#{SHARD_SUFFIX}"
|
|
1231
1285
|
return nil unless present.include?(shard)
|
|
1232
1286
|
|
|
1233
|
-
download_asset_json(find_asset(release, shard))
|
|
1287
|
+
download_asset_json(find_asset(release, shard))
|
|
1234
1288
|
rescue StandardError => e
|
|
1235
|
-
puts "::warning::could not read #{shard} for the
|
|
1236
|
-
"no
|
|
1289
|
+
puts "::warning::could not read #{shard} for the additive expectations (#{e.class}: #{e.message}) — " \
|
|
1290
|
+
"no additive assets are expected of this package"
|
|
1237
1291
|
nil
|
|
1238
1292
|
end
|
|
1239
1293
|
|