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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data/CHANGELOG.md +20 -1
- data/README.md +1 -1
- data/lib/kettle/dev/interactive_release_command.rb +101 -2
- data/lib/kettle/dev/lockfile_reset.rb +17 -0
- data/lib/kettle/dev/rakelib/appraisal.rake +13 -0
- data/lib/kettle/dev/release_cli.rb +19 -2
- data/lib/kettle/dev/ruby_gems_versions.rb +41 -0
- data/lib/kettle/dev/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +12 -12
- metadata.gz.sig +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 402314d89802c8ea05c0ad109c93b25ee8a703e767a5581855ac80ab1981f139
|
|
4
|
+
data.tar.gz: 91d16f55dfe212bb82f0506d030734daa151dcbd0cc1cf2cf9f7f4547597e82c
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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.
|
|
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.
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
1886
|
-
"BUNDLE_LOCKFILE=#{Shellwords.escape(appraisal_lockfile)}
|
|
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
|
data/lib/kettle/dev/version.rb
CHANGED
|
@@ -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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
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.
|
|
426
|
-
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.1.
|
|
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.
|
|
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
|
-
|
|
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>�
|