kettle-family 1.3.35 → 1.3.36

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: df70ef40b82ccb54155fc57a43a1137d620d3cbd78cd74643d050b9056f3ecdb
4
- data.tar.gz: aff84d0529ac6ef7b78a3248160eb72b4077f51609362c887837b1cd390a9a10
3
+ metadata.gz: 90c20dc69493246554befc819ed36f9e5c1bc81ef54f44257c7c8e2347bbe457
4
+ data.tar.gz: 410f4b020a832c51c372ab3230b859c8ec7b1e8829c26c595582a22f27d6901d
5
5
  SHA512:
6
- metadata.gz: e3ba12f341362839b45835afda346efa79c49aa886cf5d731980e0d9a2090ffe0297abb752bf72a293135e6ab4fa64c1f132210c882edfef2583c56204fb8355
7
- data.tar.gz: 7cd500810f8b034e00be64dc03574d957c578be29ef1df6d17ca4bf73999c1c47a381d57799e445f1f4c0cabae3622c0ad44152b1152175c1a4b252e0800a034
6
+ metadata.gz: 9268ee8a2ee002ca7394d0c67c55a579f2eeb2621bf2b09362b3ca8f776ff02ab98a39923b343b5c805f7c42276ed25fe34e35efc2b605cb282ae704140ad45b
7
+ data.tar.gz: bf88cb60646c3adbe20b397ea8e4e2e6829435b078ad9841e75623090233c5575682dc1f8695192b92706b34fa9635e07de1e0abd2f8d833d2ec1447bd1511d1
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,27 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [1.3.36] - 2026-10-28
34
+
35
+ - TAG: [v1.3.36][1.3.36t]
36
+ - COVERAGE: 93.12% -- 7601/8163 lines in 45 files
37
+ - BRANCH COVERAGE: 77.34% -- 3041/3932 branches in 45 files
38
+ - 38.89% documented
39
+
40
+ ### Changed
41
+
42
+ - [kc] template-family-resume-hints: Template failures now produce one combined retry hint for failed and pending members, preserving member@branch selectors for branch-stack templates.
43
+
44
+ - [kc] kettle-jem/prepare: updated 7 project files:
45
+ - configuration (1)
46
+ - dependencies (6)
47
+
48
+ - [kc] kettle-jem/template: updated 5 project files:
49
+ - code and tests (1)
50
+ - documentation (1)
51
+ - other (2)
52
+ - workflows (1)
53
+
33
54
  ## [1.3.35] - 2026-10-26
34
55
 
35
56
  - TAG: [v1.3.35][1.3.35t]
@@ -3299,7 +3320,9 @@ Please file a bug if you notice a violation of semantic versioning.
3299
3320
  - Fixed CI load failures on engines without compatible `pty` support by falling back to Open3 for interactive release commands.
3300
3321
  - Fixed Ruby 3.2 version-bump support by loading Prism lazily and wiring the Prism gem only for MRI versions that need it.
3301
3322
 
3302
- [Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.3.35...HEAD
3323
+ [Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.3.36...HEAD
3324
+ [1.3.36]: https://github.com/kettle-dev/kettle-family/compare/v1.3.35...v1.3.36
3325
+ [1.3.36t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.3.36
3303
3326
  [1.3.35]: https://github.com/kettle-dev/kettle-family/compare/v1.3.34...v1.3.35
3304
3327
  [1.3.35t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.3.35
3305
3328
  [1.3.34]: https://github.com/kettle-dev/kettle-family/compare/v1.3.33...v1.3.34
data/README.md CHANGED
@@ -64,12 +64,12 @@ configuration, create their own GitHub Release through `kettle-release`.
64
64
 
65
65
  ### Compatibility
66
66
 
67
- Compatible with MRI Ruby 4.0.0+.
67
+ The gem's declared runtime compatibility floor is MRI Ruby 4.0.0+, with concordant releases of JRuby and TruffleRuby.
68
68
  CI workflows and Appraisals are generated for MRI Ruby 4.0.0+.
69
69
  The current MRI CI lane runs on Linux and macOS.
70
- This test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml` and
71
- may be higher than the gem's runtime compatibility floor when legacy Rubies are
72
- not practical for the current toolchain.
70
+ The test floor is configured by `ruby.test_minimum` in `.kettle-jem.yml`.
71
+ When it is higher than the runtime floor, older runtime-compatible Rubies are
72
+ not covered by the generated CI or Appraisal matrix.
73
73
 
74
74
  <a href="https://github.com/kettle-dev"><img alt="kettle-dev Logo by Aboling0, CC BY-SA 4.0" src="https://logos.galtzo.com/assets/images/kettle-dev/avatar-128px.svg" width="14%" align="right"/></a>
75
75
 
@@ -1191,7 +1191,7 @@ Thanks for RTFM. ☺️
1191
1191
  [📌gitmoji]: https://gitmoji.dev
1192
1192
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
1193
1193
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
1194
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-8.121-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1194
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-8.163-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1195
1195
  [🔐security]: https://github.com/kettle-dev/kettle-family/blob/main/SECURITY.md
1196
1196
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
1197
1197
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -113,7 +113,7 @@ module Kettle
113
113
 
114
114
  def check_member(member, branch: nil, event_handler: nil)
115
115
  started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
116
- command = release_state_command
116
+ command = release_state_command(member)
117
117
  emit_event(event_handler, member: member, branch: branch, action: "member_start", status: "running", command: command)
118
118
  emit_event(event_handler, member: member, branch: branch, action: "changelog_command", status: "running", command: command)
119
119
  stdout, stderr, status = capture_release_state(
@@ -142,15 +142,16 @@ module Kettle
142
142
  emit_event(event_handler, member: member, branch: branch, action: "member_complete", status: success ? "ok" : "failed", elapsed_seconds: elapsed, status_code: status.exitstatus)
143
143
  result
144
144
  rescue JSON::ParserError => error
145
- result = result(member: member, command: command || release_state_command, stdout: stdout, stderr: stderr, status: 1, elapsed: elapsed || 0.0, success: false, state: {}, reason: "invalid release-state JSON: #{error.message}", branch: branch)
145
+ result = result(member: member, command: command || release_state_command(member), stdout: stdout, stderr: stderr, status: 1, elapsed: elapsed || 0.0, success: false, state: {}, reason: "invalid release-state JSON: #{error.message}", branch: branch)
146
146
  emit_event(event_handler, member: member, branch: branch, action: "member_complete", status: "failed", elapsed_seconds: elapsed || 0.0, status_code: 1, reason: result.reason)
147
147
  result
148
148
  end
149
149
 
150
- def release_state_command
151
- [RbConfig.ruby, kettle_changelog_executable, "--release-state", "--json"]
150
+ def release_state_command(member = nil)
151
+ version_args = member&.version ? ["--version", member.version.to_s] : []
152
+ [RbConfig.ruby, kettle_changelog_executable, *version_args, "--release-state", "--json"]
152
153
  rescue Gem::Exception
153
- [RbConfig.ruby, "-S", "kettle-changelog", "--release-state", "--json"]
154
+ [RbConfig.ruby, "-S", "kettle-changelog", *version_args, "--release-state", "--json"]
154
155
  end
155
156
 
156
157
  def kettle_changelog_executable
@@ -176,7 +177,7 @@ module Kettle
176
177
 
177
178
  def check_shared_changelog_member(member, branch: nil, event_handler: nil)
178
179
  started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
179
- command = release_state_command
180
+ command = release_state_command(member)
180
181
  emit_event(event_handler, member: member, branch: branch, action: "member_start", status: "running", command: command)
181
182
  emit_event(event_handler, member: member, branch: branch, action: "changelog_command", status: "running", command: command)
182
183
  stdout, stderr, status = capture_release_state(
@@ -216,13 +217,13 @@ module Kettle
216
217
  emit_event(event_handler, member: member, branch: branch, action: "member_complete", status: success ? "ok" : "failed", elapsed_seconds: elapsed, status_code: status.exitstatus)
217
218
  result
218
219
  rescue JSON::ParserError => error
219
- result = result(member: member, command: command || release_state_command, stdout: stdout, stderr: stderr, status: 1, elapsed: elapsed || 0.0, success: false, state: {}, reason: "invalid release-state JSON: #{error.message}", branch: branch)
220
+ result = result(member: member, command: command || release_state_command(member), stdout: stdout, stderr: stderr, status: 1, elapsed: elapsed || 0.0, success: false, state: {}, reason: "invalid release-state JSON: #{error.message}", branch: branch)
220
221
  emit_event(event_handler, member: member, branch: branch, action: "member_complete", status: "failed", elapsed_seconds: elapsed || 0.0, status_code: 1, reason: result.reason)
221
222
  result
222
223
  rescue Error => error
223
224
  result = result(
224
225
  member: member,
225
- command: command || release_state_command,
226
+ command: command || release_state_command(member),
226
227
  stdout: "",
227
228
  stderr: error.message,
228
229
  status: 1,
@@ -804,8 +805,6 @@ module Kettle
804
805
  return unless member_config
805
806
 
806
807
  current_result = check_member(member, event_handler: event_handler)
807
- return [current_result] unless current_result.ok?
808
-
809
808
  [current_result, *self.class.new(config: member_config, members: [member]).results(event_handler: event_handler)]
810
809
  end
811
810
 
@@ -125,7 +125,7 @@ module Kettle
125
125
  lines << " #{result_state(result)} #{result_identity(result)} #{result.phase} #{result.reason || ""}".rstrip
126
126
  append_result_stdout(lines, result)
127
127
  append_indented_output(lines, result.stderr) if !result.ok? && !result.stderr.to_s.empty?
128
- resume_hint = resume_hint_for(result)
128
+ resume_hint = resume_hint_for(result) unless command == "template"
129
129
  lines << " resume: #{resume_hint}" if !result.ok? && resume_hint
130
130
  end
131
131
  append_template_summary(lines) if command == "template"
@@ -764,11 +764,10 @@ module Kettle
764
764
  failed ? [resume_hint_for(failed)] : []
765
765
  end
766
766
 
767
- # Mirrors release_resume_hints: one hint per failure, plus a single set-based
768
- # hint naming every member that never ran. --only selects by name rather
769
- # than position, so it resumes exactly the unfinished members regardless of
770
- # how dispatch ordered them, and the wave grouping is re-derived from the
771
- # selected subset.
767
+ # Test gets one hint per failure plus a set-based hint for members that never
768
+ # ran. --only selects by name rather than position, so it resumes exactly the
769
+ # unfinished members regardless of how dispatch ordered them. Template uses
770
+ # one combined hint because it is idempotent and family-lockstep.
772
771
  #
773
772
  # A family-root failure takes precedence and suppresses the set-based hint:
774
773
  # that phase aborts the entire run before member dispatch, so every member
@@ -776,6 +775,7 @@ module Kettle
776
775
  def non_positional_resume_hints
777
776
  root_failure = results.find { |result| !result.ok? && family_root_phase?(result.phase) }
778
777
  return [resume_hint_for(root_failure)] if root_failure
778
+ return template_resume_hints if command == "template"
779
779
 
780
780
  failed_hints = visible_results.reject(&:ok?).filter_map { |result| resume_hint_for(result) }.uniq
781
781
  pending_names = summary_pending.map { |entry| entry.fetch("member") }
@@ -784,6 +784,15 @@ module Kettle
784
784
  [*failed_hints, "kettle-family #{command} --only #{pending_names.join(",")}"]
785
785
  end
786
786
 
787
+ def template_resume_hints
788
+ member_names = visible_results.reject(&:ok?).map { |result| result_identity(result) }
789
+ member_names.concat(summary_pending.map { |entry| entry.fetch("member") })
790
+ member_names = member_names.compact.uniq.sort
791
+ return ["kettle-family template"] if member_names.empty?
792
+
793
+ ["kettle-family template --only #{member_names.join(",")}"]
794
+ end
795
+
787
796
  def release_resume_hints
788
797
  failed_hints = visible_results.reject(&:ok?).filter_map { |result| resume_hint_for(result) }.uniq
789
798
  pending_names = summary_pending.map { |entry| entry.fetch("member") }
@@ -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.35"
8
+ VERSION = "1.3.36"
9
9
  end
10
10
  # Current gem version exposed at the traditional constant location.
11
11
  VERSION = Version::VERSION # Traditional Constant Location
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "kettle/dev"
4
+ require "ast/crispr/ruby/prism"
4
5
 
5
6
  module Kettle
6
7
  module Family
@@ -74,12 +75,20 @@ module Kettle
74
75
  end
75
76
 
76
77
  def collect_edits(member, member_target_version)
77
- version_edits = with_dev_errors do
78
- Kettle::Dev::VersionBump.new(
79
- root: member.root,
80
- current_version: member.version,
81
- target_version: member_target_version
82
- ).edits
78
+ begin
79
+ version_edits = with_dev_errors do
80
+ Kettle::Dev::VersionBump.new(
81
+ root: member.root,
82
+ current_version: member.version,
83
+ target_version: member_target_version
84
+ ).edits
85
+ end
86
+ rescue Error => error
87
+ bump = Kettle::Dev::VersionBump.new(root: member.root, current_version: member.version, target_version: member_target_version)
88
+ computed_version_edits = prism_computed_version_edits(member, member_target_version)
89
+ raise error if computed_version_edits.empty?
90
+
91
+ version_edits = computed_version_edits + bump.send(:gemspec_version_edits)
83
92
  end
84
93
  version_edits = version_edits.map do |edit|
85
94
  if same_file?(edit.fetch(:path), member.gemspec_path)
@@ -91,6 +100,33 @@ module Kettle
91
100
  version_edits + gemspec_dependency_edits(member)
92
101
  end
93
102
 
103
+ def prism_computed_version_edits(member, target_version)
104
+ version = Gem::Version.new(target_version)
105
+ replacements = {major: version.segments[0] || 0, minor: version.segments[1] || 0, patch: version.segments[2] || 0}
106
+ Kettle::Dev::Versioning.version_file_candidates(member.root).flat_map do |path|
107
+ source = File.read(path)
108
+ analysis = Ast::Crispr::Ruby::Prism.document_context(content: source, source_label: path).ast
109
+ root = analysis.parse_result.value
110
+ nodes = Kettle::Dev::VersionBump.each_node(root).to_a
111
+ version_constant = nodes.find do |node|
112
+ node.is_a?(Prism::ConstantWriteNode) && node.name == :VERSION && node.value.is_a?(Prism::CallNode) && node.value.name == :to_s
113
+ end
114
+ next [] unless version_constant
115
+
116
+ replacements.filter_map do |method_name, replacement_value|
117
+ method = nodes.find { |node| node.is_a?(Prism::DefNode) && node.name == method_name }
118
+ literal = method&.body&.body&.last
119
+ next unless literal.is_a?(Prism::IntegerNode) || literal.is_a?(Prism::StringNode)
120
+
121
+ next if literal.is_a?(Prism::IntegerNode) && literal.value == replacement_value
122
+ next if literal.is_a?(Prism::StringNode) && literal.unescaped == replacement_value.to_s
123
+
124
+ replacement = literal.is_a?(Prism::StringNode) ? Kettle::Dev::VersionBump.quote_like(literal.location.slice, replacement_value.to_s) : replacement_value.to_s
125
+ Kettle::Dev::VersionBump.file_edit(path, source, literal.location.start_offset, literal.location.end_offset, replacement)
126
+ end
127
+ end
128
+ end
129
+
94
130
  def same_file?(left, right)
95
131
  right && File.identical?(left, right)
96
132
  rescue SystemCallError
@@ -3789,6 +3789,7 @@ module Kettle
3789
3789
  def append_kettle_release_args(command, member: nil)
3790
3790
  command = replace_kettle_release_provider(command) if @release_secrets_broker
3791
3791
  args = []
3792
+ args << "--version=#{member.version}" if member&.version && !command_includes_arg?(command, "--version")
3792
3793
  effective_start_step = release_start_step_for(member)
3793
3794
  command, configured_skip_steps = extract_kettle_release_skip_steps(command)
3794
3795
  effective_skip_steps = (configured_skip_steps + release_skip_steps_for(member).split(",")).uniq.join(",")
data.tar.gz.sig CHANGED
Binary file
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.35
4
+ version: 1.3.36
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -57,6 +57,26 @@ dependencies:
57
57
  - - ">="
58
58
  - !ruby/object:Gem::Version
59
59
  version: 7.1.11
60
+ - !ruby/object:Gem::Dependency
61
+ name: ast-crispr-ruby-prism
62
+ requirement: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - "~>"
65
+ - !ruby/object:Gem::Version
66
+ version: '7.1'
67
+ - - ">="
68
+ - !ruby/object:Gem::Version
69
+ version: 7.1.10
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - "~>"
75
+ - !ruby/object:Gem::Version
76
+ version: '7.1'
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: 7.1.10
60
80
  - !ruby/object:Gem::Dependency
61
81
  name: ast-crispr-toml
62
82
  requirement: !ruby/object:Gem::Requirement
@@ -114,7 +134,7 @@ dependencies:
114
134
  version: '1.0'
115
135
  - - ">="
116
136
  - !ruby/object:Gem::Version
117
- version: 1.0.14
137
+ version: 1.0.15
118
138
  type: :runtime
119
139
  prerelease: false
120
140
  version_requirements: !ruby/object:Gem::Requirement
@@ -124,7 +144,7 @@ dependencies:
124
144
  version: '1.0'
125
145
  - - ">="
126
146
  - !ruby/object:Gem::Version
127
- version: 1.0.14
147
+ version: 1.0.15
128
148
  - !ruby/object:Gem::Dependency
129
149
  name: kettle-deps-floor
130
150
  requirement: !ruby/object:Gem::Requirement
@@ -134,7 +154,7 @@ dependencies:
134
154
  version: '0.1'
135
155
  - - ">="
136
156
  - !ruby/object:Gem::Version
137
- version: 0.1.1
157
+ version: 0.1.2
138
158
  type: :runtime
139
159
  prerelease: false
140
160
  version_requirements: !ruby/object:Gem::Requirement
@@ -144,7 +164,7 @@ dependencies:
144
164
  version: '0.1'
145
165
  - - ">="
146
166
  - !ruby/object:Gem::Version
147
- version: 0.1.1
167
+ version: 0.1.2
148
168
  - !ruby/object:Gem::Dependency
149
169
  name: kettle-dev
150
170
  requirement: !ruby/object:Gem::Requirement
@@ -154,7 +174,7 @@ dependencies:
154
174
  version: '3.1'
155
175
  - - ">="
156
176
  - !ruby/object:Gem::Version
157
- version: 3.1.25
177
+ version: 3.1.26
158
178
  type: :runtime
159
179
  prerelease: false
160
180
  version_requirements: !ruby/object:Gem::Requirement
@@ -164,7 +184,7 @@ dependencies:
164
184
  version: '3.1'
165
185
  - - ">="
166
186
  - !ruby/object:Gem::Version
167
- version: 3.1.25
187
+ version: 3.1.26
168
188
  - !ruby/object:Gem::Dependency
169
189
  name: kettle-gha-pins
170
190
  requirement: !ruby/object:Gem::Requirement
@@ -174,7 +194,7 @@ dependencies:
174
194
  version: '0.3'
175
195
  - - ">="
176
196
  - !ruby/object:Gem::Version
177
- version: 0.3.19
197
+ version: 0.3.20
178
198
  type: :runtime
179
199
  prerelease: false
180
200
  version_requirements: !ruby/object:Gem::Requirement
@@ -184,7 +204,7 @@ dependencies:
184
204
  version: '0.3'
185
205
  - - ">="
186
206
  - !ruby/object:Gem::Version
187
- version: 0.3.19
207
+ version: 0.3.20
188
208
  - !ruby/object:Gem::Dependency
189
209
  name: kettle-jem
190
210
  requirement: !ruby/object:Gem::Requirement
@@ -608,10 +628,10 @@ licenses:
608
628
  - AGPL-3.0-only
609
629
  metadata:
610
630
  homepage_uri: https://kettle-family.galtzo.com
611
- source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.3.35
612
- changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.3.35/CHANGELOG.md
631
+ source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.3.36
632
+ changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.3.36/CHANGELOG.md
613
633
  bug_tracker_uri: https://github.com/kettle-dev/kettle-family/issues
614
- documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.3.35
634
+ documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.3.36
615
635
  funding_uri: https://github.com/sponsors/pboling
616
636
  wiki_uri: https://github.com/kettle-dev/kettle-family/wiki
617
637
  news_uri: https://www.railsbling.com/tags/kettle-family
metadata.gz.sig CHANGED
Binary file