kettle-family 1.0.0 → 1.0.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5bca5a6ab33a2d894ba06b7b75827b8849476922494bbf02df50efb0d9a0edac
4
- data.tar.gz: 9dc491d15e3f89e737961bf87f103a982bddafc6183dc26f8d2287b84dce7d12
3
+ metadata.gz: ddbeefcf7d7d90e52b0fadb3f09358c14baaa3eade9b03685e36868bd608e810
4
+ data.tar.gz: a75ce0508f27ba21ee30cf7a23fb95b97479ce1f6f03242a0fcc3210b2d2092f
5
5
  SHA512:
6
- metadata.gz: 9ebfabcd00bbb7631fe7ef8f3aae71e283b2bfda98a7c60e8b28551e7e3401f219916408c0fafa7321a62dc3ff44fd02a9a44a7461684399a672df9af89d0adf
7
- data.tar.gz: 9d72e678c1f451b101b3dc297da6b320321a2fec0b1c723a6c174a5e2a5f5f1d0175ef120c276ca1f52df115a70f87a8d6f76a4a7e30eba7fb2b137eade11b29
6
+ metadata.gz: '02850c92673ac9c330561be7e9b7cba733683aa952312cdf17bab8a299e4dbcd002ee9f75c5f08cd68c4650dcfea57399e04713523890822a50ce6278bf0536a'
7
+ data.tar.gz: a4b1e30e093fb889d26755250bc035243436a2e272288575991b9fcb83003288b4cb665363633711b20e4c7e1ce13103c7cd038d1b0e721dbd78a805af3ec4c9
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -28,8 +28,58 @@ Please file a bug if you notice a violation of semantic versioning.
28
28
 
29
29
  ### Fixed
30
30
 
31
+ - Generated HEAD and runtime dependency HEAD CI workflows no longer include
32
+ JRuby or TruffleRuby jobs for this MRI-only gem.
33
+
31
34
  ### Security
32
35
 
36
+ ## [1.0.1] - 2026-07-20
37
+
38
+ - TAG: [v1.0.1][1.0.1t]
39
+ - COVERAGE: 95.44% -- 2534/2655 lines in 23 files
40
+ - BRANCH COVERAGE: 77.89% -- 877/1126 branches in 23 files
41
+ - 29.10% documented
42
+
43
+ ### Added
44
+
45
+ - `kettle-family release-state` now includes an `ahead` column counting commits
46
+ from the latest release tag to the local default branch when available.
47
+ - `kettle-family release` now accepts `--skip-remotes` and forwards the
48
+ comma-separated remote skip list to member `kettle-release` runs.
49
+ - `kettle-family --only` now accepts release-state tokens `unreleased`,
50
+ `prepared`, and `pending`; multiple tokens are combined with logical AND.
51
+ - `kettle-family template` now accepts `--verbose` and forwards verbose mode to
52
+ member `kettle-jem` runs instead of forcing quiet JSON output.
53
+
54
+ - `kettle-family template` now runs `kettle-jem prepare` before full templating
55
+ for Kettle Jem-powered members so templating-only dependency bootstraps, such
56
+ as parser packages, are available before the full template command loads.
57
+
58
+ - `kettle-family template` now uses `kettle-jem --events` as its default
59
+ templating interface, including verbose and single-job runs, and streams
60
+ newline-delimited JSON template phase, recipe, post-apply, command-step,
61
+ diagnostic, and summary events as member-prefixed progress lines.
62
+
63
+ ### Deprecated
64
+
65
+ - `kettle-family bump-version` is now deprecated in favor of `kettle-family bump`.
66
+
67
+ ### Fixed
68
+
69
+ - The templating prepare phase now disables only the implicit family local path
70
+ environment variable unless it was explicitly provided, avoiding stale local
71
+ Gemfile activation failures before the prepare payload can refresh generated
72
+ modular Gemfiles.
73
+ - The templating prepare phase now runs outside each member's Bundler context so
74
+ it can repair stale generated Gemfiles before Bundler evaluates them.
75
+
76
+ - `kettle-family` template preparation now handles custom non-`kettle-jem`
77
+ template commands without treating no-op dependency preparation as failure.
78
+ - `kettle-family release-state` now counts `ahead` from the release tag to the
79
+ checked-out member `HEAD`.
80
+ - Generated docs now retain the YARD `_index.html` content wrapper after
81
+ regeneration with the shared YARD postprocessing stack.
82
+
33
83
  ## [1.0.0] - 2026-07-17
34
84
 
35
85
  - TAG: [v1.0.0][1.0.0t]
@@ -736,7 +786,9 @@ Please file a bug if you notice a violation of semantic versioning.
736
786
  - Fixed CI load failures on engines without compatible `pty` support by falling back to Open3 for interactive release commands.
737
787
  - Fixed Ruby 3.2 version-bump support by loading Prism lazily and wiring the Prism gem only for MRI versions that need it.
738
788
 
739
- [Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.0.0...HEAD
789
+ [Unreleased]: https://github.com/kettle-dev/kettle-family/compare/v1.0.1...HEAD
790
+ [1.0.1]: https://github.com/kettle-dev/kettle-family/compare/v1.0.0...v1.0.1
791
+ [1.0.1t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.0.1
740
792
  [1.0.0]: https://github.com/kettle-dev/kettle-family/compare/v0.2.7...v1.0.0
741
793
  [1.0.0t]: https://github.com/kettle-dev/kettle-family/releases/tag/v1.0.0
742
794
  [0.2.7]: https://github.com/kettle-dev/kettle-family/compare/v0.2.6...v0.2.7
data/README.md CHANGED
@@ -211,7 +211,7 @@ changelog:
211
211
 
212
212
  release:
213
213
  env:
214
- KETTLE_RB_DEV: false
214
+ KETTLE_DEV_DEV: false
215
215
  family_changelog:
216
216
  enabled: true
217
217
  command: bundle exec kettle-changelog
@@ -273,8 +273,28 @@ kettle-family release-state
273
273
  ```
274
274
 
275
275
  The release-state report lists each gem's current `version.rb`, latest published
276
- release, latest versioned `CHANGELOG.md` section, and whether pending changelog
277
- work exists in either `Unreleased` or an unpublished prepared release section.
276
+ release, latest versioned `CHANGELOG.md` section, whether pending changelog work
277
+ exists in either `Unreleased` or an unpublished prepared release section, and
278
+ how many commits the current branch is ahead of the latest release tag.
279
+
280
+ Use release-state tokens with `--only` to select gems by state instead of by
281
+ name. Multiple tokens are combined with logical AND, so this selects only gems
282
+ that are both unreleased and pending. Status tokens cannot be mixed with member
283
+ names in the same `--only` value.
284
+
285
+ ```console
286
+ kettle-family release-state --only pending
287
+ kettle-family release-state --only unreleased,prepared
288
+ kettle-family release --execute --only unreleased,pending
289
+ ```
290
+
291
+ The supported release-state tokens are:
292
+
293
+ | Token | Meaning |
294
+ |-------|---------|
295
+ | `unreleased` | The current `version.rb` is not the latest published gem version. |
296
+ | `prepared` | The changelog already has a versioned section for the current `version.rb`. |
297
+ | `pending` | The member has unreleased changelog work or an unpublished prepared release. |
278
298
 
279
299
  Plan or update GitHub Actions workflow SHA pins across the selected family
280
300
  members:
@@ -291,6 +311,15 @@ Run release prep/build phases without publishing:
291
311
  kettle-family release --execute
292
312
  ```
293
313
 
314
+ When a remote mirror is temporarily unavailable, skip it for the underlying
315
+ `kettle-release` fetch/parity gate instead of removing the remote from each
316
+ member repository:
317
+
318
+ ```console
319
+ kettle-family release --execute --publish --skip-remotes cb
320
+ kettle-family release --execute --publish --skip-remotes cb,mirror2
321
+ ```
322
+
294
323
  Publish through `kettle-release`. A full publish first runs the
295
324
  `kettle-pre-release` gate, then prompts once for the gem signing key password
296
325
  and leaves RubyGems MFA prompts interactive:
@@ -321,6 +350,61 @@ If you intentionally need to continue after CI failures, opt in explicitly:
321
350
  kettle-family release --publish --execute --continue-ci-failures
322
351
  ```
323
352
 
353
+ Bump aligned member versions with `bump`. The older `bump-version` command still
354
+ works as a deprecated alias.
355
+
356
+ ```console
357
+ kettle-family bump --execute --only pending patch
358
+ kettle-family bump --execute --only unreleased minor
359
+ ```
360
+
361
+ Run `kettle-jem` templating across the selected family members. Planning shows
362
+ the commands that would run; `--execute` runs them. Executed templating defaults
363
+ to a parallel job count based on CPU cores, capped for readability, and can be
364
+ overridden with `--jobs`.
365
+
366
+ ```console
367
+ kettle-family template
368
+ kettle-family template --execute --jobs 4
369
+ kettle-family template --execute --only kettle-family
370
+ ```
371
+
372
+ Templating uses `kettle-jem --events` as the default child interface, so
373
+ executed runs stream member-prefixed progress while still keeping the final
374
+ family report. Progress marks include:
375
+
376
+ | Mark | Meaning |
377
+ |------|---------|
378
+ | `>` | A phase or command step started. |
379
+ | `.` | A phase, recipe, or step completed without changing files. |
380
+ | `*` | A recipe or step changed files. |
381
+ | `!` | A diagnostic was emitted. |
382
+ | `F` | A phase or step failed. |
383
+ | `done` | The member summary was emitted. |
384
+
385
+ Example progress:
386
+
387
+ ```text
388
+ templating 1 member with 1 job:
389
+ [kettle-family] > recipes
390
+ [kettle-family] * Gemfile
391
+ [kettle-family] * post_apply:git_hooks_executable
392
+ [kettle-family] done 2 files changed
393
+ .
394
+ template summary: 1/1 members ok, 2 files changed
395
+ ```
396
+
397
+ Use `--verbose` when you need `kettle-jem` verbose diagnostics layered on top of
398
+ the event stream. Environment overrides pass through to every member workflow
399
+ command, which is useful when templating against local unreleased dependencies.
400
+
401
+ ```console
402
+ kettle-family template --execute --verbose --jobs 1
403
+ kettle-family template --execute \
404
+ --env K_JEM_TEMPLATING=true \
405
+ --env STRUCTUREDMERGE_DEV=/home/me/src/structuredmerge/ruby/gems
406
+ ```
407
+
324
408
  ## 🔐 Security
325
409
 
326
410
  See [SECURITY.md][🔐security].
@@ -386,7 +470,7 @@ For most applications, prefer the [Pessimistic Version Constraint][📌pvc] with
386
470
  For example:
387
471
 
388
472
  ```ruby
389
- spec.add_dependency("kettle-family", "~> 0.0")
473
+ spec.add_dependency("kettle-family", "~> 1.0")
390
474
  ```
391
475
 
392
476
  <details markdown="1">
@@ -583,7 +667,7 @@ Thanks for RTFM. ☺️
583
667
  [📌gitmoji]: https://gitmoji.dev
584
668
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
585
669
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
586
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.489-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
670
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-2.655-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
587
671
  [🔐security]: https://github.com/kettle-dev/kettle-family/blob/main/SECURITY.md
588
672
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
589
673
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -10,7 +10,7 @@ module Kettle
10
10
  class CLI < CommandKit::Command
11
11
  include CommandKit::Commands
12
12
 
13
- COMMANDS = %w[discover plan report metadata check test lint docs template gha-sha-pins bup bupb bex install bump-version add-changelog release push pull up branch-lanes release-state].freeze
13
+ COMMANDS = %w[discover plan report metadata check test lint docs template gha-sha-pins bup bupb bex install bump bump-version add-changelog release push pull up branch-lanes release-state].freeze
14
14
  WORKFLOW_COMMANDS = %w[check test lint docs template gha-sha-pins bup bupb bex release push pull up].freeze
15
15
 
16
16
  command_name "kettle-family"
@@ -37,7 +37,7 @@ module Kettle
37
37
 
38
38
  module SelectionOptions
39
39
  def self.included(base)
40
- base.option :only, value: {type: String, usage: "MEMBERS"}, desc: "Select comma-separated members"
40
+ base.option :only, value: {type: String, usage: "MEMBERS"}, desc: "Select comma-separated members, or release-state tokens: unreleased, prepared, pending"
41
41
  base.option :exclude, value: {type: String, usage: "MEMBERS"}, desc: "Exclude comma-separated members"
42
42
  base.option :start_at, long: "--start-at", value: {type: String, usage: "MEMBER[@BRANCH]"}, desc: "Select from member through the end of order"
43
43
  end
@@ -65,6 +65,7 @@ module Kettle
65
65
  module WorkflowOptions
66
66
  def self.included(base)
67
67
  base.option :debug, desc: "Preserve debug environment for workflow commands"
68
+ base.option :verbose, desc: "Pass verbose mode through to supported workflow commands"
68
69
  base.option :jobs, value: {type: Integer, usage: "N"}, desc: "Parallel jobs for supported executed workflows"
69
70
  base.option :env, value: {type: String, usage: "KEY=VALUE"}, desc: "Override an environment variable for each member workflow command" do |value|
70
71
  parse_env_override(value, workflow_env)
@@ -134,6 +135,7 @@ module Kettle
134
135
  report: options[:report],
135
136
  execute: truthy_option?(:execute),
136
137
  debug: truthy_option?(:debug),
138
+ verbose: truthy_option?(:verbose),
137
139
  jobs: options[:jobs],
138
140
  workflow_env: workflow_env,
139
141
  changelog_section: nil,
@@ -148,6 +150,7 @@ module Kettle
148
150
  release_continue_ci_failures: false,
149
151
  release_ci_workflows: nil,
150
152
  release_skip_bundle_audit: false,
153
+ release_skip_remotes: nil,
151
154
  accept: true,
152
155
  tag: false,
153
156
  push: false,
@@ -353,11 +356,11 @@ module Kettle
353
356
  end
354
357
  end
355
358
 
356
- class BumpVersion < BaseCommand
359
+ class Bump < BaseCommand
357
360
  include ExecutionOptions
358
361
  include CommitOptions
359
362
 
360
- command_name "bump-version"
363
+ command_name "bump"
361
364
  usage "[options] VERSION|major|minor|patch|pre"
362
365
  description "Check, plan, or execute family version alignment."
363
366
  argument :target_version, required: false, usage: "VERSION|major|minor|patch|pre", desc: "Version or bump target"
@@ -366,9 +369,31 @@ module Kettle
366
369
  option :from, value: {type: String, usage: "VERSION"}, desc: "Require selected members to currently match VERSION"
367
370
 
368
371
  def run(target_version = nil)
369
- raise Error, "bump-version requires VERSION, major, minor, patch, or pre" unless target_version
372
+ raise Error, "#{workflow_command_name} requires VERSION, major, minor, patch, or pre" unless target_version
373
+
374
+ run_family(workflow_command_name, target_version: target_version, from_version: options[:from])
375
+ end
376
+
377
+ private
378
+
379
+ def workflow_command_name
380
+ "bump"
381
+ end
382
+ end
383
+
384
+ class BumpVersion < Bump
385
+ command_name "bump-version"
386
+ description "Deprecated alias for bump."
387
+
388
+ def run(target_version = nil)
389
+ stderr.puts("kettle-family: bump-version is deprecated; use bump instead.")
390
+ super
391
+ end
392
+
393
+ private
370
394
 
371
- run_family("bump-version", target_version: target_version, from_version: options[:from])
395
+ def workflow_command_name
396
+ "bump-version"
372
397
  end
373
398
  end
374
399
 
@@ -407,6 +432,7 @@ module Kettle
407
432
  option :continue_ci_failures, long: "--continue-ci-failures", desc: "Set K_RELEASE_CI_CONTINUE=true for release commands"
408
433
  option :ci_workflows, long: "--ci-workflows", value: {type: String, usage: "LIST"}, desc: "Pass a comma-separated CI workflow monitor subset through to kettle-release commands"
409
434
  option :skip_bundle_audit, long: "--skip-bundle-audit", desc: "Skip bundle:audit/update during release rake checks"
435
+ option :skip_remotes, long: "--skip-remotes", value: {type: String, usage: "LIST"}, desc: "Pass a comma-separated git remote skip list through to kettle-release commands"
410
436
  option :no_auto_floors, long: "--no-auto-floors", desc: "Do not raise family dependency floors between member releases" do
411
437
  options[:no_auto_floors] = true
412
438
  end
@@ -428,6 +454,7 @@ module Kettle
428
454
  release_continue_ci_failures: truthy_option?(:continue_ci_failures),
429
455
  release_ci_workflows: options[:ci_workflows],
430
456
  release_skip_bundle_audit: truthy_option?(:skip_bundle_audit),
457
+ release_skip_remotes: options[:skip_remotes],
431
458
  release_auto_dependency_floors: !truthy_option?(:no_auto_floors),
432
459
  accept: !options.key?(:accept) || options[:accept],
433
460
  tag: truthy_option?(:tag),
@@ -468,6 +495,7 @@ module Kettle
468
495
  command Bupb
469
496
  command Bex
470
497
  command Install
498
+ command Bump
471
499
  command BumpVersion
472
500
  command AddChangelog
473
501
  command Release
@@ -514,7 +542,8 @@ module Kettle
514
542
  else
515
543
  Orderer.new(members: members, mode: config.order_mode, hints: config.order_hints).ordered
516
544
  end
517
- selected = Selection.new(members: ordered).apply(only: options[:only], exclude: options[:exclude], start_at: start_at.member)
545
+ release_state_results = release_state_results_for_selection(config: config, members: ordered, only: options[:only])
546
+ selected = Selection.new(members: ordered, release_state_results: release_state_results).apply(only: options[:only], exclude: options[:exclude], start_at: start_at.member)
518
547
  result_members = selected
519
548
  results = command_results(command: command, config: config, members: result_members, options: options, start_at: start_at)
520
549
  Report.new(
@@ -542,8 +571,14 @@ module Kettle
542
571
  command_results_for_current_branch(command: command, config: config, members: members, options: options, start_at: start_at)
543
572
  end
544
573
 
574
+ def release_state_results_for_selection(config:, members:, only:)
575
+ return nil unless only.to_s.split(",").map(&:strip).any? { |token| Selection.status_token?(token) }
576
+
577
+ ReleaseStateCheck.new(config: config, members: members).results
578
+ end
579
+
545
580
  def command_results_for_current_branch(command:, config:, members:, options:, start_at: StartAt.new(nil, nil))
546
- return bump_version_results(members: members, options: options) if command == "bump-version"
581
+ return bump_version_results(members: members, options: options, phase: command) if %w[bump bump-version].include?(command)
547
582
  return add_changelog_results(members: members, options: options) if command == "add-changelog"
548
583
  return branch_lane_results(config: config, members: members) if command == "branch-lanes"
549
584
  return release_state_results(config: config, members: members) if command == "release-state"
@@ -567,11 +602,13 @@ module Kettle
567
602
  continue_ci_failures: options[:release_continue_ci_failures],
568
603
  ci_workflows: options[:release_ci_workflows],
569
604
  skip_bundle_audit: options[:release_skip_bundle_audit],
605
+ skip_remotes: options[:release_skip_remotes],
570
606
  auto_dependency_floors: options[:release_auto_dependency_floors],
571
607
  gha_sha_pins_upgrade: options[:gha_sha_pins_upgrade],
572
608
  gha_sha_pins_check: options[:check],
573
609
  env_overrides: options[:workflow_env],
574
610
  debug: options[:debug],
611
+ verbose: options[:verbose],
575
612
  jobs: options[:jobs],
576
613
  progress_io: progress_io(command, options),
577
614
  bup_args: options[:bup_args],
@@ -593,14 +630,14 @@ module Kettle
593
630
  return false if config.release_target_branches.empty?
594
631
  return false if command == "release-state"
595
632
  return false if command == "branch-lanes"
596
- return false unless WORKFLOW_COMMANDS.include?(command) || %w[bump-version install add-changelog].include?(command)
633
+ return false unless WORKFLOW_COMMANDS.include?(command) || %w[bump bump-version install add-changelog].include?(command)
597
634
 
598
635
  !WORKFLOW_COMMANDS.include?(command)
599
636
  end
600
637
 
601
638
  def member_local_branch_target_command?(command, config, members)
602
639
  return false if !config.release_target_branches.empty?
603
- return false unless %w[bump-version install add-changelog].include?(command)
640
+ return false unless %w[bump bump-version install add-changelog].include?(command)
604
641
 
605
642
  members.any? { |member| member_release_config(member: member, config: config) }
606
643
  end
@@ -686,14 +723,15 @@ module Kettle
686
723
  StartAt.new(member, branch)
687
724
  end
688
725
 
689
- def bump_version_results(members:, options:)
726
+ def bump_version_results(members:, options:, phase:)
690
727
  require_relative "version_bump"
691
728
 
692
729
  results = VersionBump.new(
693
730
  members: members,
694
731
  target_version: options[:target_version],
695
732
  from_version: options[:from_version],
696
- mode: bump_version_mode(options)
733
+ mode: bump_version_mode(options),
734
+ phase: phase
697
735
  ).results
698
736
  return results if options[:check] || !options[:commit]
699
737
  return results unless results.all?(&:ok?)
@@ -111,7 +111,7 @@ module Kettle
111
111
  @otp_coordinator = otp_coordinator
112
112
  end
113
113
 
114
- def call(member:, phase:, command:, env: {}, interactive: false)
114
+ def call(member:, phase:, command:, env: {}, interactive: false, stdout_line_handler: nil)
115
115
  argv = command_argv(member: member, command: command, env: env)
116
116
  process_env = process_env(member: member, env: env)
117
117
  spawn_options = process_options
@@ -120,6 +120,8 @@ module Kettle
120
120
  started = Process.clock_gettime(Process::CLOCK_MONOTONIC)
121
121
  stdout, stderr, status = if interactive
122
122
  run_interactive(env: process_env, argv: argv, chdir: member.root, member_name: member.name, process_options: spawn_options)
123
+ elsif stdout_line_handler
124
+ run_streaming(env: process_env, argv: argv, chdir: member.root, process_options: spawn_options, stdout_line_handler: stdout_line_handler)
123
125
  else
124
126
  Open3.capture3(process_env, *argv, chdir: member.root, **spawn_options)
125
127
  end
@@ -145,6 +147,41 @@ module Kettle
145
147
 
146
148
  attr_reader :execute, :accept, :gem_signing_password, :otp_coordinator
147
149
 
150
+ def run_streaming(env:, argv:, chdir:, process_options:, stdout_line_handler:)
151
+ captured_stdout = +""
152
+ captured_stderr = +""
153
+ stdout_line_buffer = +""
154
+ status = nil
155
+ Open3.popen3(env, *argv, chdir: chdir, **process_options) do |_input, output, error, wait_thread|
156
+ readers = [output, error]
157
+ until readers.empty?
158
+ ready = IO.select(readers)
159
+ ready.first.each do |reader|
160
+ if reader.equal?(output)
161
+ chunk = reader.readpartial(1024)
162
+ captured_stdout << chunk
163
+ stdout_line_buffer = stream_stdout_lines(stdout_line_buffer, chunk, stdout_line_handler)
164
+ else
165
+ captured_stderr << reader.readpartial(1024)
166
+ end
167
+ rescue EOFError
168
+ readers.delete(reader)
169
+ end
170
+ end
171
+ stdout_line_handler.call(stdout_line_buffer) unless stdout_line_buffer.empty?
172
+ status = wait_thread.value
173
+ end
174
+ [captured_stdout, captured_stderr, status]
175
+ end
176
+
177
+ def stream_stdout_lines(buffer, chunk, handler)
178
+ pending = buffer + chunk
179
+ lines = pending.lines
180
+ remainder = pending.end_with?("\n") ? +"" : lines.pop.to_s
181
+ lines.each { |line| handler.call(line.chomp) }
182
+ remainder
183
+ end
184
+
148
185
  def run_interactive(env:, argv:, chdir:, member_name:, process_options:)
149
186
  return run_interactive_pty(env: env, argv: argv, chdir: chdir, member_name: member_name, process_options: process_options) if pty_available?
150
187
 
@@ -278,9 +278,9 @@ module Kettle
278
278
  def default_release_disable_local_path_env
279
279
  local_envs = %w[
280
280
  K_JEM_TEMPLATING
281
- SMORG_RB_DEV
281
+ STRUCTUREDMERGE_DEV
282
282
  TSLP_DEV
283
- KETTLE_RB_DEV
283
+ KETTLE_DEV_DEV
284
284
  RUBOCOP_LTS_DEV
285
285
  PBOLING_DEV
286
286
  GALTZO_FLOSS_DEV
@@ -125,7 +125,10 @@ module Kettle
125
125
  latest_released = branch_latest_released(member, state["latest_changelog_version"])
126
126
  return state unless latest_released
127
127
 
128
- state.merge("latest_released" => latest_released)
128
+ state.merge(
129
+ "latest_released" => latest_released,
130
+ "ahead" => commits_ahead_of_release(member.root, latest_released)
131
+ )
129
132
  rescue ArgumentError
130
133
  state
131
134
  end
@@ -160,6 +163,25 @@ module Kettle
160
163
  Gem::Version.new(value)
161
164
  end
162
165
 
166
+ def commits_ahead_of_release(root, version)
167
+ tag = release_tag_for_version(root, version)
168
+ return nil unless tag && git_ref_exists?(root, "HEAD")
169
+
170
+ stdout, _stderr, status = Open3.capture3("git", "rev-list", "--count", "#{tag}..HEAD", chdir: root)
171
+ status.success? ? stdout.to_i : nil
172
+ end
173
+
174
+ def release_tag_for_version(root, version)
175
+ return nil if version.to_s.empty?
176
+
177
+ ["v#{version}", version.to_s].find { |tag| git_ref_exists?(root, "refs/tags/#{tag}^{commit}") }
178
+ end
179
+
180
+ def git_ref_exists?(root, ref)
181
+ _stdout, _stderr, status = Open3.capture3("git", "rev-parse", "--verify", "--quiet", ref, chdir: root)
182
+ status.success?
183
+ end
184
+
163
185
  def family_changelog_state(root)
164
186
  changelog = File.expand_path(config.changelog_path, root)
165
187
  raise Error, "missing root changelog #{config.changelog_path}" unless File.file?(changelog)
@@ -169,11 +191,13 @@ module Kettle
169
191
  latest_changelog_version = latest_changelog_version(content)
170
192
  unreleased_entries = unreleased_entries?(content)
171
193
  prepared_release_pending = !version.to_s.empty? && latest_changelog_version == version
194
+ ahead = commits_ahead_of_release(root, latest_changelog_version)
172
195
  {
173
196
  "gem_name" => config.family_name,
174
197
  "version" => version,
175
198
  "latest_released" => nil,
176
199
  "latest_changelog_version" => latest_changelog_version,
200
+ "ahead" => ahead,
177
201
  "unreleased_entries" => unreleased_entries,
178
202
  "prepared_release_pending" => prepared_release_pending,
179
203
  "pending_release" => unreleased_entries || prepared_release_pending
@@ -316,6 +316,7 @@ module Kettle
316
316
  state.fetch("version", "unknown").to_s,
317
317
  state.fetch("latest_released", nil).to_s.empty? ? "unknown" : state.fetch("latest_released").to_s,
318
318
  state.fetch("latest_changelog_version", nil).to_s.empty? ? "none" : state.fetch("latest_changelog_version").to_s,
319
+ state.fetch("ahead", nil).nil? ? "unknown" : state.fetch("ahead").to_s,
319
320
  yes_no(state.fetch("unreleased_entries", nil)),
320
321
  yes_no(state.fetch("prepared_release_pending", nil)),
321
322
  yes_no(state.fetch("pending_release", nil))
@@ -326,7 +327,7 @@ module Kettle
326
327
  end
327
328
 
328
329
  def release_state_header
329
- header = [["gem", "version.rb", "latest released", "latest changelog", "unreleased", "prepared", "pending"]]
330
+ header = [["gem", "version.rb", "latest released", "latest changelog", "ahead", "unreleased", "prepared", "pending"]]
330
331
  return header unless release_state_has_branches?
331
332
 
332
333
  [["branch", *header.first]]
@@ -3,8 +3,23 @@
3
3
  module Kettle
4
4
  module Family
5
5
  class Selection
6
- def initialize(members:)
6
+ STATUS_TOKEN_KEYS = {
7
+ "unreleased" => "unreleased_entries",
8
+ "prepared" => "prepared_release_pending",
9
+ "pending" => "pending_release"
10
+ }.freeze
11
+
12
+ def self.status_tokens
13
+ STATUS_TOKEN_KEYS.keys
14
+ end
15
+
16
+ def self.status_token?(value)
17
+ STATUS_TOKEN_KEYS.key?(value.to_s)
18
+ end
19
+
20
+ def initialize(members:, release_state_results: nil)
7
21
  @members = members
22
+ @release_state_results = release_state_results
8
23
  end
9
24
 
10
25
  def apply(only: nil, exclude: nil, start_at: nil)
@@ -19,12 +34,20 @@ module Kettle
19
34
 
20
35
  private
21
36
 
22
- attr_reader :members
37
+ attr_reader :members, :release_state_results
23
38
 
24
39
  def select_only(selected, only)
25
40
  names = only.split(",").map(&:strip).reject(&:empty?)
26
41
  raise Error, "--only requires at least one member" if names.empty?
27
42
 
43
+ status_tokens = names.select { |name| self.class.status_token?(name) }
44
+ unless status_tokens.empty?
45
+ member_names = names - status_tokens
46
+ raise Error, "--only release-state tokens cannot be combined with member names: #{member_names.join(", ")}" unless member_names.empty?
47
+
48
+ return select_release_state_status(selected, status_tokens)
49
+ end
50
+
28
51
  unknown = names - members.map(&:name)
29
52
  raise Error, "unknown member(s): #{unknown.join(", ")}" unless unknown.empty?
30
53
 
@@ -47,6 +70,29 @@ module Kettle
47
70
 
48
71
  selected.drop(index)
49
72
  end
73
+
74
+ def select_release_state_status(selected, status_tokens)
75
+ results_by_member = release_state_results_by_member
76
+ failed = results_by_member.values.select { |result| !result.ok? }
77
+ raise Error, "release-state check failed for: #{failed.map(&:member_name).join(", ")}" unless failed.empty?
78
+
79
+ selected.select do |candidate|
80
+ result = results_by_member[candidate.name]
81
+ result && status_tokens.all? { |token| truthy_state?(result.state[STATUS_TOKEN_KEYS.fetch(token)]) }
82
+ end
83
+ end
84
+
85
+ def release_state_results_by_member
86
+ raise Error, "--only release-state tokens require release-state results" unless release_state_results
87
+
88
+ release_state_results.each_with_object({}) do |result, memo|
89
+ memo[result.member_name] = result
90
+ end
91
+ end
92
+
93
+ def truthy_state?(value)
94
+ value == true
95
+ end
50
96
  end
51
97
  end
52
98
  end
@@ -3,7 +3,7 @@
3
3
  module Kettle
4
4
  module Family
5
5
  module Version
6
- VERSION = "1.0.0"
6
+ VERSION = "1.0.1"
7
7
  end
8
8
  VERSION = Version::VERSION # Traditional Constant Location
9
9
  end
@@ -7,12 +7,13 @@ module Kettle
7
7
  class VersionBump
8
8
  DEPENDENCY_METHODS = %i[add_dependency add_runtime_dependency].freeze
9
9
 
10
- def initialize(members:, target_version:, from_version: nil, mode: :dry_run)
10
+ def initialize(members:, target_version:, from_version: nil, mode: :dry_run, phase: "bump-version")
11
11
  @members = members
12
12
  @target_version = target_version.to_s
13
13
  @explicit_target_version = validate_version(target_version) unless Kettle::Dev::VersionBump::BUMP_TYPES.include?(@target_version)
14
14
  @from_version = validate_version(from_version) if from_version
15
15
  @mode = mode
16
+ @phase = phase
16
17
  @member_names = members.map(&:name)
17
18
  @member_target_versions = members.each_with_object({}) do |member, memo|
18
19
  memo[member.name] = resolve_target_version(member)
@@ -25,7 +26,7 @@ module Kettle
25
26
 
26
27
  private
27
28
 
28
- attr_reader :members, :target_version, :explicit_target_version, :from_version, :mode, :member_names, :member_target_versions
29
+ attr_reader :members, :target_version, :explicit_target_version, :from_version, :mode, :phase, :member_names, :member_target_versions
29
30
 
30
31
  def validate_version(version)
31
32
  with_dev_errors { Kettle::Dev::VersionBump.validate_version(version) }
@@ -39,8 +40,8 @@ module Kettle
39
40
  write_edits(edits) if mode == :execute
40
41
  CommandResult.new(
41
42
  member_name: member.name,
42
- phase: "bump-version",
43
- command: ["internal", "bump-version", member_target_version],
43
+ phase: phase,
44
+ command: ["internal", phase, member_target_version],
44
45
  workdir: member.root,
45
46
  status: check_failed?(edits) ? 1 : 0,
46
47
  success: !check_failed?(edits),
@@ -27,7 +27,7 @@ module Kettle
27
27
  "KETTLE_JEM_QUIET" => "true",
28
28
  "KETTLE_JEM_DEBUG" => "false",
29
29
  "KETTLE_DEV_DEBUG" => "false",
30
- "SMORG_RB_DEBUG" => "false",
30
+ "STRUCTUREDMERGE_DEBUG" => "false",
31
31
  "DEBUG" => nil,
32
32
  "BUNDLE_QUIET" => "true",
33
33
  "BUNDLE_DEBUG" => "false",
@@ -46,7 +46,7 @@ module Kettle
46
46
  REGISTRY_WAIT_ATTEMPTS = 15
47
47
  REGISTRY_WAIT_INTERVAL_SECONDS = 15
48
48
 
49
- 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, ci_workflows: nil, skip_bundle_audit: false, auto_dependency_floors: nil, 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: [], bex_args: [], start_member: nil, start_branch: nil, **options)
49
+ 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, ci_workflows: nil, skip_bundle_audit: false, skip_remotes: nil, auto_dependency_floors: nil, gha_sha_pins_upgrade: "patch", gha_sha_pins_check: false, env_overrides: {}, debug: false, verbose: false, gem_signing_password: nil, jobs: nil, progress_io: nil, bup_args: [], bex_args: [], start_member: nil, start_branch: nil, **options)
50
50
  @command = command
51
51
  @config = config
52
52
  @members = members
@@ -63,11 +63,13 @@ module Kettle
63
63
  @continue_ci_failures = continue_ci_failures
64
64
  @ci_workflows = validate_ci_workflows(ci_workflows)
65
65
  @skip_bundle_audit = skip_bundle_audit
66
+ @skip_remotes = validate_skip_remotes(skip_remotes)
66
67
  @auto_dependency_floors = auto_dependency_floors.nil? ? config.release_auto_dependency_floors? : auto_dependency_floors
67
68
  @gha_sha_pins_upgrade = gha_sha_pins_upgrade
68
69
  @gha_sha_pins_check = gha_sha_pins_check
69
70
  @env_overrides = env_overrides
70
71
  @debug = debug
72
+ @verbose = verbose
71
73
  @gem_signing_password = gem_signing_password
72
74
  @jobs = jobs
73
75
  @progress_io = progress_io
@@ -90,7 +92,7 @@ module Kettle
90
92
 
91
93
  private
92
94
 
93
- attr_reader :command, :config, :members, :execute, :accept, :commit, :allow_dirty, :publish, :push, :tag, :start_step, :skip_steps, :local_ci, :continue_ci_failures, :ci_workflows, :skip_bundle_audit, :auto_dependency_floors, :gha_sha_pins_upgrade, :gha_sha_pins_check, :env_overrides, :debug, :jobs, :progress_io, :bup_args, :bex_args, :start_member, :start_branch
95
+ attr_reader :command, :config, :members, :execute, :accept, :commit, :allow_dirty, :publish, :push, :tag, :start_step, :skip_steps, :local_ci, :continue_ci_failures, :ci_workflows, :skip_bundle_audit, :skip_remotes, :auto_dependency_floors, :gha_sha_pins_upgrade, :gha_sha_pins_check, :env_overrides, :debug, :verbose, :jobs, :progress_io, :bup_args, :bex_args, :start_member, :start_branch
94
96
 
95
97
  def current_branch_results(workflow_members)
96
98
  return check_results(workflow_members) if command == "check"
@@ -101,7 +103,7 @@ module Kettle
101
103
  end
102
104
 
103
105
  def member_workflow_results(workflow_members)
104
- return template_member_workflow_results(workflow_members) if command == "template" && execute && template_jobs(workflow_members) > 1
106
+ return template_member_workflow_results(workflow_members) if command == "template" && execute
105
107
 
106
108
  runner = CommandRunner.new(execute: execute, accept: accept)
107
109
  workflow_members.each_with_object([]) do |member, memo|
@@ -110,6 +112,11 @@ module Kettle
110
112
  break memo unless memo.last.ok?
111
113
  end
112
114
 
115
+ if command == "template"
116
+ prepared = prepare_template_dependencies(member: member, runner: runner, memo: memo)
117
+ break memo if prepared == false
118
+ end
119
+
113
120
  command_text = workflow_command(member)
114
121
  result = runner.call(member: member, phase: command, command: command_text, env: workflow_env)
115
122
  memo << result
@@ -158,7 +165,16 @@ module Kettle
158
165
  return memo unless memo.last.ok?
159
166
  end
160
167
 
161
- memo << runner.call(member: member, phase: command, command: workflow_command(member), env: workflow_env)
168
+ prepared = prepare_template_dependencies(member: member, runner: runner, memo: memo)
169
+ return memo if prepared == false
170
+
171
+ memo << runner.call(
172
+ member: member,
173
+ phase: command,
174
+ command: workflow_command(member),
175
+ env: workflow_env,
176
+ stdout_line_handler: template_event_line_handler(member)
177
+ )
162
178
  return memo unless memo.last.ok?
163
179
 
164
180
  normalize_lockfiles(member: member, runner: runner, memo: memo, phase: "normalize_lockfiles")
@@ -646,6 +662,7 @@ module Kettle
646
662
  args << "--ci-workflows=#{ci_workflows}" if ci_workflows && !ci_workflows.to_s.empty?
647
663
  args << "--local-ci" if local_ci
648
664
  args << "--skip-bundle-audit" if skip_bundle_audit
665
+ args << "--skip-remotes=#{skip_remotes}" if skip_remotes && !skip_remotes.to_s.empty?
649
666
  return command if args.empty?
650
667
 
651
668
  command.is_a?(Array) ? [*command, *args] : "#{command} #{args.join(" ")}"
@@ -661,6 +678,16 @@ module Kettle
661
678
  workflows.join(",")
662
679
  end
663
680
 
681
+ def validate_skip_remotes(value)
682
+ return nil if value.nil? || value.to_s.empty?
683
+
684
+ remotes = value.to_s.split(",").map(&:strip)
685
+ invalid = remotes.find { |remote| remote.empty? || !remote.match?(/\A[A-Za-z0-9_.-]+\z/) }
686
+ raise Error, "invalid --skip-remotes value #{value.inspect}" if invalid
687
+
688
+ remotes.join(",")
689
+ end
690
+
664
691
  def release_env
665
692
  env = base_release_env
666
693
  env.merge!(env_overrides)
@@ -674,6 +701,7 @@ module Kettle
674
701
  env["K_RELEASE_CI_CONTINUE"] = "true" if continue_ci_failures
675
702
  env["K_RELEASE_CI_WORKFLOWS"] = ci_workflows if ci_workflows && !ci_workflows.to_s.empty?
676
703
  env["KETTLE_DEV_SKIP_BUNDLE_AUDIT"] = "true" if skip_bundle_audit
704
+ env["K_RELEASE_SKIP_REMOTES"] = skip_remotes if skip_remotes && !skip_remotes.to_s.empty?
677
705
  env
678
706
  end
679
707
 
@@ -886,6 +914,16 @@ module Kettle
886
914
  def template_command(member)
887
915
  command_text = config.template_command || default_template_command(member)
888
916
  command_text = append_template_family_args(command_text) if kettle_jem_template_command?(command_text)
917
+ append_template_skip_commit(command_text)
918
+ end
919
+
920
+ def template_prepare_command(member)
921
+ command_text = "kettle-jem prepare"
922
+ command_text = append_template_family_args(command_text)
923
+ append_template_skip_commit(command_text)
924
+ end
925
+
926
+ def append_template_skip_commit(command_text)
889
927
  return command_text if commit
890
928
  return command_text if command_text.is_a?(Array) && command_text.include?("--skip-commit")
891
929
  return [*command_text, "--skip-commit"] if command_text.is_a?(Array)
@@ -916,7 +954,11 @@ module Kettle
916
954
  env["KJ_REPOSITORY_TOPOLOGY"] = config.template_repository_topology if config.template_repository_topology
917
955
  end
918
956
  env.merge!(env_overrides)
919
- env.merge!(TEMPLATE_QUIET_ENV) if command == "template" && !debug
957
+ if command == "template" && verbose
958
+ env["KETTLE_JEM_VERBOSE"] = "true"
959
+ elsif command == "template" && !debug
960
+ env.merge!(TEMPLATE_QUIET_ENV)
961
+ end
920
962
  end
921
963
  end
922
964
 
@@ -926,8 +968,12 @@ module Kettle
926
968
 
927
969
  def append_template_family_args(command_text)
928
970
  args = []
929
- args << "--quiet" unless command_includes_arg?(command_text, "--quiet")
930
- args << "--json" unless command_includes_arg?(command_text, "--json")
971
+ if verbose
972
+ args << "--verbose" unless command_includes_arg?(command_text, "--verbose")
973
+ else
974
+ args << "--quiet" unless command_includes_arg?(command_text, "--quiet")
975
+ end
976
+ args << "--events" unless command_includes_arg?(command_text, "--events")
931
977
  append_command_args(command_text, args)
932
978
  end
933
979
 
@@ -946,6 +992,72 @@ module Kettle
946
992
  progress_io.flush if progress_io.respond_to?(:flush)
947
993
  end
948
994
 
995
+ def template_event_line_handler(member)
996
+ return nil unless progress_io
997
+
998
+ lambda do |line|
999
+ event = parse_template_event(line)
1000
+ next unless event
1001
+
1002
+ emit_template_event_progress(member, event)
1003
+ end
1004
+ end
1005
+
1006
+ def parse_template_event(line)
1007
+ payload = JSON.parse(line.to_s)
1008
+ (payload.is_a?(Hash) && payload["event_version"]) ? payload : nil
1009
+ rescue JSON::ParserError
1010
+ nil
1011
+ end
1012
+
1013
+ def emit_template_event_progress(member, event)
1014
+ case event["type"]
1015
+ when "phase_start"
1016
+ emit_template_event_line(member, ">", event["phase"].to_s)
1017
+ when "phase_finish"
1018
+ emit_template_event_line(member, phase_finish_event_mark(event), event["phase"].to_s)
1019
+ when "recipe"
1020
+ path = event["path"].to_s
1021
+ emit_template_event_line(member, template_event_mark(event, changed_mark: "*"), path)
1022
+ when "post_apply_step", "command_step"
1023
+ label = [event["phase"], event["name"]].map(&:to_s).reject(&:empty?).join(":")
1024
+ emit_template_event_line(member, template_event_mark(event), label)
1025
+ when "diagnostic"
1026
+ message = event["message"].to_s
1027
+ label = message.empty? ? event["kind"].to_s : message
1028
+ emit_template_event_line(member, "!", label)
1029
+ when "summary"
1030
+ emit_template_event_line(member, "done", "#{event["changed_count"].to_i} file#{"s" unless event["changed_count"].to_i == 1} changed")
1031
+ end
1032
+ end
1033
+
1034
+ def emit_template_event_line(member, mark, label)
1035
+ return if label.to_s.empty?
1036
+
1037
+ synchronize_template_progress do
1038
+ progress_io.puts("[#{member.name}] #{mark} #{label}")
1039
+ progress_io.flush if progress_io.respond_to?(:flush)
1040
+ end
1041
+ end
1042
+
1043
+ def template_event_mark(event, changed_mark: ".")
1044
+ mark = event["mark"].to_s
1045
+ return mark unless mark.empty?
1046
+
1047
+ event["changed"] ? changed_mark : "."
1048
+ end
1049
+
1050
+ def phase_finish_event_mark(event)
1051
+ return "F" if event["status"].to_s == "failed"
1052
+
1053
+ "."
1054
+ end
1055
+
1056
+ def synchronize_template_progress(&block)
1057
+ @template_progress_mutex ||= Mutex.new
1058
+ @template_progress_mutex.synchronize(&block)
1059
+ end
1060
+
949
1061
  def emit_template_progress_summary(results)
950
1062
  return unless progress_io
951
1063
 
@@ -957,6 +1069,9 @@ module Kettle
957
1069
  end
958
1070
 
959
1071
  def template_changed_file_count(result)
1072
+ event_count = template_changed_file_count_from_events(result.stdout)
1073
+ return event_count if event_count
1074
+
960
1075
  payload = JSON.parse(result.stdout.to_s)
961
1076
  Array(payload["changed_files"] || payload[:changed_files]).length if payload.is_a?(Hash)
962
1077
  rescue JSON::ParserError
@@ -966,6 +1081,16 @@ module Kettle
966
1081
  0
967
1082
  end
968
1083
 
1084
+ def template_changed_file_count_from_events(output)
1085
+ summaries = output.to_s.lines.filter_map do |line|
1086
+ event = parse_template_event(line)
1087
+ event if event && event["type"] == "summary"
1088
+ end
1089
+ return nil if summaries.empty?
1090
+
1091
+ summaries.last["changed_count"].to_i
1092
+ end
1093
+
969
1094
  def normalize_lockfiles(member:, runner:, memo:, phase:)
970
1095
  return unless config.normalize_lockfiles?
971
1096
 
@@ -978,6 +1103,27 @@ module Kettle
978
1103
  memo << result
979
1104
  end
980
1105
 
1106
+ def prepare_template_dependencies(member:, runner:, memo:)
1107
+ command_text = config.template_command || default_template_command(member)
1108
+ return true unless kettle_jem_template_command?(command_text)
1109
+
1110
+ result = runner.call(
1111
+ member: member,
1112
+ phase: "prepare_template_dependencies",
1113
+ command: template_prepare_command(member),
1114
+ env: template_prepare_env
1115
+ )
1116
+ memo << result
1117
+ result.ok?
1118
+ end
1119
+
1120
+ def template_prepare_env
1121
+ env = workflow_env
1122
+ family_env_name = config.family_local_path_env_name
1123
+ env[family_env_name] = "false" if family_env_name && !env_overrides.key?(family_env_name)
1124
+ env
1125
+ end
1126
+
981
1127
  def normalize_release_lockfiles(member:, runner:, memo:)
982
1128
  result = runner.call(
983
1129
  member: member,
@@ -1,68 +1,5 @@
1
1
  module Kettle
2
2
  module Family
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
5
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
6
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
7
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
8
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
9
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
10
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
11
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
12
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
13
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
14
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
15
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
16
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
17
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
18
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
19
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
20
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
21
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
22
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
23
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
24
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
25
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
26
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
27
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
28
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
29
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
30
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
31
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
32
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
33
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
34
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
35
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
36
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
37
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
38
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
39
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
40
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
41
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
42
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
43
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
44
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
45
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
46
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
47
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
48
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
49
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
50
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
51
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
52
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
53
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
54
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
55
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
56
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
57
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
58
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
59
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
60
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
61
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
62
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
63
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
64
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
65
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
66
3
  # See the writing guide of rbs: https://github.com/ruby/rbs#guides
67
4
  module Version
68
5
  VERSION: String
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.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -173,40 +173,40 @@ dependencies:
173
173
  requirements:
174
174
  - - "~>"
175
175
  - !ruby/object:Gem::Version
176
- version: '3.1'
176
+ version: '3.2'
177
177
  - - ">="
178
178
  - !ruby/object:Gem::Version
179
- version: 3.1.4
179
+ version: 3.2.0
180
180
  type: :development
181
181
  prerelease: false
182
182
  version_requirements: !ruby/object:Gem::Requirement
183
183
  requirements:
184
184
  - - "~>"
185
185
  - !ruby/object:Gem::Version
186
- version: '3.1'
186
+ version: '3.2'
187
187
  - - ">="
188
188
  - !ruby/object:Gem::Version
189
- version: 3.1.4
189
+ version: 3.2.0
190
190
  - !ruby/object:Gem::Dependency
191
191
  name: turbo_tests2
192
192
  requirement: !ruby/object:Gem::Requirement
193
193
  requirements:
194
194
  - - "~>"
195
195
  - !ruby/object:Gem::Version
196
- version: '3.1'
196
+ version: '3.2'
197
197
  - - ">="
198
198
  - !ruby/object:Gem::Version
199
- version: 3.1.14
199
+ version: 3.2.0
200
200
  type: :development
201
201
  prerelease: false
202
202
  version_requirements: !ruby/object:Gem::Requirement
203
203
  requirements:
204
204
  - - "~>"
205
205
  - !ruby/object:Gem::Version
206
- version: '3.1'
206
+ version: '3.2'
207
207
  - - ">="
208
208
  - !ruby/object:Gem::Version
209
- version: 3.1.14
209
+ version: 3.2.0
210
210
  - !ruby/object:Gem::Dependency
211
211
  name: ruby-progressbar
212
212
  requirement: !ruby/object:Gem::Requirement
@@ -303,10 +303,10 @@ licenses:
303
303
  - AGPL-3.0-only
304
304
  metadata:
305
305
  homepage_uri: https://kettle-family.galtzo.com
306
- source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.0.0
307
- changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.0.0/CHANGELOG.md
306
+ source_code_uri: https://github.com/kettle-dev/kettle-family/tree/v1.0.1
307
+ changelog_uri: https://github.com/kettle-dev/kettle-family/blob/v1.0.1/CHANGELOG.md
308
308
  bug_tracker_uri: https://github.com/kettle-dev/kettle-family/issues
309
- documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.0.0
309
+ documentation_uri: https://www.rubydoc.info/gems/kettle-family/1.0.1
310
310
  funding_uri: https://github.com/sponsors/pboling
311
311
  wiki_uri: https://github.com/kettle-dev/kettle-family/wiki
312
312
  news_uri: https://www.railsbling.com/tags/kettle-family
metadata.gz.sig CHANGED
Binary file