kettle-family 0.1.26 → 0.1.27

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: 19ca7e62279303fb49a70e0f20282369460c9f57209de5a3d76ffe40f06c91d9
4
- data.tar.gz: c9c0a6f497f51997c83fcf02a83c7878ccf9a0dee5cfd821cf6068f3fddc35c5
3
+ metadata.gz: e9e37861434b48448ce84ade0fe78e8f58f774ef8bf69c3b58cd15db95b7fec7
4
+ data.tar.gz: 30c6f85a22d4af9d7590e703f74d22d021582cbe55425b8f576397f6e19cd27a
5
5
  SHA512:
6
- metadata.gz: ece5ecc423f749383cd783683a36f5a04d5c4695a7dbd5e21a448b23f36362100be375e533b25fb063fe0fad217015f64e377f9bccb2a64c6318e9b1b8b34cc1
7
- data.tar.gz: 4a6c0aa7cdf54f3e8ee36819632cb95e3f59b57ab8e1f82b216bab60a4f1dba78d0b6ba4f602940631b8dab008075ab2f5611c70dc21e435b7fa35e4ec49650d
6
+ metadata.gz: 1493009541e59ff4b55d746edff3f44fb9a063eb1feb3e2f6a3d71a271c70ca91210be347141074fcae29b0d42cd357a6ce66bcf7a55b34bd35cf996309e2bff
7
+ data.tar.gz: 0bac251bdbe718310a6a0b1026e04c40d1922df2489e0626270af541c83612e00745f67c56c38ee0d851f9eaa6eb3b380636c25389e6e6d6fea1291b63d59aa7
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,24 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [0.1.27] - 2026-06-28
34
+
35
+ - TAG: [v0.1.27][0.1.27t]
36
+ - COVERAGE: 95.13% -- 1854/1949 lines in 21 files
37
+ - BRANCH COVERAGE: 74.79% -- 638/853 branches in 21 files
38
+ - 38.60% documented
39
+
40
+ ### Added
41
+
42
+ - Added `kettle-family bup [GEM]` for family-wide `bundle update --all` or
43
+ targeted `bundle update GEM`, and `kettle-family bupb` for family-wide
44
+ `bundle update --bundler`.
45
+
46
+ ### Fixed
47
+
48
+ - `kettle-family bup` and `bupb` now commit bundle lockfile changes after a
49
+ successful member update so branch-stack runs can continue to the next branch.
50
+
33
51
  ## [0.1.26] - 2026-06-27
34
52
 
35
53
  - TAG: [v0.1.26][0.1.26t]
@@ -465,7 +483,9 @@ Please file a bug if you notice a violation of semantic versioning.
465
483
  - Fixed CI load failures on engines without compatible `pty` support by falling back to Open3 for interactive release commands.
466
484
  - Fixed Ruby 3.2 version-bump support by loading Prism lazily and wiring the Prism gem only for MRI versions that need it.
467
485
 
468
- [Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v0.1.26...HEAD
486
+ [Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v0.1.27...HEAD
487
+ [0.1.27]: https://github.com/kettle-dev/kettle-family/compare/v0.1.26...v0.1.27
488
+ [0.1.27t]: https://github.com/kettle-dev/kettle-family/releases/tag/v0.1.27
469
489
  [0.1.26]: https://github.com/kettle-dev/kettle-family/compare/v0.1.25...v0.1.26
470
490
  [0.1.26t]: https://github.com/kettle-dev/kettle-family/releases/tag/v0.1.26
471
491
  [0.1.25]: https://github.com/kettle-dev/kettle-family/compare/v0.1.24...v0.1.25
data/README.md CHANGED
@@ -571,7 +571,7 @@ Thanks for RTFM. ☺️
571
571
  [📌gitmoji]: https://gitmoji.dev
572
572
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
573
573
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
574
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-1.931-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
574
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-1.949-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
575
575
  [🔐security]: https://github.com/kettle-dev/kettle-family/blob/main/SECURITY.md
576
576
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
577
577
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -6,8 +6,8 @@ require "optparse"
6
6
  module Kettle
7
7
  module Family
8
8
  class CLI
9
- COMMANDS = %w[discover plan report metadata check test lint docs template gha-sha-pins install bump-version add-changelog release push pull up branch-lanes release-state].freeze
10
- WORKFLOW_COMMANDS = %w[check test lint docs template gha-sha-pins release push pull up].freeze
9
+ COMMANDS = %w[discover plan report metadata check test lint docs template gha-sha-pins bup bupb install bump-version add-changelog release push pull up branch-lanes release-state].freeze
10
+ WORKFLOW_COMMANDS = %w[check test lint docs template gha-sha-pins bup bupb release push pull up].freeze
11
11
 
12
12
  def self.call(argv, out: $stdout, err: $stderr)
13
13
  new(argv, out: out, err: err).call
@@ -27,9 +27,11 @@ module Kettle
27
27
 
28
28
  target_version = argv.shift if command == "bump-version"
29
29
  raise Error, "bump-version requires VERSION, major, minor, patch, or pre" if command == "bump-version" && !target_version
30
+ bup_args = parse_bup_args(command)
30
31
 
31
32
  options = parse_options
32
33
  options[:target_version] = target_version
34
+ options[:bup_args] = bup_args
33
35
  return help if options.delete(:help)
34
36
 
35
37
  report = build_report(command, options)
@@ -51,6 +53,7 @@ module Kettle
51
53
 
52
54
  Usage: kettle-family COMMAND [options]
53
55
  kettle-family bump-version VERSION|major|minor|patch|pre [options]
56
+ kettle-family bup [GEM] [options]
54
57
 
55
58
  Commands:
56
59
  discover Discover family members and print selected order
@@ -63,6 +66,8 @@ module Kettle
63
66
  docs Plan or execute configured docs command per member
64
67
  template Plan or execute kettle-jem templating per member
65
68
  gha-sha-pins Plan or execute kettle-gha-sha-pins per member
69
+ bup Plan or execute bundle update --all, or bundle update GEM
70
+ bupb Plan or execute bundle update --bundler
66
71
  install Build and install selected local family gems
67
72
  bump-version Check, plan, or execute family version alignment
68
73
  add-changelog Add an entry to an existing Unreleased changelog section
@@ -241,10 +246,19 @@ module Kettle
241
246
  env_overrides: options[:workflow_env],
242
247
  debug: options[:debug],
243
248
  jobs: options[:jobs],
244
- progress_io: progress_io(command, options)
249
+ progress_io: progress_io(command, options),
250
+ bup_args: options[:bup_args]
245
251
  ).results
246
252
  end
247
253
 
254
+ def parse_bup_args(command)
255
+ return [] unless command == "bup"
256
+
257
+ args = []
258
+ args << argv.shift while argv.first && !argv.first.start_with?("-")
259
+ args
260
+ end
261
+
248
262
  def progress_io(command, options)
249
263
  return nil unless command == "template"
250
264
  return nil unless options[:execute]
@@ -78,7 +78,7 @@ module Kettle
78
78
  wave.each_with_index { |member, index| queue << [index, member] }
79
79
  ordered_results = Array.new(wave.length)
80
80
  Array.new(install_jobs(wave)) do
81
- Thread.new do
81
+ Thread.new do # rubocop:disable ThreadSafety/NewThread -- family install intentionally runs independent members concurrently.
82
82
  loop do
83
83
  index, member = queue.pop(true)
84
84
  ordered_results[index] = install_member(member)
@@ -114,7 +114,7 @@ module Kettle
114
114
 
115
115
  def install_jobs(candidate_members)
116
116
  count = jobs ? jobs.to_i : [Etc.nprocessors, 4].min
117
- [[count, 1].max, candidate_members.length].min
117
+ count.clamp(1, candidate_members.length)
118
118
  end
119
119
 
120
120
  def member_from_path(path)
@@ -142,13 +142,15 @@ module Kettle
142
142
  stdout, stderr, status = Open3.capture3("git", "tag", "--list", "v*", chdir: root)
143
143
  raise Error, "could not list release tags for #{root}: #{stderr}" unless status.success?
144
144
 
145
- stdout.lines.filter_map do |line|
145
+ stdout.lines.each_with_object([]) do |line, memo|
146
146
  tag = line.strip
147
147
  next unless tag.start_with?("v")
148
148
 
149
- gem_version(tag.delete_prefix("v"))
150
- rescue ArgumentError
151
- nil
149
+ begin
150
+ memo << gem_version(tag.delete_prefix("v"))
151
+ rescue ArgumentError
152
+ nil
153
+ end
152
154
  end
153
155
  end
154
156
 
@@ -218,7 +220,7 @@ module Kettle
218
220
  start = lines.index { |line| line.start_with?("## [Unreleased]") }
219
221
  return false unless start
220
222
 
221
- following = lines[(start + 1)..] || []
223
+ following = lines.drop(start + 1)
222
224
  block = following.take_while { |line| !line.start_with?("## [") }
223
225
  block.any? { |line| line.match?(/\S/) && !line.match?(/\A###? /) }
224
226
  end
@@ -31,7 +31,7 @@ module Kettle
31
31
  index = selected.index { |candidate| candidate.name == start_at }
32
32
  raise Error, "unknown member #{start_at.inspect}" unless index
33
33
 
34
- selected[index..]
34
+ selected.drop(index)
35
35
  end
36
36
  end
37
37
  end
@@ -3,7 +3,7 @@
3
3
  module Kettle
4
4
  module Family
5
5
  module Version
6
- VERSION = "0.1.26"
6
+ VERSION = "0.1.27"
7
7
  end
8
8
  VERSION = Version::VERSION # Traditional Constant Location
9
9
  end
@@ -15,7 +15,8 @@ module Kettle
15
15
  "test" => "bundle exec kettle-test",
16
16
  "lint" => "bundle exec rake rubocop_gradual",
17
17
  "docs" => "bundle exec rake yard",
18
- "gha-sha-pins" => "bundle exec kettle-gha-sha-pins"
18
+ "gha-sha-pins" => "bundle exec kettle-gha-sha-pins",
19
+ "bupb" => %w[bundle update --bundler]
19
20
  }.freeze
20
21
  GIT_SYNC_COMMANDS = {
21
22
  "push" => [["push", %w[git push]]],
@@ -43,7 +44,7 @@ module Kettle
43
44
  "BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES" => "true"
44
45
  }.freeze
45
46
 
46
- def initialize(command:, config:, members:, execute: false, accept: true, commit: true, allow_dirty: false, publish: false, push: false, tag: false, start_step: nil, skip_steps: nil, local_ci: false, continue_ci_failures: false, gha_sha_pins_upgrade: "patch", gha_sha_pins_check: false, env_overrides: {}, debug: false, gem_signing_password: nil, jobs: nil, progress_io: nil)
47
+ def initialize(command:, config:, members:, execute: false, accept: true, commit: true, allow_dirty: false, publish: false, push: false, tag: false, start_step: nil, skip_steps: nil, local_ci: false, continue_ci_failures: false, gha_sha_pins_upgrade: "patch", gha_sha_pins_check: false, env_overrides: {}, debug: false, gem_signing_password: nil, jobs: nil, progress_io: nil, bup_args: [])
47
48
  @command = command
48
49
  @config = config
49
50
  @members = members
@@ -65,6 +66,7 @@ module Kettle
65
66
  @gem_signing_password = gem_signing_password
66
67
  @jobs = jobs
67
68
  @progress_io = progress_io
69
+ @bup_args = bup_args
68
70
  end
69
71
 
70
72
  def results
@@ -77,7 +79,7 @@ module Kettle
77
79
 
78
80
  private
79
81
 
80
- attr_reader :command, :config, :members, :execute, :accept, :commit, :allow_dirty, :publish, :push, :tag, :start_step, :skip_steps, :local_ci, :continue_ci_failures, :gha_sha_pins_upgrade, :gha_sha_pins_check, :env_overrides, :debug, :jobs, :progress_io
82
+ attr_reader :command, :config, :members, :execute, :accept, :commit, :allow_dirty, :publish, :push, :tag, :start_step, :skip_steps, :local_ci, :continue_ci_failures, :gha_sha_pins_upgrade, :gha_sha_pins_check, :env_overrides, :debug, :jobs, :progress_io, :bup_args
81
83
 
82
84
  def current_branch_results(workflow_members)
83
85
  return check_results(workflow_members) if command == "check"
@@ -104,6 +106,7 @@ module Kettle
104
106
 
105
107
  normalize_lockfiles(member: member, runner: runner, memo: memo, phase: "normalize_lockfiles") if command == "template"
106
108
  commit_gha_sha_pins(member: member, runner: runner, memo: memo) if command == "gha-sha-pins"
109
+ commit_bundle_update(member: member, runner: runner, memo: memo) if %w[bup bupb].include?(command)
107
110
  end
108
111
  end
109
112
 
@@ -115,7 +118,7 @@ module Kettle
115
118
  stop = false
116
119
  emit_template_progress_start(workflow_members)
117
120
  Array.new(template_jobs(workflow_members)) do
118
- Thread.new do
121
+ Thread.new do # rubocop:disable ThreadSafety/NewThread -- family templating intentionally runs independent members concurrently.
119
122
  loop do
120
123
  break if mutex.synchronize { stop }
121
124
  index, member = queue.pop(true)
@@ -153,7 +156,7 @@ module Kettle
153
156
  def template_jobs(workflow_members)
154
157
  requested = jobs || config.template_jobs
155
158
  count = requested ? requested.to_i : [Etc.nprocessors, 4].min
156
- [[count, 1].max, workflow_members.length].min
159
+ count.clamp(1, workflow_members.length)
157
160
  end
158
161
 
159
162
  def check_results(workflow_members)
@@ -232,7 +235,8 @@ module Kettle
232
235
  env_overrides: env_overrides,
233
236
  gem_signing_password: @gem_signing_password,
234
237
  jobs: jobs,
235
- progress_io: progress_io
238
+ progress_io: progress_io,
239
+ bup_args: bup_args
236
240
  )
237
241
  end
238
242
 
@@ -266,7 +270,7 @@ module Kettle
266
270
  wave_jobs = release_jobs(wave)
267
271
  release_otp_coordinator&.queue_total = wave_jobs
268
272
  Array.new(wave_jobs) do
269
- Thread.new do
273
+ Thread.new do # rubocop:disable ThreadSafety/NewThread -- family release intentionally runs independent members concurrently.
270
274
  runner = release_command_runner
271
275
  loop do
272
276
  index, member = queue.pop(true)
@@ -350,7 +354,7 @@ module Kettle
350
354
  def release_jobs(release_members)
351
355
  requested = jobs || config.release_jobs
352
356
  count = requested ? requested.to_i : [Etc.nprocessors, 4].min
353
- [[count, 1].max, release_members.length].min
357
+ count.clamp(1, release_members.length)
354
358
  end
355
359
 
356
360
  def release_waves(release_members)
@@ -545,10 +549,18 @@ module Kettle
545
549
  def workflow_command(member = nil)
546
550
  return template_command(member) if command == "template"
547
551
  return gha_sha_pins_command if command == "gha-sha-pins"
552
+ return bup_command if command == "bup"
548
553
 
549
554
  command_for(command)
550
555
  end
551
556
 
557
+ def bup_command
558
+ args = Array(bup_args).map(&:to_s).reject(&:empty?)
559
+ return ["bundle", "update", "--all"] if args.empty?
560
+
561
+ ["bundle", "update", *args]
562
+ end
563
+
552
564
  def gha_sha_pins_command
553
565
  command_text = command_for(command)
554
566
  args = []
@@ -742,6 +754,22 @@ module Kettle
742
754
  memo << result
743
755
  end
744
756
 
757
+ def commit_bundle_update(member:, runner:, memo:)
758
+ return unless commit
759
+
760
+ result = runner.call(
761
+ member: member,
762
+ phase: "commit_bundle_update",
763
+ command: [
764
+ "sh",
765
+ "-lc",
766
+ "files=$(git ls-files --modified --others --exclude-standard -- Gemfile.lock '*.lock' '**/*.lock'); " \
767
+ "if [ -n \"$files\" ]; then printf '%s\\n' \"$files\" | xargs git add -- && git commit -m '🔒 Update bundle'; fi"
768
+ ]
769
+ )
770
+ memo << result
771
+ end
772
+
745
773
  def family_member
746
774
  Member.new(
747
775
  name: config.family_name,
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: 0.1.26
4
+ version: 0.1.27
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -310,10 +310,10 @@ licenses:
310
310
  - AGPL-3.0-only
311
311
  metadata:
312
312
  homepage_uri: https://kettle-family.galtzo.com
313
- source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v0.1.26
314
- changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v0.1.26/CHANGELOG.md
313
+ source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v0.1.27
314
+ changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v0.1.27/CHANGELOG.md
315
315
  bug_tracker_uri: https://github.com/kettle-dev/kettle-family/issues
316
- documentation_uri: https://www.rubydoc.info/gems/kettle-family/0.1.26
316
+ documentation_uri: https://www.rubydoc.info/gems/kettle-family/0.1.27
317
317
  funding_uri: https://github.com/sponsors/pboling
318
318
  wiki_uri: https://github.com/kettle-dev/kettle-family/wiki
319
319
  news_uri: https://www.railsbling.com/tags/kettle-family
metadata.gz.sig CHANGED
Binary file