kettle-dev 3.1.9 → 3.1.10

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: 452c1019273fac5fa450b42b6bf0d24fee016a6641971eeb3c5bddcf08efaa64
4
- data.tar.gz: 4919f5ac1cd4aeb579da6ae378109923cf7fe86c6568b77ab42101e2f8bd4087
3
+ metadata.gz: 402314d89802c8ea05c0ad109c93b25ee8a703e767a5581855ac80ab1981f139
4
+ data.tar.gz: 91d16f55dfe212bb82f0506d030734daa151dcbd0cc1cf2cf9f7f4547597e82c
5
5
  SHA512:
6
- metadata.gz: 58be74c463a06ea48b7571ec6fffa36bcaca0da0eb5e1a7cab2b4d3765f7fe2a4be2932f1cf09bfc496c97a9fa32badcf36182eabcdf58e61f5eb8c7242c9d41
7
- data.tar.gz: 6e679af06a75e16ff6321f348cae64f8fa8c6884408f4fca7f20c7d5d8b5498bd4cf6bac270c0dc04a84747f3e67dffe7562c89e15d91afc38d11dd7f59e82f6
6
+ metadata.gz: 3e4c5dbd0e71242d0b8d7ad112858de871a169f76dfe49d1754525656e31f5d7421c324dcdbddc597a2a38e55228640f57d34a637d7d30f35a0565476a32442f
7
+ data.tar.gz: c1ceeb7a1c40a1f989ff4ba76fe44bebc988c76d82fb945c6f15ccac66d6e547e6924557bb3cef10f661fd1f91b82407613a014462bbae47fa63b8c70f460a52
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,23 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [3.1.10] - 2026-10-11
34
+
35
+ - TAG: [v3.1.10][3.1.10t]
36
+ - COVERAGE: 91.78% -- 6341/6909 lines in 49 files
37
+ - BRANCH COVERAGE: 75.83% -- 2412/3181 branches in 49 files
38
+ - 52.10% documented
39
+
40
+ ### Fixed
41
+
42
+ - appraisal:generate now deletes a stale Appraisal.root.gemfile.lock before its bundle install. The root appraisal lockfile is a gitignored local artifact that drifts after dependency bumps; a stale pin made appraisal:generate fail with an opaque "locked to X ... can no longer be found" (observed templating kettle-jem after ast-crispr-ruby-prism's floor moved to an unpublished version). appraisal:generate's contract is to work without resolving appraisal locks, so the stale lock is removed and Bundler resolves fresh.
43
+
44
+ ### Security
45
+
46
+ - InteractiveReleaseCommand now scrubs every configured secret from child output before printing, capturing, or logging it: a PTY echoes bytes written to its input back onto the output stream while the child's terminal echo is on (e.g. before RubyGems' noecho wraps the password read), so the gem signing passphrase previously appeared in release logs; the scrubber tracks written secrets in memory, removes them from every chunk including secrets split across chunk boundaries, and clears the prompt buffer after answering so a stale prompt cannot trigger a duplicate write
47
+
48
+ - kettle-release aborts at startup under a prerelease Bundler, and LockfileReset now treats a lockfile BUNDLED WITH a prerelease Bundler as drift: Bundler auto-installs the locked version (including betas) on every bundle install, so one beta-pinned lockfile re-infects every machine that bundles against it; the reset re-locks with the currently running stable Bundler
49
+
33
50
  ## [3.1.9] - 2026-10-09
34
51
 
35
52
  - TAG: [v3.1.9][3.1.9t]
@@ -4021,7 +4038,9 @@ Please file a bug if you notice a violation of semantic versioning.
4021
4038
  - Selecting will run the selected workflow via `act`
4022
4039
  - This may move to its own gem in the future.
4023
4040
 
4024
- [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.1.9...HEAD
4041
+ [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.1.10...HEAD
4042
+ [3.1.10]: https://github.com/kettle-dev/kettle-dev/compare/v3.1.9...v3.1.10
4043
+ [3.1.10t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.1.10
4025
4044
  [3.1.9]: https://github.com/kettle-dev/kettle-dev/compare/v3.1.8...v3.1.9
4026
4045
  [3.1.9t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.1.9
4027
4046
  [3.1.8]: https://github.com/kettle-dev/kettle-dev/compare/v3.1.7...v3.1.8
data/README.md CHANGED
@@ -1067,7 +1067,7 @@ Thanks for RTFM. ☺️
1067
1067
  [📌gitmoji]: https://gitmoji.dev
1068
1068
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
1069
1069
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
1070
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-6.848-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1070
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-6.909-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
1071
1071
  [🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
1072
1072
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
1073
1073
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
@@ -14,6 +14,14 @@ module Kettle
14
14
  @secret_event_handler = secret_event_handler
15
15
  @forward_stdin = forward_stdin
16
16
  @gem_signing_passphrase = nil
17
+ # Secrets are written to the PTY master to answer child prompts. A PTY
18
+ # slave still echoes what is typed while the child has not yet disabled
19
+ # terminal echo (RubyGems' ask_for_password only wraps gets in noecho),
20
+ # so the secret bytes can bounce back into the PTY output stream and —
21
+ # without filtering — land in release logs. Track every secret written
22
+ # and scrub it from all child output before it is printed or captured.
23
+ @written_secrets = []
24
+ @secret_scrub_carryover = +""
17
25
  end
18
26
 
19
27
  def call(env, cmd)
@@ -44,14 +52,35 @@ module Kettle
44
52
  input.write(@input.readpartial(1024))
45
53
  else
46
54
  chunk = output.readpartial(1024)
55
+ # Two views of the same bytes, with independent state.
56
+ #
57
+ # Emitted view: holds back a trailing window so a secret
58
+ # split across chunks can never reach the log; the window
59
+ # is released by flush_secret_scrub_carryover at stream end.
60
+ #
61
+ # Prompt view: scrubbed but never held back. A child that
62
+ # prints its prompt and then blocks on stdin (Gem's OTP
63
+ # `Code: ` ask) produces no further output; if the prompt
64
+ # tail sat in the emitted view's holdback, detection would
65
+ # never fire and the child would deadlock. The prompt view
66
+ # therefore scrubs the raw chunk directly (plus the emitted
67
+ # view's carryover, read-only, so bytes spanning the
68
+ # boundary are still masked) instead of consuming it.
69
+ chunk = scrub_secrets_from_chunk(chunk)
70
+ prompt_text = scrub_secrets_for_prompt_detection(chunk)
47
71
  stdout_str << chunk
48
72
  @output.print(chunk)
49
- prompt_buffer = handle_prompt(input, chunk, prompt_buffer: prompt_buffer)
73
+ prompt_buffer = handle_prompt(input, prompt_text, prompt_buffer: prompt_buffer)
50
74
  end
51
75
  end
52
76
  end
53
77
  rescue Errno::EIO, EOFError
54
78
  # PTY platforms signal a closed child with EIO or EOFError.
79
+ chunk = flush_secret_scrub_carryover
80
+ unless chunk.empty?
81
+ stdout_str << chunk
82
+ @output.print(chunk)
83
+ end
55
84
  rescue Kettle::Dev::Error
56
85
  Process.kill("TERM", pid)
57
86
  raise
@@ -78,6 +107,7 @@ module Kettle
78
107
  else
79
108
  begin
80
109
  chunk = reader.readpartial(1024)
110
+ chunk = scrub_secrets_from_chunk(chunk)
81
111
  if reader.equal?(output)
82
112
  stdout_str << chunk
83
113
  @output.print(chunk)
@@ -93,6 +123,11 @@ module Kettle
93
123
  end
94
124
  end
95
125
  status = wait_thread.value
126
+ chunk = flush_secret_scrub_carryover
127
+ unless chunk.empty?
128
+ stdout_str << chunk
129
+ @output.print(chunk)
130
+ end
96
131
  end
97
132
  [stdout_str, stderr_str, status]
98
133
  end
@@ -110,7 +145,15 @@ module Kettle
110
145
  return prompt_buffer
111
146
  end
112
147
 
113
- write_secret(input, label: "gem signing passphrase", source: "gem_signing_passphrase") { gem_signing_passphrase } if signing_password_prompt?(prompt_buffer)
148
+ if signing_password_prompt?(prompt_buffer)
149
+ write_secret(input, label: "gem signing passphrase", source: "gem_signing_passphrase") { gem_signing_passphrase }
150
+ # Clear the buffer after answering: otherwise the stale prompt text
151
+ # re-matches on every subsequent chunk and writes the secret again.
152
+ # The duplicate write happens after the child has restored terminal
153
+ # echo (RubyGems' noecho wraps only the gets call), so its bytes echo
154
+ # back through the PTY and land in the captured output and logs.
155
+ return +""
156
+ end
114
157
  prompt_buffer
115
158
  end
116
159
 
@@ -129,6 +172,11 @@ module Kettle
129
172
  @output.puts("#{label} loaded from configured secrets provider.")
130
173
  input.write("#{secret}\n")
131
174
  input.flush
175
+ # Register AFTER writing: a chunk currently in flight may contain a
176
+ # legitimately echoed prompt line, but anything the child echoes from
177
+ # this point on that contains the secret bytes is PTY echo of the write
178
+ # and must never reach @output, captured output, or release logs.
179
+ register_secret!(secret)
132
180
  emit_secret_event(source: source, action: "prompt_response", status: "ok", label: label)
133
181
  rescue Kettle::Dev::Error => error
134
182
  emit_secret_event(source: source, action: "prompt_response", status: "failed", label: label, reason: error.message)
@@ -139,6 +187,57 @@ module Kettle
139
187
  secret_event_handler&.call(payload)
140
188
  end
141
189
 
190
+ # Never persist secret values. Register the exact byte string so the
191
+ # scrubber can recognize it in child output without logging it.
192
+ def register_secret!(secret)
193
+ secret = secret.to_s
194
+ return if secret.empty?
195
+
196
+ @written_secrets << secret unless @written_secrets.include?(secret)
197
+ @written_secrets.shift if @written_secrets.length > 8
198
+ end
199
+
200
+ # Secrets typed into a PTY can be echoed back when the child's terminal
201
+ # echo is momentarily on (e.g. before Gem's noecho gets runs). Remove
202
+ # registered secret byte sequences from every chunk before printing or
203
+ # capturing. A chunk boundary can split a secret, so carry a trailing
204
+ # window of the longest secret forward to the next chunk.
205
+ def scrub_secrets_from_chunk(chunk)
206
+ return chunk if @written_secrets.empty? || chunk.empty?
207
+
208
+ window = @written_secrets.map(&:bytesize).max || 0
209
+ buffer = @secret_scrub_carryover + chunk
210
+ buffer = buffer.gsub(Regexp.union(@written_secrets), "[SECRET REMOVED]")
211
+ if buffer.bytesize >= window && window > 0
212
+ @secret_scrub_carryover = buffer.byteslice(-window, window).to_s
213
+ buffer.byteslice(0, buffer.bytesize - window).to_s
214
+ else
215
+ @secret_scrub_carryover = buffer
216
+ +""
217
+ end
218
+ end
219
+
220
+ # At stream end nothing else can reveal a secret split across chunks, so
221
+ # release the held trailing window (already scrubbed once).
222
+ def flush_secret_scrub_carryover
223
+ chunk = @secret_scrub_carryover
224
+ @secret_scrub_carryover = +""
225
+ chunk
226
+ end
227
+
228
+ # Prompt-detection view: scrubbed, but never holds back a trailing
229
+ # window. Reads (never consumes) the emitted view's carryover so bytes
230
+ # spanning a chunk boundary are still masked here. Without this view, a
231
+ # prompt whose tail falls inside the holdback — a child that blocks on
232
+ # stdin and produces no further output — would never be answered, and
233
+ # the release would deadlock.
234
+ def scrub_secrets_for_prompt_detection(chunk)
235
+ return chunk if @written_secrets.empty?
236
+
237
+ buffer = @secret_scrub_carryover + chunk
238
+ buffer.gsub(Regexp.union(@written_secrets), "[SECRET REMOVED]")
239
+ end
240
+
142
241
  def otp_prompt?(chunk)
143
242
  chunk.match?(/(?:multi-factor authentication|OTP code|one-time password|\bCode:\s*)/i)
144
243
  end
@@ -311,6 +311,7 @@ module Kettle
311
311
  has_local_path_remote?(path, strict: strict) ||
312
312
  !empty_registry_checksums(path).empty? ||
313
313
  !unreleased_workspace_registry_specs(path).empty? ||
314
+ bundled_with_prerelease?(path) ||
314
315
  bundled_with_checksum_mismatch?(path)
315
316
  end
316
317
 
@@ -325,6 +326,9 @@ module Kettle
325
326
  unreleased_workspace_registry_specs(path).each do |name, version, line_number|
326
327
  diagnostics << "#{display_path(path)} locks local workspace gem #{name} #{version} as a registry gem, but that version is not resolvable from the configured gem source at line #{line_number}"
327
328
  end
329
+ if bundled_with_prerelease?(path)
330
+ diagnostics.push("#{display_path(path)} BUNDLED WITH #{bundled_with_version(path)} is a prerelease Bundler; re-lock with a stable Bundler")
331
+ end
328
332
  if bundled_with_checksum_mismatch?(path)
329
333
  diagnostics.push("#{display_path(path)} BUNDLED WITH #{bundled_with_version(path)} has no matching Bundler checksum")
330
334
  end
@@ -542,6 +546,19 @@ module Kettle
542
546
  ""
543
547
  end
544
548
 
549
+ # A lockfile pinned to a prerelease Bundler re-infects every machine that
550
+ # runs bundle install against it: Bundler auto-installs the locked version
551
+ # (including betas) before doing anything else. Treat it as drift and let
552
+ # the reset re-lock with the currently running stable Bundler.
553
+ def bundled_with_prerelease?(path)
554
+ version = bundled_with_version(path)
555
+ return false if version.empty?
556
+
557
+ Gem::Version.new(version).prerelease?
558
+ rescue ArgumentError
559
+ false
560
+ end
561
+
545
562
  def path_source_gems(path)
546
563
  lockfile_parser(path).specs.each_with_object(Set.new) do |spec, gems|
547
564
  source = spec.source
@@ -54,6 +54,19 @@ begin
54
54
  end
55
55
 
56
56
  run_generate_steps = lambda do
57
+ # The root appraisal lockfile is a local artifact (gitignored) that drifts
58
+ # after dependency bumps. A stale pin makes `bundle install` fail with an
59
+ # opaque "locked to X ... can no longer be found" — observed when a family
60
+ # member's gemspec floor was raised to an unpublished sibling version.
61
+ # appraisal:generate's contract is to work without resolving appraisal
62
+ # locks, so delete the stale root lock and let Bundler resolve fresh from
63
+ # Appraisal.root.gemfile.
64
+ root_appraisal_lock = File.join("Appraisal.root.gemfile.lock")
65
+ if File.file?(root_appraisal_lock)
66
+ File.delete(root_appraisal_lock)
67
+ puts("[kettle-dev][appraisal:generate] deleted stale #{root_appraisal_lock}")
68
+ end
69
+
57
70
  # 1) BUNDLE_GEMFILE=Appraisal.root.gemfile bundle install
58
71
  run_command.call(
59
72
  "appraisal:generate failed: BUNDLE_GEMFILE=Appraisal.root.gemfile bundle install",
@@ -1859,6 +1859,13 @@ module Kettle
1859
1859
  if ver < min
1860
1860
  abort("kettle-release requires Bundler >= 2.7.0 for reproducible builds by default. Current: #{Bundler::VERSION}. Please upgrade bundler.")
1861
1861
  end
1862
+ if ver.prerelease?
1863
+ abort(
1864
+ "kettle-release refuses to run under a prerelease Bundler (#{Bundler::VERSION}). " \
1865
+ "Prerelease Bundler has repeatedly introduced release-breaking behavior changes. " \
1866
+ "Run `gem uninstall bundler -v #{Bundler::VERSION}` and install the latest stable Bundler."
1867
+ )
1868
+ end
1862
1869
  end
1863
1870
 
1864
1871
  # Keep Bundler maintenance separate from the release metadata commit.
@@ -1882,8 +1889,18 @@ module Kettle
1882
1889
  appraisal_gemfile = File.join(@root, "Appraisal.root.gemfile")
1883
1890
  if File.file?(appraisal_gemfile)
1884
1891
  appraisal_lockfile = File.join(@root, "Appraisal.root.gemfile.lock")
1885
- appraisal_command = "BUNDLE_GEMFILE=#{Shellwords.escape(appraisal_gemfile)} " \
1886
- "BUNDLE_LOCKFILE=#{Shellwords.escape(appraisal_lockfile)} bundle update --bundler=#{bundler_version}"
1892
+ appraisal_env = "BUNDLE_GEMFILE=#{Shellwords.escape(appraisal_gemfile)} " \
1893
+ "BUNDLE_LOCKFILE=#{Shellwords.escape(appraisal_lockfile)}"
1894
+ # The appraisal root lockfile is a gitignored local artifact; the
1895
+ # release lockfile reset restores repo state by removing untracked
1896
+ # files, so it is frequently absent here. `bundle update` refuses to
1897
+ # run against a missing lockfile ("This Bundle hasn't been installed
1898
+ # yet"), so materialize the bundle first — bundle install writes the
1899
+ # lockfile and is a no-op when everything is already installed.
1900
+ unless File.file?(appraisal_lockfile)
1901
+ run_cmd!(release_project_command("#{appraisal_env} bundle install"))
1902
+ end
1903
+ appraisal_command = "#{appraisal_env} bundle update --bundler=#{bundler_version}"
1887
1904
  run_cmd!(release_project_command(appraisal_command))
1888
1905
  run_cmd!(release_project_command("bundle exec rake appraisal:reset"))
1889
1906
  end
@@ -12,6 +12,47 @@ module Kettle
12
12
  ENV_TRUE_RE = /\A(1|true|y|yes)\z/i unless const_defined?(:ENV_TRUE_RE, false)
13
13
 
14
14
  module RubyGemsVersions
15
+ # ---------------------------------------------------------------------------
16
+ # Registry answer caches: which one to build on
17
+ # ---------------------------------------------------------------------------
18
+ #
19
+ # Registry answers are cached at three layers. Each has a distinct scope
20
+ # and purpose; pick by the question your tool asks, not by proximity.
21
+ #
22
+ # 1. THE PERSISTENT CACHE — this module (disk, ~30-day TTL, keyed
23
+ # [name, source]). The only cross-process layer. Use it, via
24
+ # #published_version_numbers / #fetch, whenever your tool needs
25
+ # "what versions exist on this registry" and can tolerate the TTL
26
+ # window. Source-keyed because gem.coop can lag rubygems.org — a
27
+ # version present on one can be absent from the other, so the two
28
+ # registries must never share entries.
29
+ # Built on by: kettle-jem deps-floor, kettle-family bup pre-clean.
30
+ #
31
+ # 2. THE SNAPSHOT MEMO — kettle-family PublishedVersionCheck::REGISTRY_MEMO
32
+ # (process-local, keyed [name, remote, version]). NOT a performance
33
+ # layer. Exists for snapshot consistency: one command run must see one
34
+ # registry snapshot, so a gem landing mid-run cannot be reported
35
+ # unpublished for early members and published for later ones. It also
36
+ # owns the just-released bypass: the disk cache can hold a pre-publish
37
+ # answer, and only this layer knows which exact pinned version the
38
+ # caller cares about, so only here can kettle-release's on-disk
39
+ # release marker override the disk cache for that gem+version.
40
+ # Built on by: kettle-family bup/release lockfile validation.
41
+ #
42
+ # 3. THE RUN-LEVEL MEMO — kettle-family ReleasePreClean@published
43
+ # (per-command-instance, keyed name). Fail-open sentinel: registry
44
+ # answers memoized as nil mean "unreachable — remove nothing", which
45
+ # is this command's safety rule. Also collapses repeated per-member
46
+ # lookups of the same name into one answer within the run.
47
+ # Built on by: kettle-family release-mode bup pre-clean.
48
+ #
49
+ # Rule of thumb: persistence goes at layer 1, correctness-scoping
50
+ # (snapshot/bypass) at layer 2, command-local safety policy at layer 3.
51
+ # A future tool that needs "is this version published" should call
52
+ # layer 1, and add a higher layer ONLY if it needs snapshot
53
+ # consistency or its own failure policy.
54
+ #
55
+ # -------------------------------------------------------------------------
15
56
  CACHE_BUST_TTL_SECONDS = 30 * 24 * 60 * 60
16
57
  VERSION_CACHE_TTL_SECONDS = 30 * 24 * 60 * 60
17
58
  HTTP_OPEN_TIMEOUT_SECONDS = 5
@@ -5,7 +5,7 @@ module Kettle
5
5
  # Version namespace for this gem.
6
6
  module Version
7
7
  # Current gem version.
8
- VERSION = "3.1.9"
8
+ VERSION = "3.1.10"
9
9
  end
10
10
  # Current gem version exposed at the traditional constant location.
11
11
  VERSION = Version::VERSION # Traditional Constant Location
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: 3.1.9
4
+ version: 3.1.10
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -60,7 +60,7 @@ dependencies:
60
60
  version: '0.3'
61
61
  - - ">="
62
62
  - !ruby/object:Gem::Version
63
- version: 0.3.16
63
+ version: 0.3.17
64
64
  type: :runtime
65
65
  prerelease: false
66
66
  version_requirements: !ruby/object:Gem::Requirement
@@ -70,7 +70,7 @@ dependencies:
70
70
  version: '0.3'
71
71
  - - ">="
72
72
  - !ruby/object:Gem::Version
73
- version: 0.3.16
73
+ version: 0.3.17
74
74
  - !ruby/object:Gem::Dependency
75
75
  name: kettle-ndjson
76
76
  requirement: !ruby/object:Gem::Requirement
@@ -80,7 +80,7 @@ dependencies:
80
80
  version: '0.1'
81
81
  - - ">="
82
82
  - !ruby/object:Gem::Version
83
- version: 0.1.18
83
+ version: 0.1.19
84
84
  type: :runtime
85
85
  prerelease: false
86
86
  version_requirements: !ruby/object:Gem::Requirement
@@ -90,7 +90,7 @@ dependencies:
90
90
  version: '0.1'
91
91
  - - ">="
92
92
  - !ruby/object:Gem::Version
93
- version: 0.1.18
93
+ version: 0.1.19
94
94
  - !ruby/object:Gem::Dependency
95
95
  name: kettle-rb
96
96
  requirement: !ruby/object:Gem::Requirement
@@ -100,7 +100,7 @@ dependencies:
100
100
  version: '0.1'
101
101
  - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: 0.1.15
103
+ version: 0.1.17
104
104
  type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
@@ -110,7 +110,7 @@ dependencies:
110
110
  version: '0.1'
111
111
  - - ">="
112
112
  - !ruby/object:Gem::Version
113
- version: 0.1.15
113
+ version: 0.1.17
114
114
  - !ruby/object:Gem::Dependency
115
115
  name: kettle-test
116
116
  requirement: !ruby/object:Gem::Requirement
@@ -120,7 +120,7 @@ dependencies:
120
120
  version: '2.0'
121
121
  - - ">="
122
122
  - !ruby/object:Gem::Version
123
- version: 2.0.23
123
+ version: 2.0.24
124
124
  type: :runtime
125
125
  prerelease: false
126
126
  version_requirements: !ruby/object:Gem::Requirement
@@ -130,7 +130,7 @@ dependencies:
130
130
  version: '2.0'
131
131
  - - ">="
132
132
  - !ruby/object:Gem::Version
133
- version: 2.0.23
133
+ version: 2.0.24
134
134
  - !ruby/object:Gem::Dependency
135
135
  name: ruby-progressbar
136
136
  requirement: !ruby/object:Gem::Requirement
@@ -422,10 +422,10 @@ licenses:
422
422
  - AGPL-3.0-only
423
423
  metadata:
424
424
  homepage_uri: https://kettle-dev.galtzo.com
425
- source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v3.1.9
426
- changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.1.9/CHANGELOG.md
425
+ source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v3.1.10
426
+ changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.1.10/CHANGELOG.md
427
427
  bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
428
- documentation_uri: https://www.rubydoc.info/gems/kettle-dev/3.1.9
428
+ documentation_uri: https://www.rubydoc.info/gems/kettle-dev/3.1.10
429
429
  funding_uri: https://github.com/sponsors/pboling
430
430
  wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
431
431
  news_uri: https://www.railsbling.com/tags/kettle-dev
metadata.gz.sig CHANGED
@@ -1 +1,5 @@
1
- "���5s_�4+���ٻ\�ڋlb=��*��%�.$/��>���Z���=Q�R%���J�+Z ���2����3��YX
1
+ ��yo}��+'�c��Q��UK�N��*v;�\/�P���Z-Y�^���.�%��EV5
2
+ za*/�◅*q� �r���.]��/���j �y�?��v�¾���4\����%��$"�wD<�%�V�w���49�G[��~���9\�!0ʄ�gYe�R���;99�� "K�:}KCr
3
+ e+�
4
+ ������_Žg��,�C� ���� �3$G+�T�]jJ!�I�{���{�pAD�7'B�<4��U�(“�^�A�nK����r0x�-�Rc>ެ?%���Q%u�2������w��$>��L�w؝��n��J}C
5
+ �8�����b�l�-r��CdYU*���Ku�$�����G�p;�7vO>�