kettle-family 1.1.8 → 1.1.9
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 +32 -1
- data/README.md +1 -1
- data/lib/kettle/family/cli.rb +11 -2
- data/lib/kettle/family/release_state_check.rb +76 -1
- data/lib/kettle/family/report.rb +18 -2
- data/lib/kettle/family/version.rb +1 -1
- data/lib/kettle/family/workflow.rb +5 -1
- data.tar.gz.sig +0 -0
- metadata +24 -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: a7a1fef6a9376e6ea7f3d4f2ecd61bf5a610fdb1585037ce63631ef106ec6e24
|
|
4
|
+
data.tar.gz: aa9c89f697651bf26926575dde900f6ab070b487191f2ca6436ce04a3ad231c6
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 11993355cf52d83e6bbbdae954983f7e10233968fece69a812c62ea5c1787112ba825e2eed207c12a06d44abb3af6199af5f3a11647733845abd8ba76ed25335
|
|
7
|
+
data.tar.gz: 7abbd03f4c8f434c8a069dc92d6c4eb66b06b81adb73d2454cf5fc0be9dbcb5335201b248173c15d91fcff699761e408303be2c7887fdabd1a07b2dd63e38ec8
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,35 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [1.1.9] - 2026-07-25
|
|
34
|
+
|
|
35
|
+
- TAG: [v1.1.9][1.1.9t]
|
|
36
|
+
- COVERAGE: 95.23% -- 3197/3357 lines in 25 files
|
|
37
|
+
- BRANCH COVERAGE: 77.20% -- 1192/1544 branches in 25 files
|
|
38
|
+
- 28.16% documented
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- `kettle-family state` now marks mismatched GitHub release tags and reports
|
|
43
|
+
kettle-jem transfer changelog replay lag in a `T📰` column.
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- Bare `kettle-family bump` now defaults to `--only bump`, and bare
|
|
48
|
+
`kettle-family release` now defaults to `--only pending`.
|
|
49
|
+
|
|
50
|
+
- kettle-jem-template-20260725-002 - Generated gemspec templates now include
|
|
51
|
+
`anonymous_loader` as a development dependency, and version specs use it to
|
|
52
|
+
execute generated `version.rb` files for coverage without redefining package
|
|
53
|
+
constants. Managed version specs are removed when `version_gem` is disabled
|
|
54
|
+
or incompatible with the project's runtime Ruby floor.
|
|
55
|
+
|
|
56
|
+
### Fixed
|
|
57
|
+
|
|
58
|
+
- Monorepo templating now passes a shared Git operation lock to `kettle-jem`,
|
|
59
|
+
allowing template workers to serialize repo-wide Git config/index mutations
|
|
60
|
+
instead of only bootstrap commits.
|
|
61
|
+
|
|
33
62
|
## [1.1.8] - 2026-07-25
|
|
34
63
|
|
|
35
64
|
- TAG: [v1.1.8][1.1.8t]
|
|
@@ -1043,7 +1072,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
1043
1072
|
- Fixed CI load failures on engines without compatible `pty` support by falling back to Open3 for interactive release commands.
|
|
1044
1073
|
- Fixed Ruby 3.2 version-bump support by loading Prism lazily and wiring the Prism gem only for MRI versions that need it.
|
|
1045
1074
|
|
|
1046
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.1.
|
|
1075
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.1.9...HEAD
|
|
1076
|
+
[1.1.9]: https://github.com/kettle-dev/kettle-family/compare/v1.1.8...v1.1.9
|
|
1077
|
+
[1.1.9t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.1.9
|
|
1047
1078
|
[1.1.8]: https://github.com/kettle-dev/kettle-family/compare/v1.1.7...v1.1.8
|
|
1048
1079
|
[1.1.8t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.1.8
|
|
1049
1080
|
[1.1.7]: https://github.com/kettle-dev/kettle-family/compare/v1.1.6...v1.1.7
|
data/README.md
CHANGED
|
@@ -669,7 +669,7 @@ Thanks for RTFM. ☺️
|
|
|
669
669
|
[📌gitmoji]: https://gitmoji.dev
|
|
670
670
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
671
671
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
672
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-3.
|
|
672
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-3.357-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
673
673
|
[🔐security]: https://github.com/kettle-dev/kettle-family/blob/main/SECURITY.md
|
|
674
674
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
675
675
|
[📄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
|
@@ -560,8 +560,9 @@ module Kettle
|
|
|
560
560
|
else
|
|
561
561
|
Orderer.new(members: members, mode: config.order_mode, hints: config.order_hints).ordered
|
|
562
562
|
end
|
|
563
|
-
|
|
564
|
-
|
|
563
|
+
effective_only = default_only_filter(command: command, only: options[:only])
|
|
564
|
+
release_state_results = release_state_results_for_selection(config: config, members: ordered, only: effective_only)
|
|
565
|
+
selected = Selection.new(members: ordered, release_state_results: release_state_results).apply(only: effective_only, exclude: options[:exclude], start_at: start_at.member)
|
|
565
566
|
result_members = selected
|
|
566
567
|
results = command_results(command: command, config: config, members: result_members, options: options, start_at: start_at)
|
|
567
568
|
Report.new(
|
|
@@ -595,6 +596,14 @@ module Kettle
|
|
|
595
596
|
ReleaseStateCheck.new(config: config, members: members).results
|
|
596
597
|
end
|
|
597
598
|
|
|
599
|
+
def default_only_filter(command:, only:)
|
|
600
|
+
return only unless only.to_s.empty?
|
|
601
|
+
return "bump" if %w[bump bump-version].include?(command)
|
|
602
|
+
return "pending" if command == "release"
|
|
603
|
+
|
|
604
|
+
only
|
|
605
|
+
end
|
|
606
|
+
|
|
598
607
|
def command_results_for_current_branch(command:, config:, members:, options:, start_at: StartAt.new(nil, nil))
|
|
599
608
|
return bump_version_results(members: members, options: options, phase: command) if %w[bump bump-version].include?(command)
|
|
600
609
|
return add_changelog_results(members: members, options: options) if command == "add-changelog"
|
|
@@ -6,14 +6,18 @@ require "open3"
|
|
|
6
6
|
require "rbconfig"
|
|
7
7
|
require "rubygems"
|
|
8
8
|
require "securerandom"
|
|
9
|
+
require "yaml"
|
|
9
10
|
|
|
10
11
|
module Kettle
|
|
11
12
|
module Family
|
|
12
13
|
class ReleaseStateCheck
|
|
14
|
+
KETTLE_JEM_CONFIG_PATHS = [".structuredmerge/kettle-jem.yml", ".kettle-jem.yml"].freeze
|
|
15
|
+
|
|
13
16
|
def initialize(members:, config: nil)
|
|
14
17
|
@members = members
|
|
15
18
|
@config = config
|
|
16
19
|
@github_latest_release_by_repo = {}
|
|
20
|
+
@transfer_changelog_lag_by_key = {}
|
|
17
21
|
end
|
|
18
22
|
|
|
19
23
|
def results
|
|
@@ -63,6 +67,7 @@ module Kettle
|
|
|
63
67
|
state = state_with_computed_booleans(state) if success
|
|
64
68
|
state = enrich_git_state(member.root, state) if success
|
|
65
69
|
state = enrich_github_release(member.root, state) if success
|
|
70
|
+
state = enrich_transfer_changelog_lag(member.root, state) if success
|
|
66
71
|
result(member: member, command: command, stdout: stdout, stderr: stderr, status: status.exitstatus, elapsed: elapsed, success: success, state: state, branch: branch)
|
|
67
72
|
rescue JSON::ParserError => error
|
|
68
73
|
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)
|
|
@@ -88,6 +93,7 @@ module Kettle
|
|
|
88
93
|
state = branch_filtered_state(member, state, branch) if success && branch
|
|
89
94
|
state = enrich_git_state(member.root, state) if success
|
|
90
95
|
state = enrich_github_release(member.root, state) if success
|
|
96
|
+
state = enrich_transfer_changelog_lag(member.root, state) if success
|
|
91
97
|
result(
|
|
92
98
|
member: member,
|
|
93
99
|
command: command,
|
|
@@ -283,7 +289,7 @@ module Kettle
|
|
|
283
289
|
unreleased_entries = unreleased_entries?(content)
|
|
284
290
|
prepared_release_pending = !version.to_s.empty? && latest_changelog_version == version
|
|
285
291
|
ahead = commits_ahead_of_release(root, latest_changelog_version)
|
|
286
|
-
enrich_github_release(root, state_with_computed_booleans(enrich_git_state(root, {
|
|
292
|
+
state = enrich_github_release(root, state_with_computed_booleans(enrich_git_state(root, {
|
|
287
293
|
"gem_name" => config.family_name,
|
|
288
294
|
"version" => version,
|
|
289
295
|
"latest_released" => nil,
|
|
@@ -293,6 +299,7 @@ module Kettle
|
|
|
293
299
|
"prepared_release_pending" => prepared_release_pending,
|
|
294
300
|
"pending_release" => unreleased_entries || prepared_release_pending
|
|
295
301
|
})))
|
|
302
|
+
enrich_transfer_changelog_lag(root, state)
|
|
296
303
|
end
|
|
297
304
|
|
|
298
305
|
def state_with_computed_booleans(state)
|
|
@@ -312,6 +319,74 @@ module Kettle
|
|
|
312
319
|
state.merge("github_latest_release" => tag)
|
|
313
320
|
end
|
|
314
321
|
|
|
322
|
+
def enrich_transfer_changelog_lag(root, state)
|
|
323
|
+
kettle_jem_state = kettle_jem_config_state(root)
|
|
324
|
+
return state unless kettle_jem_state
|
|
325
|
+
|
|
326
|
+
replay = kettle_jem_state["changelog_replay"]
|
|
327
|
+
replay = replay.is_a?(Hash) ? replay : {}
|
|
328
|
+
last_entry_key = replay["last_entry_key"] || replay[:last_entry_key]
|
|
329
|
+
lag = transfer_changelog_lag(last_entry_key)
|
|
330
|
+
return state unless lag
|
|
331
|
+
|
|
332
|
+
state.merge("transfer_changelog_lag" => lag.fetch("missing_count", 0).to_i)
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
def kettle_jem_config_state(root)
|
|
336
|
+
path = KETTLE_JEM_CONFIG_PATHS.map { |relative| File.join(root.to_s, relative) }.find { |candidate| File.file?(candidate) }
|
|
337
|
+
return nil unless path
|
|
338
|
+
|
|
339
|
+
data = YAML.safe_load_file(path, permitted_classes: [], aliases: false)
|
|
340
|
+
state = data.is_a?(Hash) ? data["kettle-jem"] : nil
|
|
341
|
+
state.is_a?(Hash) ? state : {}
|
|
342
|
+
rescue Psych::Exception, SystemCallError
|
|
343
|
+
nil
|
|
344
|
+
end
|
|
345
|
+
|
|
346
|
+
def transfer_changelog_lag(last_entry_key)
|
|
347
|
+
cache_key = last_entry_key.to_s
|
|
348
|
+
@transfer_changelog_lag_by_key.fetch(cache_key) do
|
|
349
|
+
@transfer_changelog_lag_by_key[cache_key] = in_process_transfer_changelog_lag(last_entry_key) || external_transfer_changelog_lag(cache_key)
|
|
350
|
+
end
|
|
351
|
+
rescue
|
|
352
|
+
nil
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
def in_process_transfer_changelog_lag(last_entry_key)
|
|
356
|
+
return nil unless load_kettle_jem_transfer_api
|
|
357
|
+
|
|
358
|
+
normalize_transfer_changelog_lag(::Kettle::Jem.transfer_changelog_lag(last_entry_key))
|
|
359
|
+
rescue
|
|
360
|
+
nil
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
def load_kettle_jem_transfer_api
|
|
364
|
+
return true if defined?(::Kettle::Jem) && ::Kettle::Jem.respond_to?(:transfer_changelog_lag)
|
|
365
|
+
|
|
366
|
+
require "kettle/jem"
|
|
367
|
+
defined?(::Kettle::Jem) && ::Kettle::Jem.respond_to?(:transfer_changelog_lag)
|
|
368
|
+
rescue LoadError
|
|
369
|
+
false
|
|
370
|
+
end
|
|
371
|
+
|
|
372
|
+
def external_transfer_changelog_lag(cache_key)
|
|
373
|
+
code = <<~RUBY
|
|
374
|
+
last_entry_key = ARGV.fetch(0, "")
|
|
375
|
+
last_entry_key = nil if last_entry_key.empty?
|
|
376
|
+
puts JSON.generate(Kettle::Jem.transfer_changelog_lag(last_entry_key))
|
|
377
|
+
RUBY
|
|
378
|
+
stdout, _stderr, status = Open3.capture3(RbConfig.ruby, "-rjson", "-rkettle/jem", "-e", code, cache_key)
|
|
379
|
+
status.success? ? normalize_transfer_changelog_lag(JSON.parse(stdout)) : nil
|
|
380
|
+
rescue JSON::ParserError, SystemCallError
|
|
381
|
+
nil
|
|
382
|
+
end
|
|
383
|
+
|
|
384
|
+
def normalize_transfer_changelog_lag(lag)
|
|
385
|
+
return nil unless lag.is_a?(Hash)
|
|
386
|
+
|
|
387
|
+
lag.each_with_object({}) { |(key, value), memo| memo[key.to_s] = value }
|
|
388
|
+
end
|
|
389
|
+
|
|
315
390
|
def github_latest_release(root)
|
|
316
391
|
repo = github_repo_slug(root)
|
|
317
392
|
return nil unless repo
|
data/lib/kettle/family/report.rb
CHANGED
|
@@ -421,6 +421,7 @@ module Kettle
|
|
|
421
421
|
lines << " prep: V.ch.md matches V.rb and is ready to publish"
|
|
422
422
|
lines << " pend: unrel or prep"
|
|
423
423
|
lines << " bump: unrel is yes and V.rb matches V.rel"
|
|
424
|
+
lines << " T📰: kettle-jem transfer changelog entries not yet replayed"
|
|
424
425
|
rows = release_state_header
|
|
425
426
|
results.each do |result|
|
|
426
427
|
rows << release_state_row(result)
|
|
@@ -444,7 +445,8 @@ module Kettle
|
|
|
444
445
|
state.fetch("version", "unknown").to_s,
|
|
445
446
|
state.fetch("latest_changelog_version", nil).to_s.empty? ? "none" : state.fetch("latest_changelog_version").to_s,
|
|
446
447
|
state.fetch("latest_released", nil).to_s.empty? ? "unknown" : state.fetch("latest_released").to_s,
|
|
447
|
-
|
|
448
|
+
release_state_github_release(state),
|
|
449
|
+
state.fetch("transfer_changelog_lag", 0).to_i.to_s,
|
|
448
450
|
release_state_ahead_behind(state),
|
|
449
451
|
yes_no(state.fetch("unreleased_entries", nil)),
|
|
450
452
|
yes_no(state.fetch("prepared_release_pending", nil)),
|
|
@@ -457,12 +459,26 @@ module Kettle
|
|
|
457
459
|
end
|
|
458
460
|
|
|
459
461
|
def release_state_header
|
|
460
|
-
header = [["gem", "checkout", "V.rb", "V.ch.md", "V.rel", "GH.rel", "🔼 / 🔽", "unrel", "prep", "pend", "bump"]]
|
|
462
|
+
header = [["gem", "checkout", "V.rb", "V.ch.md", "V.rel", "GH.rel", "T📰", "🔼 / 🔽", "unrel", "prep", "pend", "bump"]]
|
|
461
463
|
return header unless release_state_has_branches?
|
|
462
464
|
|
|
463
465
|
[["branch", *header.first]]
|
|
464
466
|
end
|
|
465
467
|
|
|
468
|
+
def release_state_github_release(state)
|
|
469
|
+
github_release = state.fetch("github_latest_release", nil).to_s
|
|
470
|
+
return "unknown" if github_release.empty?
|
|
471
|
+
|
|
472
|
+
latest_released = state.fetch("latest_released", nil).to_s
|
|
473
|
+
return github_release if latest_released.empty? || latest_released == "unknown"
|
|
474
|
+
|
|
475
|
+
release_state_release_versions_match?(latest_released, github_release) ? github_release : "🔴 #{github_release}"
|
|
476
|
+
end
|
|
477
|
+
|
|
478
|
+
def release_state_release_versions_match?(latest_released, github_release)
|
|
479
|
+
latest_released.to_s.delete_prefix("v") == github_release.to_s.delete_prefix("v")
|
|
480
|
+
end
|
|
481
|
+
|
|
466
482
|
def release_state_checkout(state)
|
|
467
483
|
branch = state.fetch("current_branch", nil).to_s
|
|
468
484
|
branch.empty? ? "unknown" : branch[0, 10]
|
|
@@ -1059,7 +1059,11 @@ module Kettle
|
|
|
1059
1059
|
if command == "template"
|
|
1060
1060
|
env["KETTLE_JEM_TEMPLATE_PROFILE"] = config.template_profile if config.template_profile
|
|
1061
1061
|
env["KJ_REPOSITORY_TOPOLOGY"] = config.template_repository_topology if config.template_repository_topology
|
|
1062
|
-
|
|
1062
|
+
if monorepo_template?
|
|
1063
|
+
template_git_lock_path = template_git_commit_lock_path
|
|
1064
|
+
env["KETTLE_JEM_GIT_LOCK"] = template_git_lock_path
|
|
1065
|
+
env["KETTLE_JEM_GIT_COMMIT_LOCK"] = template_git_lock_path
|
|
1066
|
+
end
|
|
1063
1067
|
corporate_sponsors = config.readme_corporate_sponsors
|
|
1064
1068
|
unless corporate_sponsors.empty?
|
|
1065
1069
|
env["KETTLE_JEM_CORPORATE_SPONSORS_JSON"] = JSON.generate(corporate_sponsors)
|
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.1.
|
|
4
|
+
version: 1.1.9
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -181,6 +181,26 @@ dependencies:
|
|
|
181
181
|
- - ">="
|
|
182
182
|
- !ruby/object:Gem::Version
|
|
183
183
|
version: 1.0.4
|
|
184
|
+
- !ruby/object:Gem::Dependency
|
|
185
|
+
name: anonymous_loader
|
|
186
|
+
requirement: !ruby/object:Gem::Requirement
|
|
187
|
+
requirements:
|
|
188
|
+
- - "~>"
|
|
189
|
+
- !ruby/object:Gem::Version
|
|
190
|
+
version: '0.1'
|
|
191
|
+
- - ">="
|
|
192
|
+
- !ruby/object:Gem::Version
|
|
193
|
+
version: 0.1.3
|
|
194
|
+
type: :development
|
|
195
|
+
prerelease: false
|
|
196
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
197
|
+
requirements:
|
|
198
|
+
- - "~>"
|
|
199
|
+
- !ruby/object:Gem::Version
|
|
200
|
+
version: '0.1'
|
|
201
|
+
- - ">="
|
|
202
|
+
- !ruby/object:Gem::Version
|
|
203
|
+
version: 0.1.3
|
|
184
204
|
- !ruby/object:Gem::Dependency
|
|
185
205
|
name: appraisal2
|
|
186
206
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -319,10 +339,10 @@ licenses:
|
|
|
319
339
|
- AGPL-3.0-only
|
|
320
340
|
metadata:
|
|
321
341
|
homepage_uri: https://kettle-family.galtzo.com
|
|
322
|
-
source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.1.
|
|
323
|
-
changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.1.
|
|
342
|
+
source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.1.9
|
|
343
|
+
changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.1.9/CHANGELOG.md
|
|
324
344
|
bug_tracker_uri: https://github.com/kettle-dev/kettle-family/issues
|
|
325
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.1.
|
|
345
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.1.9
|
|
326
346
|
funding_uri: https://github.com/sponsors/pboling
|
|
327
347
|
wiki_uri: https://github.com/kettle-dev/kettle-family/wiki
|
|
328
348
|
news_uri: https://www.railsbling.com/tags/kettle-family
|
metadata.gz.sig
CHANGED
|
Binary file
|