kettle-dev 2.2.6 → 2.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b8c22a00d9dde1e8574e1b8018fcf356b683c5a0c558b304bfac6d4b307d2de1
4
- data.tar.gz: 69b132d5faa7e4d07f52344491295fb349e1453b2aa43b2de2ae25fbff21a9a2
3
+ metadata.gz: 20e42b5ed4a5e7b52a046fa7cfdfe63c08963947c2414aa4cf22251419ffb853
4
+ data.tar.gz: e578b54456e497e115ccdb9bb54efc4d32be13e2b294d2b0857964b75bc5c7ff
5
5
  SHA512:
6
- metadata.gz: 0f0c9b87d7bc0cf30712c3e6cbbedabd66d6af631ed39586fe7853f78970b3b8ea80e18c78130394c323f3d09d61cf7b5c39d9c1927ed71fe9fb30a3e1c7453d
7
- data.tar.gz: 7eb506783c68f81ac54ae37b54d4b415d996f1a2f50ce112c2733cd0726ca55088b3875c281743aa8eed389243d4049ca01f07f2a0211cc99b4f462ff17a4c5e
6
+ metadata.gz: 676baf6a4ecffe8745d94c3016b402e8c002f98ca61f9ea478b9e629d42c7c57a82795682d49c853c19fff74982e8c70af5cf75b1e0eb6b28ce2fb904995762e
7
+ data.tar.gz: a000e3b43e2ea900fcdb03cb2471db4a8c312113c753524ca7be658119c81bba1cfb7113e0ccb576a2cf6b471c472fc01c6b71afc4eebf7322b3760e3a848c4c
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,40 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [2.2.8] - 2026-06-13
34
+
35
+ - TAG: [v2.2.8][2.2.8t]
36
+ - COVERAGE: 92.40% -- 3854/4171 lines in 28 files
37
+ - BRANCH COVERAGE: 73.37% -- 1521/2073 branches in 28 files
38
+ - 66.02% documented
39
+
40
+ ### Fixed
41
+
42
+ #### Changelog
43
+
44
+ - `kettle-changelog --release-state` now reports a clear family-root hint when
45
+ run outside a single gem instead of raising a missing `CHANGELOG.md` stack
46
+ trace.
47
+ - `kettle-changelog --release-state` now reports a successful no-changelog state
48
+ for individual gems that do not have a `CHANGELOG.md`.
49
+
50
+ ## [2.2.7] - 2026-06-13
51
+
52
+ - TAG: [v2.2.7][2.2.7t]
53
+ - COVERAGE: 92.36% -- 3843/4161 lines in 28 files
54
+ - BRANCH COVERAGE: 73.54% -- 1520/2067 branches in 28 files
55
+ - 66.02% documented
56
+
57
+ ### Added
58
+
59
+ #### Changelog
60
+
61
+ - Added `kettle-changelog --release-state` / `--release-status` with optional
62
+ `--json` output for single-gem changelog release state reporting.
63
+ - Added a richer `Kettle::Dev::ChangelogCLI#release_state` API that reports the
64
+ latest released version, latest changelog release section, and pending
65
+ changelog sources.
66
+
33
67
  ## [2.2.6] - 2026-06-13
34
68
 
35
69
  - TAG: [v2.2.6][2.2.6t]
@@ -2075,7 +2109,11 @@ Please file a bug if you notice a violation of semantic versioning.
2075
2109
  - Selecting will run the selected workflow via `act`
2076
2110
  - This may move to its own gem in the future.
2077
2111
 
2078
- [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.6...HEAD
2112
+ [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.8...HEAD
2113
+ [2.2.8]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.7...v2.2.8
2114
+ [2.2.8t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.2.8
2115
+ [2.2.7]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.6...v2.2.7
2116
+ [2.2.7t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.2.7
2079
2117
  [2.2.6]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.5...v2.2.6
2080
2118
  [2.2.6t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.2.6
2081
2119
  [2.2.5]: https://github.com/kettle-dev/kettle-dev/compare/v2.2.4...v2.2.5
data/README.md CHANGED
@@ -854,7 +854,7 @@ Thanks for RTFM. ☺️
854
854
  [📌gitmoji]: https://gitmoji.dev
855
855
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
856
856
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
857
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-4.154-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
857
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-4.171-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
858
858
  [🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
859
859
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
860
860
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
data/exe/kettle-changelog CHANGED
@@ -41,7 +41,7 @@ begin
41
41
 
42
42
  # This library
43
43
  require "kettle/dev"
44
- puts "== #{script_basename} v#{Kettle::Dev::Version::VERSION} =="
44
+ puts "== #{script_basename} v#{Kettle::Dev::Version::VERSION} ==" unless ARGV.include?("--json")
45
45
  rescue LoadError => e
46
46
  warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
47
47
  warn("Hint: Ensure the host project has kettle-dev as a dependency and run bundle install.")
@@ -51,7 +51,7 @@ end
51
51
  begin
52
52
  if ARGV.include?("-h") || ARGV.include?("--help")
53
53
  puts <<~USAGE
54
- Usage: kettle-changelog [--update-prep] [--pending-release] [--no-strict] [--no-coverage-threshold]
54
+ Usage: kettle-changelog [--update-prep] [--pending-release] [--release-state] [--json] [--no-strict] [--no-coverage-threshold]
55
55
 
56
56
  Detects the current version from lib/**/version.rb, the latest live release, and
57
57
  the most recent CHANGELOG.md release section, then prompts to confirm the selected plan:
@@ -63,6 +63,9 @@ begin
63
63
  Options:
64
64
  --update-prep Force updating the most recent prepared release section in place
65
65
  --pending-release Query whether the changelog has release work pending; exits 0 for yes, 1 for no
66
+ --release-state,
67
+ --release-status Print changelog release state, including latest published release and pending sources
68
+ --json Print query output as JSON
66
69
  --no-strict Allow missing coverage and yard data (warnings only, no errors)
67
70
  --no-coverage-threshold Generate coverage without hard-failing below configured thresholds
68
71
 
@@ -92,14 +95,29 @@ begin
92
95
  strict_mode = !ARGV.include?("--no-strict") && ENV.fetch("K_CHANGELOG_STRICT", "true").downcase != "false"
93
96
  update_prep = ARGV.delete("--update-prep")
94
97
  pending_release_query = ARGV.delete("--pending-release")
98
+ release_state_query = ARGV.delete("--release-state") || ARGV.delete("--release-status")
99
+ json_output = ARGV.delete("--json")
95
100
  coverage_threshold_disabled = ARGV.include?("--no-coverage-threshold") || ARGV.include?("--no-coverage-thresholds")
96
101
  coverage_hard = !coverage_threshold_disabled && ENV.fetch("K_CHANGELOG_COVERAGE_HARD", "true").downcase != "false"
97
102
 
98
103
  cli = Kettle::Dev::ChangelogCLI.new(strict: strict_mode, enforce_coverage_thresholds: coverage_hard, update_prep: update_prep)
104
+ if release_state_query
105
+ state = cli.release_state
106
+ puts(json_output ? JSON.pretty_generate(state) : cli.release_state_table(state))
107
+ exit(0)
108
+ end
109
+
99
110
  if pending_release_query
100
- status = cli.pending_release_status
101
- puts status.fetch(:pending) ? "true" : "false"
102
- exit(status.fetch(:pending) ? 0 : 1)
111
+ state = cli.pending_release_status
112
+ output = if json_output
113
+ JSON.pretty_generate(state)
114
+ elsif state.fetch(:pending_release)
115
+ "true"
116
+ else
117
+ "false"
118
+ end
119
+ puts(output)
120
+ exit(state.fetch(:pending_release) ? 0 : 1)
103
121
  end
104
122
 
105
123
  cli.run
@@ -24,8 +24,8 @@ module Kettle
24
24
  # @param strict [Boolean] when true (default), require coverage and yard data; raise errors if unavailable
25
25
  # @param enforce_coverage_thresholds [Boolean] when true, fail strict coverage generation below project thresholds
26
26
  # @param update_prep [Boolean] when true, update the most recent prepared release section in place
27
- def initialize(strict: true, enforce_coverage_thresholds: true, update_prep: false)
28
- @root = Kettle::Dev::CIHelpers.project_root
27
+ def initialize(strict: true, enforce_coverage_thresholds: true, update_prep: false, root: Kettle::Dev::CIHelpers.project_root)
28
+ @root = root
29
29
  @changelog_path = File.join(@root, "CHANGELOG.md")
30
30
  @coverage_path = File.join(@root, "coverage", "coverage.json")
31
31
  @strict = strict
@@ -136,46 +136,101 @@ module Kettle
136
136
  end
137
137
 
138
138
  def pending_release_status
139
+ release_state
140
+ end
141
+
142
+ def release_state
143
+ changelog_present = ensure_changelog_for_release_state!
144
+ version = detect_version
145
+ gem_name = detect_gem_name
146
+ unless changelog_present
147
+ latest_overall, latest_for_series = latest_released_versions(gem_name, version)
148
+ latest_target = latest_release_target(version, latest_overall, latest_for_series)
149
+ return {
150
+ root: @root,
151
+ gem_name: gem_name,
152
+ version: version,
153
+ changelog_present: false,
154
+ pending: false,
155
+ pending_release: false,
156
+ unreleased_entries: false,
157
+ prepared_release_pending: false,
158
+ latest_changelog_version: nil,
159
+ latest_released: latest_overall,
160
+ latest_released_for_current_series: latest_for_series,
161
+ latest_release_target: latest_target
162
+ }
163
+ end
164
+
139
165
  changelog = File.read(@changelog_path)
140
166
  unreleased_block, _before, after = extract_unreleased(changelog)
141
167
  unreleased_entries = unreleased_block_has_entries?(unreleased_block)
142
168
  latest_changelog_version = detect_previous_version(after.to_s)
143
- gem_name = nil
144
- latest_overall = nil
145
- latest_for_series = nil
146
- latest_target = nil
147
-
148
- if latest_changelog_version && !unreleased_entries
149
- begin
150
- gem_name = detect_gem_name
151
- latest_overall, latest_for_series = latest_released_versions(gem_name, latest_changelog_version)
152
- latest_target = latest_release_target(latest_changelog_version, latest_overall, latest_for_series)
153
- rescue => e
154
- warn("[kettle-changelog] gem.coop release check failed: #{e.class}: #{e.message}")
155
- warn("Treating the most recent CHANGELOG.md release section as pending because live release info is unavailable.")
156
- end
157
- end
158
-
159
- prepared_release_pending = !unreleased_entries && !!latest_changelog_version && latest_target != latest_changelog_version
169
+ release_lookup_version = latest_changelog_version || version
170
+ latest_overall, latest_for_series = latest_released_versions(gem_name, release_lookup_version)
171
+ latest_target = latest_release_target(release_lookup_version, latest_overall, latest_for_series)
172
+ prepared_release_pending = !!latest_changelog_version && latest_target != latest_changelog_version
160
173
 
161
174
  {
175
+ root: @root,
176
+ gem_name: gem_name,
177
+ version: version,
178
+ changelog_present: true,
162
179
  pending: unreleased_entries || prepared_release_pending,
180
+ pending_release: unreleased_entries || prepared_release_pending,
163
181
  unreleased_entries: unreleased_entries,
164
182
  prepared_release_pending: prepared_release_pending,
165
183
  latest_changelog_version: latest_changelog_version,
166
184
  latest_released: latest_overall,
167
185
  latest_released_for_current_series: latest_for_series,
168
- latest_release_target: latest_target,
169
- gem_name: gem_name
186
+ latest_release_target: latest_target
170
187
  }
171
188
  end
172
189
 
190
+ def release_state_table(state = release_state)
191
+ rows = [
192
+ ["gem", "version.rb", "latest released", "latest changelog", "unreleased", "prepared", "pending"],
193
+ [
194
+ state.fetch(:gem_name),
195
+ state.fetch(:version),
196
+ state.fetch(:latest_released) || "unknown",
197
+ state.fetch(:latest_changelog_version) || "none",
198
+ yes_no(state.fetch(:unreleased_entries)),
199
+ yes_no(state.fetch(:prepared_release_pending)),
200
+ yes_no(state.fetch(:pending_release))
201
+ ]
202
+ ]
203
+ widths = rows.transpose.map { |column| column.map(&:length).max }
204
+ rows.map.with_index do |row, index|
205
+ line = row.each_with_index.map { |value, i| value.ljust(widths.fetch(i)) }.join(" ").rstrip
206
+ if index == 0
207
+ [line, widths.map { |width| "-" * width }.join(" ")].join("\n")
208
+ else
209
+ line
210
+ end
211
+ end.join("\n")
212
+ end
213
+
173
214
  private
174
215
 
175
216
  def abort(msg)
176
217
  Kettle::Dev::ExitAdapter.abort(msg)
177
218
  end
178
219
 
220
+ def ensure_changelog_for_release_state!
221
+ return true if File.file?(@changelog_path)
222
+
223
+ if File.file?(File.join(@root, "Gemfile")) && Dir.glob(File.join(@root, "*", "*.gemspec")).any?
224
+ abort("Could not find CHANGELOG.md in #{Kettle::Dev.display_path(@root)}. This looks like a gem-family root; run `kettle-family release-state` from this directory, or run `kettle-changelog --release-state` from an individual gem directory.")
225
+ end
226
+
227
+ false
228
+ end
229
+
230
+ def yes_no(value)
231
+ value ? "yes" : "no"
232
+ end
233
+
179
234
  def detect_plan(changelog, version)
180
235
  latest_overall = nil
181
236
  latest_for_series = nil
@@ -3,7 +3,7 @@
3
3
  module Kettle
4
4
  module Dev
5
5
  module Version
6
- VERSION = "2.2.6"
6
+ VERSION = "2.2.8"
7
7
  end
8
8
  VERSION = Version::VERSION # Traditional Constant Location
9
9
  end
@@ -10,13 +10,17 @@ module Kettle
10
10
  @changelog_path: String
11
11
  @coverage_path: String
12
12
 
13
- def initialize: () -> void
13
+ def initialize: (?strict: bool, ?enforce_coverage_thresholds: bool, ?update_prep: bool, ?root: String) -> void
14
14
 
15
15
  # Main entry point that updates CHANGELOG.md
16
16
  def run: () -> void
17
17
 
18
18
  def pending_release_status: () -> Hash[Symbol, untyped]
19
19
 
20
+ def release_state: () -> Hash[Symbol, untyped]
21
+
22
+ def release_state_table: (?Hash[Symbol, untyped] state) -> String
23
+
20
24
  private
21
25
 
22
26
  # Abort with error message
data.tar.gz.sig CHANGED
Binary file
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kettle-dev
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.6
4
+ version: 2.2.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -338,10 +338,10 @@ licenses:
338
338
  - AGPL-3.0-only
339
339
  metadata:
340
340
  homepage_uri: https://kettle-dev.galtzo.com
341
- source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.2.6
342
- changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.2.6/CHANGELOG.md
341
+ source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.2.8
342
+ changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.2.8/CHANGELOG.md
343
343
  bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
344
- documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.2.6
344
+ documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.2.8
345
345
  funding_uri: https://github.com/sponsors/pboling
346
346
  wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
347
347
  news_uri: https://www.railsbling.com/tags/kettle-dev
metadata.gz.sig CHANGED
Binary file