kettle-dev 3.0.1 → 3.0.2
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/exe/kettle-pre-release +4 -0
- data/lib/kettle/dev/lockfile_reset.rb +18 -3
- data/lib/kettle/dev/pre_release_cli.rb +6 -2
- data/lib/kettle/dev/release_cli.rb +32 -3
- data/lib/kettle/dev/release_secrets.rb +74 -4
- data/lib/kettle/dev/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +6 -6
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: ac5e19991ef314add0cbb6f8c764a0389df6003ea291e5ea08bb76bf32c2786a
|
|
4
|
+
data.tar.gz: 894c0f1521ec987771056394037f3aa2108634bea11830c47f630b43b65727e7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2bbb2b78730584bfdddbf66664679393ec7c282ea8e24130b01019bc4e61c48da2d4be751d354679c0a76f6ac4ed23a28bfcf60efae081468ffa98cfbe66dfb5
|
|
7
|
+
data.tar.gz: cc6156801f9ef0b6cd6e39ee614b63729acff1862e83cd4390319a98a6978ef06e148d82c255beb38a0d68a09531e435a4d57c7f315a9e4f4cb1cd929b16edff
|
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.0.2] - 2026-08-10
|
|
34
|
+
|
|
35
|
+
- TAG: [v3.0.2][3.0.2t]
|
|
36
|
+
- COVERAGE: 91.56% -- 5629/6148 lines in 47 files
|
|
37
|
+
- BRANCH COVERAGE: 76.14% -- 2128/2795 branches in 47 files
|
|
38
|
+
- 51.00% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- Stop polling 1Password during release monitoring and support family-owned release secret brokers.
|
|
43
|
+
|
|
44
|
+
- Allow pre-release GitHub Actions pin validation to use the explicitly requested persistent cache when live TLS access is unavailable.
|
|
45
|
+
|
|
46
|
+
- Detect locally installed unreleased workspace gems through an unbundled RubyGems probe during release lockfile normalization.
|
|
47
|
+
|
|
48
|
+
- Isolate standalone kettle-changelog coverage and tests from family release orchestration environment.
|
|
49
|
+
|
|
33
50
|
## [3.0.1] - 2026-08-10
|
|
34
51
|
|
|
35
52
|
- TAG: [v3.0.1][3.0.1t]
|
|
@@ -3414,7 +3431,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
3414
3431
|
- Selecting will run the selected workflow via `act`
|
|
3415
3432
|
- This may move to its own gem in the future.
|
|
3416
3433
|
|
|
3417
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.
|
|
3434
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.2...HEAD
|
|
3435
|
+
[3.0.2]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.1...v3.0.2
|
|
3436
|
+
[3.0.2t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.2
|
|
3418
3437
|
[3.0.1]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.0...v3.0.1
|
|
3419
3438
|
[3.0.1t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.1
|
|
3420
3439
|
[3.0.0]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.28...v3.0.0
|
data/README.md
CHANGED
|
@@ -1007,7 +1007,7 @@ Thanks for RTFM. ☺️
|
|
|
1007
1007
|
[📌gitmoji]: https://gitmoji.dev
|
|
1008
1008
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1009
1009
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1010
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-6.
|
|
1010
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-6.148-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1011
1011
|
[🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
|
|
1012
1012
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1013
1013
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/exe/kettle-pre-release
CHANGED
|
@@ -59,6 +59,10 @@ parser = OptionParser.new do |opts|
|
|
|
59
59
|
puts " KETTLE_IMAGE_URL_CACHE=/path/to/cache.json Use a custom cache path"
|
|
60
60
|
puts " KETTLE_IMAGE_URL_CACHE=false Disable the image URL cache"
|
|
61
61
|
puts " KETTLE_IMAGE_URL_CACHE_REFRESH=true Ignore cached successes and refresh"
|
|
62
|
+
puts
|
|
63
|
+
puts "GitHub Actions pin cache:"
|
|
64
|
+
puts " Live cache validation is the default and refreshes stale entries from GitHub."
|
|
65
|
+
puts " KETTLE_PRE_RELEASE_GHA_SHA_PINS_OFFLINE=true Trust the persistent pin cache without network access"
|
|
62
66
|
exit(0)
|
|
63
67
|
end
|
|
64
68
|
end
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
require "set"
|
|
4
4
|
require "shellwords"
|
|
5
5
|
require "fileutils"
|
|
6
|
+
require "open3"
|
|
6
7
|
require "bundler"
|
|
7
8
|
|
|
8
9
|
require_relative "bundler_env_guard"
|
|
@@ -418,12 +419,26 @@ module Kettle
|
|
|
418
419
|
end
|
|
419
420
|
|
|
420
421
|
def locally_installed?(name, version)
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
422
|
+
_stdout, _stderr, status = Open3.capture3(
|
|
423
|
+
unbundled_env,
|
|
424
|
+
"gem",
|
|
425
|
+
"specification",
|
|
426
|
+
name,
|
|
427
|
+
"--version",
|
|
428
|
+
version.to_s,
|
|
429
|
+
"--local"
|
|
430
|
+
)
|
|
431
|
+
status.success?
|
|
432
|
+
rescue SystemCallError
|
|
424
433
|
false
|
|
425
434
|
end
|
|
426
435
|
|
|
436
|
+
def unbundled_env
|
|
437
|
+
UNBUNDLED_ENV_KEYS.each_with_object({}) do |key, env|
|
|
438
|
+
env[key] = nil
|
|
439
|
+
end
|
|
440
|
+
end
|
|
441
|
+
|
|
427
442
|
def gem_source_version_available?(name, version, source_urls)
|
|
428
443
|
urls = Array(source_urls).compact.uniq
|
|
429
444
|
return false if urls.empty?
|
|
@@ -316,8 +316,12 @@ module Kettle
|
|
|
316
316
|
# Check 1: Ensure GitHub Actions workflow action refs are current SHA pins.
|
|
317
317
|
# @return [void]
|
|
318
318
|
def check_github_actions_sha_pins!
|
|
319
|
-
|
|
320
|
-
|
|
319
|
+
offline = env_truthy?(ENV["KETTLE_PRE_RELEASE_GHA_SHA_PINS_OFFLINE"])
|
|
320
|
+
mode = offline ? "offline cache" : "live cache validation"
|
|
321
|
+
puts "[kettle-pre-release] Check 1: Validate GitHub Actions SHA pins (#{mode})"
|
|
322
|
+
args = ["--root", Dir.pwd, "--check", "--upgrade", "major"]
|
|
323
|
+
args << "--offline" if offline
|
|
324
|
+
status = Kettle::Dev::GhaShaPinsCLI.new(args).run!
|
|
321
325
|
return nil if status.zero?
|
|
322
326
|
|
|
323
327
|
Kettle::Dev::ExitAdapter.abort("GitHub Actions SHA pin validation failed")
|
|
@@ -46,6 +46,23 @@ module Kettle
|
|
|
46
46
|
"BUNDLE_SILENCE_ROOT_WARNING" => "true",
|
|
47
47
|
"BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES" => "true"
|
|
48
48
|
}.freeze
|
|
49
|
+
RELEASE_CHILD_ENV_KEYS = %w[
|
|
50
|
+
K_RELEASE_CI_CONTINUE
|
|
51
|
+
K_RELEASE_REQUIRED_REMOTES
|
|
52
|
+
KETTLE_FAMILY_CONFIG
|
|
53
|
+
KETTLE_PRE_RELEASE_GHA_SHA_PINS_OFFLINE
|
|
54
|
+
KETTLE_RELEASE_SECRETS_PROVIDER
|
|
55
|
+
KETTLE_RELEASE_SECRETS_BROKER
|
|
56
|
+
KETTLE_RELEASE_GEM_SIGNING_PASSPHRASE
|
|
57
|
+
KETTLE_RELEASE_GEM_SIGNING_PASSPHRASE_SOURCE
|
|
58
|
+
KETTLE_RELEASE_1PASSWORD_ACCOUNT
|
|
59
|
+
KETTLE_RELEASE_1PASSWORD_CLI
|
|
60
|
+
KETTLE_RELEASE_1PASSWORD_ITEM
|
|
61
|
+
KETTLE_RELEASE_1PASSWORD_GEM_SIGNING_PASSPHRASE_FIELD
|
|
62
|
+
KETTLE_RELEASE_1PASSWORD_RUBYGEMS_OTP_FIELD
|
|
63
|
+
KETTLE_RELEASE_1PASSWORD_GEM_SIGNING_PASSPHRASE_REFERENCE
|
|
64
|
+
KETTLE_RELEASE_1PASSWORD_RUBYGEMS_OTP_REFERENCE
|
|
65
|
+
].freeze
|
|
49
66
|
DEBUG_TRUE_VALUES = %w[1 true yes on].freeze
|
|
50
67
|
RELEASE_VALIDATION_SOURCE = "https://gem.coop"
|
|
51
68
|
|
|
@@ -110,7 +127,9 @@ module Kettle
|
|
|
110
127
|
env_hash = command_env
|
|
111
128
|
return env_hash unless project_bundle_command?(cmd)
|
|
112
129
|
|
|
113
|
-
env_hash.merge(BundlerEnvGuard.unbundled_env)
|
|
130
|
+
env_hash.merge(BundlerEnvGuard.unbundled_env).merge(
|
|
131
|
+
RELEASE_CHILD_ENV_KEYS.each_with_object({}) { |key, env| env[key] = nil }
|
|
132
|
+
)
|
|
114
133
|
end
|
|
115
134
|
|
|
116
135
|
def project_bundle_command?(cmd)
|
|
@@ -1170,7 +1189,7 @@ module Kettle
|
|
|
1170
1189
|
Kettle::Dev::CIMonitor.monitor_all!(
|
|
1171
1190
|
restart_hint: restart_hint,
|
|
1172
1191
|
workflows: @ci_workflows,
|
|
1173
|
-
keepalive:
|
|
1192
|
+
keepalive: release_secrets_keepalive_required? ? -> { keep_release_secrets_alive!("CI monitoring") } : nil,
|
|
1174
1193
|
event_recorder: @event_recorder
|
|
1175
1194
|
)
|
|
1176
1195
|
emit_ci_monitor_event(action: "finish", status: "ok", workflows: @ci_workflows, restart_hint: restart_hint)
|
|
@@ -1368,7 +1387,7 @@ module Kettle
|
|
|
1368
1387
|
end
|
|
1369
1388
|
|
|
1370
1389
|
def keep_release_secrets_alive!(purpose)
|
|
1371
|
-
return unless
|
|
1390
|
+
return unless release_secrets_keepalive_required?
|
|
1372
1391
|
return unless @secrets_provider.respond_to?(:keepalive!)
|
|
1373
1392
|
|
|
1374
1393
|
emit_secret_event(action: "keepalive", status: "started", purpose: purpose, source: release_secrets_provider_label, elapsed: release_elapsed_label)
|
|
@@ -1379,6 +1398,16 @@ module Kettle
|
|
|
1379
1398
|
abort("Release secrets provider keepalive failed before #{purpose}: #{error.message}")
|
|
1380
1399
|
end
|
|
1381
1400
|
|
|
1401
|
+
def release_secrets_keepalive_required?
|
|
1402
|
+
return false unless release_secrets_configured?
|
|
1403
|
+
if @secrets_provider.respond_to?(:keepalive_required?)
|
|
1404
|
+
configured = @secrets_provider.keepalive_required?
|
|
1405
|
+
return configured unless configured.nil?
|
|
1406
|
+
end
|
|
1407
|
+
|
|
1408
|
+
true
|
|
1409
|
+
end
|
|
1410
|
+
|
|
1382
1411
|
def release_elapsed_label
|
|
1383
1412
|
return nil unless @started_at
|
|
1384
1413
|
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "open3"
|
|
4
|
+
require "json"
|
|
5
|
+
require "socket"
|
|
4
6
|
require "kettle/dev/interactive_release_command"
|
|
5
7
|
require "kettle/dev/release_notifier"
|
|
6
8
|
|
|
@@ -10,6 +12,10 @@ module Kettle
|
|
|
10
12
|
|
|
11
13
|
module ReleaseSecrets
|
|
12
14
|
class Provider
|
|
15
|
+
def keepalive_required?
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
|
|
13
19
|
def gem_signing_passphrase
|
|
14
20
|
nil
|
|
15
21
|
end
|
|
@@ -23,6 +29,63 @@ module Kettle
|
|
|
23
29
|
end
|
|
24
30
|
end
|
|
25
31
|
|
|
32
|
+
# Secret provider used by a family-owned release broker. The broker keeps
|
|
33
|
+
# all 1Password lookups in the family process; member release processes
|
|
34
|
+
# never authenticate independently.
|
|
35
|
+
class BrokerClient < Provider
|
|
36
|
+
def initialize(endpoint)
|
|
37
|
+
@endpoint = endpoint.to_s
|
|
38
|
+
raise Kettle::Dev::Error, "release secrets broker endpoint is required" if @endpoint.empty?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def gem_signing_passphrase
|
|
42
|
+
return cached_gem_signing_passphrase if cached_gem_signing_passphrase?
|
|
43
|
+
|
|
44
|
+
request("gem_signing_passphrase")
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def rubygems_otp
|
|
48
|
+
request("rubygems_otp")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# A family broker owns authorization. Polling must never start a new
|
|
52
|
+
# authentication lookup in the member process.
|
|
53
|
+
def keepalive!(elapsed: nil)
|
|
54
|
+
true
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def keepalive_required?
|
|
58
|
+
false
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
private
|
|
62
|
+
|
|
63
|
+
def cached_gem_signing_passphrase?
|
|
64
|
+
%w[cached family kettle-family].include?(ENV.fetch("KETTLE_RELEASE_GEM_SIGNING_PASSPHRASE_SOURCE", "").downcase)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def cached_gem_signing_passphrase
|
|
68
|
+
value = ENV.fetch("KETTLE_RELEASE_GEM_SIGNING_PASSPHRASE", "").to_s
|
|
69
|
+
raise Kettle::Dev::Error, "cached gem signing passphrase was requested but KETTLE_RELEASE_GEM_SIGNING_PASSPHRASE is empty" if value.empty?
|
|
70
|
+
|
|
71
|
+
value
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def request(operation)
|
|
75
|
+
socket = UNIXSocket.new(@endpoint)
|
|
76
|
+
socket.write(JSON.generate("operation" => operation))
|
|
77
|
+
socket.write("\n")
|
|
78
|
+
response = JSON.parse(socket.gets.to_s)
|
|
79
|
+
return response.fetch("value").to_s if response["ok"]
|
|
80
|
+
|
|
81
|
+
raise Kettle::Dev::Error, response.fetch("error", "release secrets broker request failed")
|
|
82
|
+
rescue Errno::ENOENT, Errno::ECONNREFUSED => error
|
|
83
|
+
raise Kettle::Dev::Error, "release secrets broker is unavailable: #{error.message}"
|
|
84
|
+
ensure
|
|
85
|
+
socket&.close
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
26
89
|
class OnePassword < Provider
|
|
27
90
|
PROVIDER_NAMES = %w[1password onepassword op].freeze
|
|
28
91
|
DEFAULTS = {
|
|
@@ -71,13 +134,16 @@ module Kettle
|
|
|
71
134
|
end
|
|
72
135
|
|
|
73
136
|
def keepalive!(elapsed: nil)
|
|
74
|
-
|
|
75
|
-
account
|
|
76
|
-
|
|
77
|
-
run_op(argv, purpose: "authorization keepalive", elapsed: elapsed, interactive: true)
|
|
137
|
+
# 1Password CLI authentication is session-scoped. Starting a fresh
|
|
138
|
+
# `op account get` for every release poll does not keep it alive; it
|
|
139
|
+
# only creates repeated authorization prompts and noise.
|
|
78
140
|
true
|
|
79
141
|
end
|
|
80
142
|
|
|
143
|
+
def keepalive_required?
|
|
144
|
+
false
|
|
145
|
+
end
|
|
146
|
+
|
|
81
147
|
private
|
|
82
148
|
|
|
83
149
|
attr_reader :config
|
|
@@ -177,6 +243,10 @@ module Kettle
|
|
|
177
243
|
provider_name.to_s
|
|
178
244
|
end
|
|
179
245
|
return Provider.new if name.empty? || name == "interactive"
|
|
246
|
+
if %w[family broker].include?(name.downcase)
|
|
247
|
+
endpoint = configured.fetch("endpoint", ENV.fetch("KETTLE_RELEASE_SECRETS_BROKER", ""))
|
|
248
|
+
return BrokerClient.new(endpoint)
|
|
249
|
+
end
|
|
180
250
|
return OnePassword.new(env_config.merge(configured)) if OnePassword.configured?(name)
|
|
181
251
|
|
|
182
252
|
raise Kettle::Dev::Error, "unsupported release secrets provider #{name.inspect}"
|
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.0.
|
|
8
|
+
VERSION = "3.0.2"
|
|
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.0.
|
|
4
|
+
version: 3.0.2
|
|
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.11
|
|
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.11
|
|
74
74
|
- !ruby/object:Gem::Dependency
|
|
75
75
|
name: kettle-ndjson
|
|
76
76
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -400,10 +400,10 @@ licenses:
|
|
|
400
400
|
- AGPL-3.0-only
|
|
401
401
|
metadata:
|
|
402
402
|
homepage_uri: https://kettle-dev.galtzo.com
|
|
403
|
-
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v3.0.
|
|
404
|
-
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.0.
|
|
403
|
+
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v3.0.2
|
|
404
|
+
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.0.2/CHANGELOG.md
|
|
405
405
|
bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
|
|
406
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/3.0.
|
|
406
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/3.0.2
|
|
407
407
|
funding_uri: https://github.com/sponsors/pboling
|
|
408
408
|
wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
|
|
409
409
|
news_uri: https://www.railsbling.com/tags/kettle-dev
|
metadata.gz.sig
CHANGED
|
Binary file
|