kettle-family 1.3.0 → 1.3.1
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
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +18 -1
- data/README.md +1 -1
- data/lib/kettle/family/cli.rb +2 -2
- data/lib/kettle/family/discovery.rb +3 -1
- data/lib/kettle/family/orderer.rb +4 -1
- data/lib/kettle/family/release_state_check.rb +22 -10
- data/lib/kettle/family/report.rb +23 -1
- data/lib/kettle/family/version.rb +1 -1
- data/lib/kettle/family/workflow.rb +32 -13
- data.tar.gz.sig +1 -3
- metadata +4 -4
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ce61863e305027b86eef8097ce594d8a9b77ba0e9e043ecb1617be9722a5ae38
|
|
4
|
+
data.tar.gz: 2b61292cbe3fcabb567c8f47ab7bac6170782dcedf75366452bb171b29b5a96a
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 47d6f2b5ebe4cbb0480c75037f702aba4eacf8185758df0724922d5cf2780d15a6c742d92e4d0bbdb55e64d3272c41a9ee3db8d46ad4e3bb39fedcc82427c25e
|
|
7
|
+
data.tar.gz: 1b0db917fd48cfe90aee4f6d00909ea667b9aab0bd9ac13704039a0117878f0f46d6ef6a5f1ef3f7e23a81858ef6f3aa2966d219127826a664c7c640f15da160
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,21 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [1.3.1] - 2026-09-10
|
|
34
|
+
|
|
35
|
+
- TAG: [v1.3.1][1.3.1t]
|
|
36
|
+
- COVERAGE: 93.48% -- 6352/6795 lines in 36 files
|
|
37
|
+
- BRANCH COVERAGE: 77.98% -- 2582/3311 branches in 36 files
|
|
38
|
+
- 33.49% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- Honor configured ordering in release-state reports, emit all five phases for shared-changelog members, and distinguish missing exact GitHub releases from lookup errors.
|
|
43
|
+
|
|
44
|
+
- Publish shared monorepo GitHub releases incrementally after each finalized member, retain successful workers from interrupted waves, attach both checksum formats, and report redundant family state cells once.
|
|
45
|
+
|
|
46
|
+
- Keep independent monorepo GitHub release identities exact and avoid false unlisted-member warnings during filtered state inspection.
|
|
47
|
+
|
|
33
48
|
## [1.3.0] - 2026-09-10
|
|
34
49
|
|
|
35
50
|
- TAG: [v1.3.0][1.3.0t]
|
|
@@ -2731,7 +2746,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
2731
2746
|
- Fixed CI load failures on engines without compatible `pty` support by falling back to Open3 for interactive release commands.
|
|
2732
2747
|
- Fixed Ruby 3.2 version-bump support by loading Prism lazily and wiring the Prism gem only for MRI versions that need it.
|
|
2733
2748
|
|
|
2734
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.3.
|
|
2749
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.3.1...HEAD
|
|
2750
|
+
[1.3.1]: https://github.com/kettle-dev/kettle-family/compare/v1.3.0...v1.3.1
|
|
2751
|
+
[1.3.1t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.3.1
|
|
2735
2752
|
[1.3.0]: https://github.com/kettle-dev/kettle-family/compare/v1.2.100...v1.3.0
|
|
2736
2753
|
[1.3.0t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.3.0
|
|
2737
2754
|
[1.2.100]: https://github.com/kettle-dev/kettle-family/compare/v1.2.99...v1.2.100
|
data/README.md
CHANGED
|
@@ -1186,7 +1186,7 @@ Thanks for RTFM. ☺️
|
|
|
1186
1186
|
[📌gitmoji]: https://gitmoji.dev
|
|
1187
1187
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1188
1188
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1189
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-6.
|
|
1189
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-6.795-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1190
1190
|
[🔐security]: https://github.com/kettle-dev/kettle-family/blob/main/SECURITY.md
|
|
1191
1191
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1192
1192
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/lib/kettle/family/cli.rb
CHANGED
|
@@ -684,10 +684,10 @@ module Kettle
|
|
|
684
684
|
members = discovery.members
|
|
685
685
|
ordered = if command == "install"
|
|
686
686
|
install_order(members, config)
|
|
687
|
-
elsif
|
|
687
|
+
elsif command == "metadata"
|
|
688
688
|
members.sort_by(&:name)
|
|
689
689
|
else
|
|
690
|
-
Orderer.new(members: members, mode: config.order_mode, hints: config.order_hints).ordered
|
|
690
|
+
Orderer.new(members: members, mode: config.order_mode, hints: config.order_hints).ordered(allow_cycles: command == "release-state")
|
|
691
691
|
end
|
|
692
692
|
state_event_tape = release_state_event_tape(command: command, config: config, options: options)
|
|
693
693
|
Selection.validate_release_state_only_filter!(effective_only)
|
|
@@ -92,7 +92,9 @@ module Kettle
|
|
|
92
92
|
def warn_unlisted_discovered_members(discovered, configured)
|
|
93
93
|
return unless config.configured_member_roots? || config.explicit_members.any?
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
# Selection limits evaluation, not membership in the configuration.
|
|
96
|
+
roots = configured.map(&:root) + config.configured_member_roots + config.explicit_members.map { |entry| entry.fetch("root") }
|
|
97
|
+
configured_roots = roots.map { |root| normalized_path(root) }
|
|
96
98
|
discovered.each do |member|
|
|
97
99
|
next if configured_roots.include?(normalized_path(member.root))
|
|
98
100
|
|
|
@@ -14,7 +14,7 @@ module Kettle
|
|
|
14
14
|
@by_name = members.to_h { |member| [member.name, member] }
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
def ordered
|
|
17
|
+
def ordered(allow_cycles: false)
|
|
18
18
|
case mode
|
|
19
19
|
when "dependency"
|
|
20
20
|
tsort
|
|
@@ -24,6 +24,9 @@ module Kettle
|
|
|
24
24
|
raise Error, "unknown order mode #{mode.inspect}"
|
|
25
25
|
end
|
|
26
26
|
rescue TSort::Cyclic => error
|
|
27
|
+
# Read-only state inspection must remain available to diagnose cycles.
|
|
28
|
+
return hinted_members if allow_cycles
|
|
29
|
+
|
|
27
30
|
raise Error, "dependency cycle detected: #{error.message}"
|
|
28
31
|
end
|
|
29
32
|
|
|
@@ -152,8 +152,11 @@ module Kettle
|
|
|
152
152
|
success = status.success?
|
|
153
153
|
emit_event(event_handler, member: member, branch: branch, action: "changelog_command", status: success ? "ok" : "failed", elapsed_seconds: elapsed, status_code: status.exitstatus)
|
|
154
154
|
state = success ? JSON.parse(stdout) : {}
|
|
155
|
+
emit_event(event_handler, member: member, branch: branch, action: "computed_booleans", status: "running") if success
|
|
155
156
|
state = state_with_computed_booleans(state) if success
|
|
157
|
+
state["shared_changelog_root"] = File.expand_path(config.root) if success
|
|
156
158
|
state = branch_filtered_state(member, state, branch) if success && branch
|
|
159
|
+
emit_event(event_handler, member: member, branch: branch, action: "computed_booleans", status: "ok") if success
|
|
157
160
|
emit_event(event_handler, member: member, branch: branch, action: "git_state", status: "running") if success
|
|
158
161
|
state = enrich_git_state(member.root, state, branch: branch) if success
|
|
159
162
|
emit_event(event_handler, member: member, branch: branch, action: "git_state", status: "ok") if success
|
|
@@ -391,11 +394,12 @@ module Kettle
|
|
|
391
394
|
end
|
|
392
395
|
|
|
393
396
|
def enrich_github_release(root, state, branch: nil, member: nil)
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
397
|
+
# A shared repository can publish an independent member after (or
|
|
398
|
+
# before) the cohort. Repository-wide "latest" cannot identify either.
|
|
399
|
+
if branch || shared_changelog?
|
|
400
|
+
return state.merge(github_release_for_version(root, state["latest_released"]))
|
|
398
401
|
end
|
|
402
|
+
tag = github_latest_release(root)
|
|
399
403
|
return state unless tag
|
|
400
404
|
|
|
401
405
|
state.merge("github_latest_release" => tag)
|
|
@@ -406,16 +410,24 @@ module Kettle
|
|
|
406
410
|
end
|
|
407
411
|
|
|
408
412
|
def github_release_for_version(root, version)
|
|
409
|
-
return
|
|
413
|
+
return {} if version.to_s.empty?
|
|
410
414
|
|
|
411
415
|
repo = github_repo_slug(root)
|
|
412
|
-
return
|
|
416
|
+
return {} unless repo
|
|
413
417
|
|
|
414
418
|
tag = "v#{version.to_s.delete_prefix("v")}"
|
|
415
|
-
stdout,
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
+
stdout, stderr, status = Open3.capture3("gh", "release", "view", tag, "--repo", repo, "--json", "tagName", "--jq", ".tagName")
|
|
420
|
+
return {"github_latest_release" => normalize_github_release_tag(stdout)} if status.success?
|
|
421
|
+
|
|
422
|
+
# A missing exact release is not a failed lookup, nor permission to
|
|
423
|
+
# substitute an independently versioned member's latest release.
|
|
424
|
+
{
|
|
425
|
+
"github_release_status" => (stderr.strip == "release not found") ? "missing" : "error",
|
|
426
|
+
"github_expected_release" => tag,
|
|
427
|
+
"github_release_error" => stderr.strip
|
|
428
|
+
}
|
|
429
|
+
rescue SystemCallError => error
|
|
430
|
+
{"github_release_status" => "error", "github_release_error" => error.message}
|
|
419
431
|
end
|
|
420
432
|
|
|
421
433
|
def enrich_transfer_changelog_lag(root, state)
|
data/lib/kettle/family/report.rb
CHANGED
|
@@ -554,9 +554,28 @@ module Kettle
|
|
|
554
554
|
lines << " count columns:"
|
|
555
555
|
lines << " T(n): filter-aware kettle-jem transfer changelog lag; n is the total source entry count and row values are missing / applicable (x excluded-present)"
|
|
556
556
|
rows = release_state_header
|
|
557
|
+
shared_rows = {}
|
|
557
558
|
results.each do |result|
|
|
558
|
-
|
|
559
|
+
row = release_state_row(result)
|
|
560
|
+
state = result.state || {}
|
|
561
|
+
shared_root = state["shared_changelog_root"]
|
|
562
|
+
if shared_root
|
|
563
|
+
# Only explicit shared-changelog cohorts share presentation. Keep
|
|
564
|
+
# member versions, registry state, transfer filters and flags intact.
|
|
565
|
+
key = [shared_root, result.branch, state["latest_released"]]
|
|
566
|
+
offset = release_state_has_branches? ? 1 : 0
|
|
567
|
+
shared_columns = [1, 3, 5, 7]
|
|
568
|
+
if shared_rows.key?(key)
|
|
569
|
+
shared_columns.each do |column|
|
|
570
|
+
row[column + offset] = "-" if row[column + offset] == shared_rows[key][column + offset]
|
|
571
|
+
end
|
|
572
|
+
else
|
|
573
|
+
shared_rows[key] = row.dup
|
|
574
|
+
end
|
|
575
|
+
end
|
|
576
|
+
rows << row
|
|
559
577
|
end
|
|
578
|
+
lines << " -: shared family value reported on the first matching cohort row" unless shared_rows.empty?
|
|
560
579
|
lines.concat(format_table(rows).map { |line| " #{line}" })
|
|
561
580
|
failures = results.reject(&:ok?)
|
|
562
581
|
return if failures.empty?
|
|
@@ -615,6 +634,9 @@ module Kettle
|
|
|
615
634
|
end
|
|
616
635
|
|
|
617
636
|
def release_state_github_release(state)
|
|
637
|
+
lookup_status = state["github_release_status"]
|
|
638
|
+
return lookup_status if %w[missing error].include?(lookup_status)
|
|
639
|
+
|
|
618
640
|
github_release = state.fetch("github_latest_release", nil).to_s
|
|
619
641
|
return "unknown" if github_release.empty?
|
|
620
642
|
|
|
@@ -5,7 +5,7 @@ module Kettle
|
|
|
5
5
|
# Version namespace for this gem.
|
|
6
6
|
module Version
|
|
7
7
|
# Current gem version.
|
|
8
|
-
VERSION = "1.3.
|
|
8
|
+
VERSION = "1.3.1"
|
|
9
9
|
end
|
|
10
10
|
# Current gem version exposed at the traditional constant location.
|
|
11
11
|
VERSION = Version::VERSION # Traditional Constant Location
|
|
@@ -533,7 +533,7 @@ module Kettle
|
|
|
533
533
|
return results unless results.all?(&:ok?)
|
|
534
534
|
|
|
535
535
|
results.concat(release_member_results(workflow_members, include_family_changelog: !skip_changelog))
|
|
536
|
-
return results unless explicit_monorepo_mode? && results.all?(&:ok?)
|
|
536
|
+
return results unless !execute && explicit_monorepo_mode? && results.all?(&:ok?)
|
|
537
537
|
|
|
538
538
|
selected_aggregate_members = aggregate_release_members(workflow_members)
|
|
539
539
|
results << aggregate_monorepo_github_release(aggregate_github_release_members) unless selected_aggregate_members.empty?
|
|
@@ -2128,6 +2128,9 @@ module Kettle
|
|
|
2128
2128
|
results.concat(release_results_for_member(member, runner: runner, wave_jobs: 1))
|
|
2129
2129
|
break unless results.last.ok?
|
|
2130
2130
|
|
|
2131
|
+
append_member_github_release(member, results)
|
|
2132
|
+
break unless results.last.ok?
|
|
2133
|
+
|
|
2131
2134
|
remaining_members = ordered_members.drop(ordered_members.index(member) + 1)
|
|
2132
2135
|
@release_completed_member_names << member.name
|
|
2133
2136
|
append_dependency_floor_results(released_members: [member], dependent_members: remaining_members, runner: runner, memo: results)
|
|
@@ -2217,10 +2220,15 @@ module Kettle
|
|
|
2217
2220
|
unless aggregate_members.empty?
|
|
2218
2221
|
worker_results = run_monorepo_release_wave(aggregate_members, wave_jobs: release_jobs(aggregate_members))
|
|
2219
2222
|
results.concat(worker_results.flatten)
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
+
# Finalize published successes even when another worker failed.
|
|
2224
|
+
# Otherwise interruption strands registry gems without GH assets.
|
|
2225
|
+
successful_members = aggregate_members.select do |member|
|
|
2226
|
+
member_results = worker_results.flatten.select { |result| result.member_name == member.name }
|
|
2227
|
+
member_results.any? { |result| result.phase == "release_publish" && result.ok? } && member_results.all?(&:ok?)
|
|
2228
|
+
end
|
|
2229
|
+
finalization_results = finalize_monorepo_release_wave(successful_members)
|
|
2223
2230
|
results.concat(finalization_results)
|
|
2231
|
+
break unless worker_results.all? { |member_results| member_results.all?(&:ok?) }
|
|
2224
2232
|
break unless finalization_results.all?(&:ok?)
|
|
2225
2233
|
end
|
|
2226
2234
|
|
|
@@ -2425,17 +2433,28 @@ module Kettle
|
|
|
2425
2433
|
passthrough_output: release_command_passthrough_output?
|
|
2426
2434
|
)
|
|
2427
2435
|
break unless results.last.ok?
|
|
2428
|
-
end
|
|
2429
|
-
return results unless results.all?(&:ok?)
|
|
2430
2436
|
|
|
2431
|
-
|
|
2432
|
-
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2437
|
+
results << runner.call(
|
|
2438
|
+
member: monorepo_release_control_member,
|
|
2439
|
+
phase: "release_shared_push",
|
|
2440
|
+
command: config.release_push_command
|
|
2441
|
+
)
|
|
2442
|
+
break unless results.last.ok?
|
|
2443
|
+
|
|
2444
|
+
append_member_github_release(member, results)
|
|
2445
|
+
break unless results.last.ok?
|
|
2446
|
+
end
|
|
2436
2447
|
results
|
|
2437
2448
|
end
|
|
2438
2449
|
|
|
2450
|
+
def append_member_github_release(member, results)
|
|
2451
|
+
return unless execute && publish && aggregate_monorepo_github_release? && aggregate_release_member?(member)
|
|
2452
|
+
|
|
2453
|
+
# Existing assets are retained by kettle-gh-release. Only contribute
|
|
2454
|
+
# this successfully published member, never a merely built future gem.
|
|
2455
|
+
results << aggregate_monorepo_github_release([member])
|
|
2456
|
+
end
|
|
2457
|
+
|
|
2439
2458
|
def ensure_monorepo_release_tag(member, runner:)
|
|
2440
2459
|
version = member.version.to_s
|
|
2441
2460
|
tag = release_tag_name(version)
|
|
@@ -3762,8 +3781,8 @@ module Kettle
|
|
|
3762
3781
|
|
|
3763
3782
|
assets = members.flat_map do |member|
|
|
3764
3783
|
gem_path = Dir[File.join(member.root, "pkg", "*.gem")].select { |path| File.basename(path).end_with?("-#{version.first}.gem") }
|
|
3765
|
-
|
|
3766
|
-
gem_path +
|
|
3784
|
+
checksum_paths = %w[sha256 sha512].map { |algorithm| File.join(member.root, "checksums", "#{member.name}-#{version.first}.gem.#{algorithm}") }
|
|
3785
|
+
gem_path + checksum_paths.select { |path| File.file?(path) }
|
|
3767
3786
|
end
|
|
3768
3787
|
command = ["bundle", "exec", "kettle-gh-release", "--allow-unpublished", "--events", "--release-version", version.first]
|
|
3769
3788
|
assets.each { |asset| command.concat(["--asset", asset]) }
|
data.tar.gz.sig
CHANGED
|
@@ -1,3 +1 @@
|
|
|
1
|
-
|
|
2
|
-
K������f�j6�/;kA�z���T�^%m�qOJ�L�e��K2(`Q��"��C�AdM��9$Ȍ/�����*�
|
|
3
|
-
�Ҙ#�+C)�p?)�á�%(*�:��M�p���T��CZv�Iw��}���:y��w1�&ُ:{H���]d~��6G�g=�ԃ2&ZL���0[�b��)P��7�����W�u�y�\jNes�w�rK�ePN����
|
|
1
|
+
������փw54|���5\3��}%�sA���K&��yTt�U��[�ZV}x�����Ao��1��°QW;8��}b�yoau�\���O:4��ތК?�E(��4��~�ܶZ��N�r��pl�u4�M�Qf�&^�Y��j��K�]�5!�`Y�X?;�wD�;1j��S��X*oЍ�������F�*VU0�]��ע���F������R�QA��|4��7��$��&�2�F*di���C��s�����rB�
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kettle-family
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.3.
|
|
4
|
+
version: 1.3.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -444,10 +444,10 @@ licenses:
|
|
|
444
444
|
- AGPL-3.0-only
|
|
445
445
|
metadata:
|
|
446
446
|
homepage_uri: https://kettle-family.galtzo.com
|
|
447
|
-
source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.3.
|
|
448
|
-
changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.3.
|
|
447
|
+
source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.3.1
|
|
448
|
+
changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.3.1/CHANGELOG.md
|
|
449
449
|
bug_tracker_uri: https://github.com/kettle-dev/kettle-family/issues
|
|
450
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.3.
|
|
450
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.3.1
|
|
451
451
|
funding_uri: https://github.com/sponsors/pboling
|
|
452
452
|
wiki_uri: https://github.com/kettle-dev/kettle-family/wiki
|
|
453
453
|
news_uri: https://www.railsbling.com/tags/kettle-family
|
metadata.gz.sig
CHANGED
|
Binary file
|