kettle-dev 2.5.4 → 2.5.5
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 +28 -1
- data/README.md +1 -1
- data/lib/kettle/dev/bundler_env_guard.rb +57 -0
- data/lib/kettle/dev/exit_adapter.rb +10 -0
- data/lib/kettle/dev/gem_source_probe.rb +96 -0
- data/lib/kettle/dev/lockfile_reset.rb +42 -33
- data/lib/kettle/dev/rakelib/yard.rake +2 -1
- data/lib/kettle/dev/release_cli.rb +45 -44
- data/lib/kettle/dev/version.rb +1 -1
- data/lib/kettle/dev.rb +2 -0
- data.tar.gz.sig +0 -0
- metadata +8 -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: 55c142437ccf4e28b174ed1a58df90a31a9e92401e7d2a230d1663eed6f40e25
|
|
4
|
+
data.tar.gz: fc1a6d490c79acd5da62afc7c363dfa6de8582d31670ebefba0a02c617c90ec0
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 01f059c2d48868c17eb93bcb29c897896b1b851af7d26fb686598d166253358b7b83b90c2e17fc7e50d634026f1fe86e41e2330d3c2a6226f9cf51634dc37542
|
|
7
|
+
data.tar.gz: a449b3e04bbc849e8914434b462a446595d82ed9a9714252307f39619f3ae66cd57c557f39396d0b06d0ad15f860e78a699aa4a8f69991f2d6a0a3d644851a69
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,31 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [2.5.5] - 2026-07-28
|
|
34
|
+
|
|
35
|
+
- TAG: [v2.5.5][2.5.5t]
|
|
36
|
+
- COVERAGE: 91.66% -- 4694/5121 lines in 44 files
|
|
37
|
+
- BRANCH COVERAGE: 76.18% -- 1772/2326 branches in 44 files
|
|
38
|
+
- 54.44% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- `kettle-release` and `kettle-reset release-lockfiles` now validate local
|
|
43
|
+
workspace gem versions with an isolated Bundler inline probe against the
|
|
44
|
+
configured gem source instead of RubyGems.org version APIs, and release task
|
|
45
|
+
lockfile resets retry transient source propagation failures.
|
|
46
|
+
|
|
47
|
+
- kettle-jem-template-20260728-002 - Generated RuboCop configs now ignore the
|
|
48
|
+
same `gemfiles/vendor/bundle` tree as `.gitignore`, so vendored dependency
|
|
49
|
+
installs are not reported as project lint debt.
|
|
50
|
+
- kettle-jem-template-20260728-003 - Generated dep-heads workflows now run
|
|
51
|
+
TruffleRuby jobs with current RubyGems and Bundler, avoiding setup failures
|
|
52
|
+
before the test suite starts.
|
|
53
|
+
|
|
54
|
+
- `kettle-release` and `kettle-reset` now warn when unexpected `BUNDLE_*` or
|
|
55
|
+
`BUNDLER_*` environment variables are present while preparing unbundled
|
|
56
|
+
subprocesses.
|
|
57
|
+
|
|
33
58
|
## [2.5.4] - 2026-07-28
|
|
34
59
|
|
|
35
60
|
- TAG: [v2.5.4][2.5.4t]
|
|
@@ -2939,7 +2964,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
2939
2964
|
- Selecting will run the selected workflow via `act`
|
|
2940
2965
|
- This may move to its own gem in the future.
|
|
2941
2966
|
|
|
2942
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.
|
|
2967
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.5...HEAD
|
|
2968
|
+
[2.5.5]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.4...v2.5.5
|
|
2969
|
+
[2.5.5t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.5.5
|
|
2943
2970
|
[2.5.4]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.3...v2.5.4
|
|
2944
2971
|
[2.5.4t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.5.4
|
|
2945
2972
|
[2.5.3]: https://github.com/kettle-dev/kettle-dev/compare/v2.5.2...v2.5.3
|
data/README.md
CHANGED
|
@@ -1005,7 +1005,7 @@ Thanks for RTFM. ☺️
|
|
|
1005
1005
|
[📌gitmoji]: https://gitmoji.dev
|
|
1006
1006
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1007
1007
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1008
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-5.
|
|
1008
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-5.121-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1009
1009
|
[🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
|
|
1010
1010
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1011
1011
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Kettle
|
|
4
|
+
module Dev
|
|
5
|
+
module BundlerEnvGuard
|
|
6
|
+
RESET_ENV_KEYS = %w[
|
|
7
|
+
BUNDLE_BIN_PATH
|
|
8
|
+
BUNDLE_FROZEN
|
|
9
|
+
BUNDLE_GEMFILE
|
|
10
|
+
BUNDLE_LOCKFILE
|
|
11
|
+
BUNDLER_SETUP
|
|
12
|
+
BUNDLER_VERSION
|
|
13
|
+
].freeze
|
|
14
|
+
|
|
15
|
+
INERT_ENV_KEYS = %w[
|
|
16
|
+
BUNDLE_DEBUG
|
|
17
|
+
BUNDLE_QUIET
|
|
18
|
+
BUNDLE_SILENCE_DEPRECATIONS
|
|
19
|
+
BUNDLE_SILENCE_ROOT_WARNING
|
|
20
|
+
BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES
|
|
21
|
+
BUNDLE_VERBOSE
|
|
22
|
+
].freeze
|
|
23
|
+
|
|
24
|
+
INERT_ENV_PREFIXES = %w[
|
|
25
|
+
BUNDLER_ORIG_
|
|
26
|
+
].freeze
|
|
27
|
+
|
|
28
|
+
module_function
|
|
29
|
+
|
|
30
|
+
def unbundled_env
|
|
31
|
+
RESET_ENV_KEYS.each_with_object({}) do |key, env|
|
|
32
|
+
env[key] = nil
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def warn_unexpected_env!(stream: $stderr)
|
|
37
|
+
unexpected = unexpected_env_keys
|
|
38
|
+
return if unexpected.empty?
|
|
39
|
+
|
|
40
|
+
stream.puts(
|
|
41
|
+
"[kettle-dev] Unexpected Bundler environment variable(s) present while preparing an unbundled subprocess: #{unexpected.join(", ")}. " \
|
|
42
|
+
"If this variable is safe, add it to BundlerEnvGuard::INERT_ENV_KEYS; otherwise add it to RESET_ENV_KEYS."
|
|
43
|
+
)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def unexpected_env_keys
|
|
47
|
+
ENV.to_hash.keys.grep(/\ABUNDLE(?:R)?_/).reject { |key| expected_env_key?(key) }.sort
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def expected_env_key?(key)
|
|
51
|
+
RESET_ENV_KEYS.include?(key) ||
|
|
52
|
+
INERT_ENV_KEYS.include?(key) ||
|
|
53
|
+
INERT_ENV_PREFIXES.any? { |prefix| key.start_with?(prefix) }
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
module Kettle
|
|
4
4
|
module Dev
|
|
5
|
+
class Error < StandardError; end unless const_defined?(:Error, false)
|
|
6
|
+
|
|
5
7
|
# Exit/abort indirection layer to allow controllable behavior in tests.
|
|
6
8
|
#
|
|
7
9
|
# Production/default behavior delegates to Kernel.abort / Kernel.exit,
|
|
@@ -13,6 +15,8 @@ module Kettle
|
|
|
13
15
|
#
|
|
14
16
|
# This adapter mirrors the "mockable adapter" approach used for GitAdapter.
|
|
15
17
|
module ExitAdapter
|
|
18
|
+
class AbortError < Kettle::Dev::Error; end
|
|
19
|
+
|
|
16
20
|
module_function
|
|
17
21
|
|
|
18
22
|
# Abort the current execution with a message. By default this calls Kernel.abort,
|
|
@@ -31,6 +35,12 @@ module Kettle
|
|
|
31
35
|
def exit(status = 0)
|
|
32
36
|
Kernel.exit(status)
|
|
33
37
|
end
|
|
38
|
+
|
|
39
|
+
def abort_as_error
|
|
40
|
+
yield
|
|
41
|
+
rescue SystemExit => error
|
|
42
|
+
raise AbortError, error.message
|
|
43
|
+
end
|
|
34
44
|
end
|
|
35
45
|
end
|
|
36
46
|
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "fileutils"
|
|
4
|
+
require "open3"
|
|
5
|
+
require "tmpdir"
|
|
6
|
+
|
|
7
|
+
require_relative "bundler_env_guard"
|
|
8
|
+
|
|
9
|
+
module Kettle
|
|
10
|
+
module Dev
|
|
11
|
+
class GemSourceProbe
|
|
12
|
+
UNBUNDLED_ENV_KEYS = (BundlerEnvGuard::RESET_ENV_KEYS + %w[
|
|
13
|
+
RUBYGEMS_GEMDEPS
|
|
14
|
+
RUBYLIB
|
|
15
|
+
RUBYOPT
|
|
16
|
+
]).freeze
|
|
17
|
+
|
|
18
|
+
def initialize(source_url:, ruby: Gem.ruby)
|
|
19
|
+
@source_url = source_url
|
|
20
|
+
@ruby = ruby
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def available?(name, version)
|
|
24
|
+
stderr = nil
|
|
25
|
+
BundlerEnvGuard.warn_unexpected_env!
|
|
26
|
+
with_probe_gem_home do |gem_home|
|
|
27
|
+
_stdout, stderr, status = Open3.capture3(
|
|
28
|
+
probe_env(gem_home),
|
|
29
|
+
"gem",
|
|
30
|
+
"install",
|
|
31
|
+
name,
|
|
32
|
+
"-v",
|
|
33
|
+
"= #{version}",
|
|
34
|
+
"--source",
|
|
35
|
+
source_url,
|
|
36
|
+
"--clear-sources",
|
|
37
|
+
"--ignore-dependencies",
|
|
38
|
+
"--no-document",
|
|
39
|
+
"--install-dir",
|
|
40
|
+
gem_home
|
|
41
|
+
)
|
|
42
|
+
status.success?
|
|
43
|
+
end
|
|
44
|
+
rescue SystemCallError => error
|
|
45
|
+
raise Error, "Could not verify #{name} #{version} from #{source_url}: #{error.message}"
|
|
46
|
+
ensure
|
|
47
|
+
warn(stderr) if ENV["KETTLE_DEV_DEBUG"] == "true" && stderr && !stderr.empty?
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.bundler_inline_script(name:, version:, source_url:)
|
|
51
|
+
<<~RUBY
|
|
52
|
+
# frozen_string_literal: true
|
|
53
|
+
|
|
54
|
+
require "bundler/inline"
|
|
55
|
+
|
|
56
|
+
gem_name = #{name.dump}
|
|
57
|
+
version = #{version.dump}
|
|
58
|
+
|
|
59
|
+
gemfile(true) do
|
|
60
|
+
source #{source_url.dump}
|
|
61
|
+
gem gem_name, "= \#{version}", require: false
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
spec = Gem::Specification.find_all_by_name(gem_name, "= \#{version}").first
|
|
65
|
+
abort("resolved no \#{gem_name} \#{version} spec from #{source_url}") unless spec
|
|
66
|
+
puts "Validated \#{gem_name} \#{version} from #{source_url}"
|
|
67
|
+
RUBY
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
private
|
|
71
|
+
|
|
72
|
+
attr_reader :source_url, :ruby
|
|
73
|
+
|
|
74
|
+
def with_probe_gem_home
|
|
75
|
+
base = File.join(Dir.pwd, "tmp")
|
|
76
|
+
FileUtils.mkdir_p(base)
|
|
77
|
+
Dir.mktmpdir("kettle-gem-source-probe-", base) do |gem_home|
|
|
78
|
+
yield(gem_home)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def probe_env(gem_home)
|
|
83
|
+
unbundled_env.merge(
|
|
84
|
+
"GEM_HOME" => gem_home,
|
|
85
|
+
"GEM_PATH" => gem_home
|
|
86
|
+
)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def unbundled_env
|
|
90
|
+
UNBUNDLED_ENV_KEYS.each_with_object({}) do |key, env|
|
|
91
|
+
env[key] = nil
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -3,11 +3,10 @@
|
|
|
3
3
|
require "set"
|
|
4
4
|
require "shellwords"
|
|
5
5
|
require "fileutils"
|
|
6
|
-
require "json"
|
|
7
|
-
require "net/http"
|
|
8
|
-
require "uri"
|
|
9
6
|
require "bundler"
|
|
10
7
|
|
|
8
|
+
require_relative "bundler_env_guard"
|
|
9
|
+
|
|
11
10
|
module Kettle
|
|
12
11
|
module Dev
|
|
13
12
|
class LockfileReset
|
|
@@ -22,12 +21,10 @@ module Kettle
|
|
|
22
21
|
}.freeze
|
|
23
22
|
RELEASE_LOCKFILES_TARGET = "release-lockfiles"
|
|
24
23
|
SUPPORTED_TARGETS = ["Gemfile.lock", "Appraisal.root.gemfile.lock", RELEASE_LOCKFILES_TARGET].freeze
|
|
25
|
-
UNBUNDLED_ENV_KEYS = %w[
|
|
26
|
-
|
|
27
|
-
BUNDLE_FROZEN
|
|
28
|
-
BUNDLER_VERSION
|
|
24
|
+
UNBUNDLED_ENV_KEYS = (BundlerEnvGuard::RESET_ENV_KEYS + %w[
|
|
25
|
+
RUBYLIB
|
|
29
26
|
RUBYOPT
|
|
30
|
-
].freeze
|
|
27
|
+
]).freeze
|
|
31
28
|
|
|
32
29
|
def initialize(root:, command_runner:)
|
|
33
30
|
@root = root
|
|
@@ -35,6 +32,7 @@ module Kettle
|
|
|
35
32
|
end
|
|
36
33
|
|
|
37
34
|
def reset(target)
|
|
35
|
+
BundlerEnvGuard.warn_unexpected_env!
|
|
38
36
|
paths = lockfile_paths_for(target)
|
|
39
37
|
force_full_update = release_lockfiles_target?(target)
|
|
40
38
|
uninstall_unreleased_local_gems(paths) if force_full_update
|
|
@@ -109,7 +107,7 @@ module Kettle
|
|
|
109
107
|
diagnostics << "#{display_path(path)} CHECKSUMS has no sha256 for #{name} #{version} at line #{line_number}"
|
|
110
108
|
end
|
|
111
109
|
unreleased_workspace_registry_specs(path).each do |name, version, line_number|
|
|
112
|
-
diagnostics << "#{display_path(path)} locks local workspace gem #{name} #{version} as a registry gem, but that version is not
|
|
110
|
+
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}"
|
|
113
111
|
end
|
|
114
112
|
diagnostics
|
|
115
113
|
end
|
|
@@ -232,9 +230,10 @@ module Kettle
|
|
|
232
230
|
local_names = local_workspace_gem_names
|
|
233
231
|
return [] if local_names.empty?
|
|
234
232
|
|
|
233
|
+
source_urls = registry_source_urls(path)
|
|
235
234
|
registry_specs_with_lines(path).filter_map do |name, version, line_number|
|
|
236
235
|
next unless local_names.include?(name)
|
|
237
|
-
next if
|
|
236
|
+
next if gem_source_version_available?(name, version, source_urls)
|
|
238
237
|
|
|
239
238
|
[name, version, line_number]
|
|
240
239
|
end
|
|
@@ -341,7 +340,7 @@ module Kettle
|
|
|
341
340
|
locked_registry_specs(paths).each do |name, version|
|
|
342
341
|
next unless local_names.include?(name)
|
|
343
342
|
next unless locally_installed?(name, version)
|
|
344
|
-
next if
|
|
343
|
+
next if gem_source_version_available?(name, version, source_urls_for_lockfiles(paths))
|
|
345
344
|
|
|
346
345
|
uninstall_unreleased_local_gem(name, version)
|
|
347
346
|
uninstalled = true
|
|
@@ -398,33 +397,43 @@ module Kettle
|
|
|
398
397
|
false
|
|
399
398
|
end
|
|
400
399
|
|
|
401
|
-
def
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
400
|
+
def gem_source_version_available?(name, version, source_urls)
|
|
401
|
+
urls = Array(source_urls).compact.uniq
|
|
402
|
+
return false if urls.empty?
|
|
403
|
+
|
|
404
|
+
urls.any? { |source_url| bundler_inline_version_available?(name, version, source_url) }
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
def bundler_inline_version_available?(name, version, source_url)
|
|
408
|
+
@gem_source_version_available ||= {}
|
|
409
|
+
cache_key = [source_url, name, version]
|
|
410
|
+
return @gem_source_version_available[cache_key] if @gem_source_version_available.key?(cache_key)
|
|
411
|
+
|
|
412
|
+
@gem_source_version_available[cache_key] = GemSourceProbe.new(source_url: source_url).available?(name, version)
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
def source_urls_for_lockfiles(paths)
|
|
416
|
+
paths.flat_map { |path| registry_source_urls(path) }.uniq
|
|
412
417
|
end
|
|
413
418
|
|
|
414
|
-
def
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
419
|
+
def registry_source_urls(path)
|
|
420
|
+
urls = []
|
|
421
|
+
in_gem = false
|
|
422
|
+
File.readlines(path).each do |line|
|
|
423
|
+
stripped = line.strip
|
|
424
|
+
if stripped == "GEM"
|
|
425
|
+
in_gem = true
|
|
426
|
+
next
|
|
427
|
+
end
|
|
428
|
+
if stripped.match?(/\A[A-Z][A-Z ]*\z/)
|
|
429
|
+
in_gem = stripped == "GEM"
|
|
430
|
+
next
|
|
421
431
|
end
|
|
432
|
+
next unless in_gem && stripped.start_with?("remote:")
|
|
422
433
|
|
|
423
|
-
|
|
424
|
-
@ruby_gems_versions[name] = versions
|
|
434
|
+
urls << stripped.delete_prefix("remote:").strip
|
|
425
435
|
end
|
|
426
|
-
|
|
427
|
-
raise Error, "Could not parse released versions for #{name} from RubyGems.org: #{error.message}"
|
|
436
|
+
urls
|
|
428
437
|
end
|
|
429
438
|
|
|
430
439
|
def uninstall_command(name, version)
|
|
@@ -34,13 +34,14 @@ begin
|
|
|
34
34
|
end
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
+
desc "Generate YARD documentation and run YARD lint"
|
|
37
38
|
task yard: "yard:lint"
|
|
38
39
|
Kettle::Dev.register_default("yard:lint")
|
|
39
40
|
Kettle::Dev.register_default("yard")
|
|
40
41
|
rescue LoadError
|
|
41
42
|
warn("[kettle-dev][yard.rake] failed to load yard") if Kettle::Dev::DEBUGGING
|
|
42
43
|
desc("(stub) yard is unavailable")
|
|
43
|
-
task(:yard) do
|
|
44
|
+
task(:yard) do # rubocop:disable Rake/DuplicateTask -- fallback when the real YARD task cannot load
|
|
44
45
|
warn("NOTE: yard isn't installed, or is disabled for #{RUBY_VERSION} in the current environment")
|
|
45
46
|
end
|
|
46
47
|
Kettle::Dev.register_default("yard")
|
|
@@ -18,6 +18,7 @@ require "kettle/rb/compat_matrix"
|
|
|
18
18
|
require "ruby-progressbar"
|
|
19
19
|
|
|
20
20
|
require_relative "interactive_release_command"
|
|
21
|
+
require_relative "exit_adapter"
|
|
21
22
|
require_relative "lockfile_reset"
|
|
22
23
|
require_relative "release_secrets"
|
|
23
24
|
|
|
@@ -69,7 +70,7 @@ module Kettle
|
|
|
69
70
|
ok = system(env_hash, cmd)
|
|
70
71
|
unless ok
|
|
71
72
|
exit_code = $?.respond_to?(:exitstatus) ? $?.exitstatus : 1
|
|
72
|
-
abort("Command failed: #{cmd} (exit #{exit_code})")
|
|
73
|
+
Kettle::Dev::ExitAdapter.abort("Command failed: #{cmd} (exit #{exit_code})")
|
|
73
74
|
end
|
|
74
75
|
return
|
|
75
76
|
end
|
|
@@ -90,7 +91,7 @@ module Kettle
|
|
|
90
91
|
tail = stderr_str.lines.last(20).join
|
|
91
92
|
diag = "\n--- STDERR (last 20 lines) ---\n#{tail}".rstrip
|
|
92
93
|
end
|
|
93
|
-
abort("Command failed: #{cmd} (exit #{exit_code})#{diag}")
|
|
94
|
+
Kettle::Dev::ExitAdapter.abort("Command failed: #{cmd} (exit #{exit_code})#{diag}")
|
|
94
95
|
end
|
|
95
96
|
end
|
|
96
97
|
|
|
@@ -586,15 +587,26 @@ module Kettle
|
|
|
586
587
|
def reset_release_lockfiles!(stage:)
|
|
587
588
|
return if @release_lockfiles_reset_for_release_tasks && stage == "before release task bundle installs"
|
|
588
589
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
590
|
+
attempts = release_lockfile_reset_attempts(stage)
|
|
591
|
+
attempts.times do |index|
|
|
592
|
+
attempt = index + 1
|
|
593
|
+
puts "Resetting release lockfiles with local path dependencies disabled #{stage} (attempt #{attempt}/#{attempts})..."
|
|
594
|
+
begin
|
|
595
|
+
lockfile_reset.reset(Kettle::Dev::LockfileReset::RELEASE_LOCKFILES_TARGET)
|
|
596
|
+
break
|
|
597
|
+
rescue Kettle::Dev::Error => error
|
|
598
|
+
raise unless error.message.start_with?("Reset #{Kettle::Dev::LockfileReset::RELEASE_LOCKFILES_TARGET} failed validation:")
|
|
599
|
+
|
|
600
|
+
# Keep release-facing failures shaped like the lockfile validation
|
|
601
|
+
# guard, even when the shared reset helper is the component that
|
|
602
|
+
# detects the unrepaired lockfile.
|
|
603
|
+
break
|
|
604
|
+
rescue => error
|
|
605
|
+
raise unless retryable_release_lockfile_reset_error?(error) && attempt < attempts
|
|
594
606
|
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
607
|
+
puts "Release lockfile reset could not resolve a gem from #{RELEASE_VALIDATION_SOURCE}; waiting before retry #{attempt + 1}/#{attempts}."
|
|
608
|
+
sleep(release_availability_probe_interval)
|
|
609
|
+
end
|
|
598
610
|
end
|
|
599
611
|
|
|
600
612
|
diagnostics = release_lockfile_paths.flat_map { |path| release_lockfile_diagnostics(path) }
|
|
@@ -604,6 +616,17 @@ module Kettle
|
|
|
604
616
|
@release_lockfiles_reset_for_release_tasks = true if stage == "before release task bundle installs"
|
|
605
617
|
end
|
|
606
618
|
|
|
619
|
+
def release_lockfile_reset_attempts(stage)
|
|
620
|
+
(stage == "before release task bundle installs") ? release_availability_probe_attempts : 1
|
|
621
|
+
end
|
|
622
|
+
|
|
623
|
+
def retryable_release_lockfile_reset_error?(error)
|
|
624
|
+
message = error.message.to_s
|
|
625
|
+
message.include?("Bundler::GemNotFound") ||
|
|
626
|
+
message.include?("Could not find gem") ||
|
|
627
|
+
message.include?("can no longer be found in that source")
|
|
628
|
+
end
|
|
629
|
+
|
|
607
630
|
def validate_release_lockfiles!(stage:)
|
|
608
631
|
diagnostics = release_lockfile_paths.flat_map { |path| release_lockfile_diagnostics(path) }
|
|
609
632
|
return if diagnostics.empty?
|
|
@@ -722,7 +745,13 @@ module Kettle
|
|
|
722
745
|
end
|
|
723
746
|
|
|
724
747
|
def lockfile_reset
|
|
725
|
-
@lockfile_reset ||= Kettle::Dev::LockfileReset.new(root: @root, command_runner: method(:
|
|
748
|
+
@lockfile_reset ||= Kettle::Dev::LockfileReset.new(root: @root, command_runner: method(:run_lockfile_reset_command!))
|
|
749
|
+
end
|
|
750
|
+
|
|
751
|
+
def run_lockfile_reset_command!(command)
|
|
752
|
+
Kettle::Dev::ExitAdapter.abort_as_error do
|
|
753
|
+
run_cmd!(command)
|
|
754
|
+
end
|
|
726
755
|
end
|
|
727
756
|
|
|
728
757
|
def run_changelog!
|
|
@@ -1390,39 +1419,11 @@ module Kettle
|
|
|
1390
1419
|
end
|
|
1391
1420
|
|
|
1392
1421
|
def release_availability_probe_script(candidate)
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
require "bundler"
|
|
1400
|
-
require "pathname"
|
|
1401
|
-
|
|
1402
|
-
Bundler.reset!
|
|
1403
|
-
Bundler.unbundle_env!
|
|
1404
|
-
Bundler.instance_variable_set(:@bundle_path, Pathname.new(Gem.dir))
|
|
1405
|
-
Bundler::SharedHelpers.set_env("BUNDLE_GEMFILE", "Gemfile")
|
|
1406
|
-
Bundler::SharedHelpers.set_env("BUNDLE_LOCKFILE", "Gemfile.lock")
|
|
1407
|
-
|
|
1408
|
-
builder = Bundler::Dsl.new
|
|
1409
|
-
builder.source(#{RELEASE_VALIDATION_SOURCE.dump})
|
|
1410
|
-
builder.gem(gem_name, "= \#{version}", require: false)
|
|
1411
|
-
definition = builder.to_definition(nil, true)
|
|
1412
|
-
definition.validate_runtime!
|
|
1413
|
-
|
|
1414
|
-
Bundler.settings.temporary(deployment: false, frozen: false, inline: true, no_install: false) do
|
|
1415
|
-
installer = Bundler::Installer.install(Bundler.root, definition, system: true)
|
|
1416
|
-
installer.post_install_messages.each do |name, message|
|
|
1417
|
-
warn("Post-install message from \#{name}:\\n\#{message}")
|
|
1418
|
-
end
|
|
1419
|
-
end
|
|
1420
|
-
|
|
1421
|
-
spec = definition.specs.find { |candidate| candidate.name == gem_name }
|
|
1422
|
-
abort("resolved no \#{gem_name} spec") unless spec
|
|
1423
|
-
abort("resolved \#{gem_name} \#{spec.version}, expected \#{version}") unless spec.version.to_s == version
|
|
1424
|
-
puts "Validated \#{gem_name} \#{version} from #{RELEASE_VALIDATION_SOURCE}"
|
|
1425
|
-
RUBY
|
|
1422
|
+
GemSourceProbe.bundler_inline_script(
|
|
1423
|
+
name: candidate.gem_name,
|
|
1424
|
+
version: candidate.version,
|
|
1425
|
+
source_url: RELEASE_VALIDATION_SOURCE
|
|
1426
|
+
)
|
|
1426
1427
|
end
|
|
1427
1428
|
|
|
1428
1429
|
def detect_version
|
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 = "2.5.
|
|
8
|
+
VERSION = "2.5.5"
|
|
9
9
|
end
|
|
10
10
|
# Current gem version exposed at the traditional constant location.
|
|
11
11
|
VERSION = Version::VERSION # Traditional Constant Location
|
data/lib/kettle/dev.rb
CHANGED
|
@@ -29,6 +29,7 @@ module Kettle
|
|
|
29
29
|
autoload :ChangelogCLI, "kettle/dev/changelog_cli"
|
|
30
30
|
autoload :ChangelogEntryAdder, "kettle/dev/changelog_entry_adder"
|
|
31
31
|
autoload :BumpCLI, "kettle/dev/bump_cli"
|
|
32
|
+
autoload :BundlerEnvGuard, "kettle/dev/bundler_env_guard"
|
|
32
33
|
autoload :CIHelpers, "kettle/dev/ci_helpers"
|
|
33
34
|
autoload :CIMonitor, "kettle/dev/ci_monitor"
|
|
34
35
|
autoload :CommitMsg, "kettle/dev/commit_msg"
|
|
@@ -36,6 +37,7 @@ module Kettle
|
|
|
36
37
|
autoload :ExitAdapter, "kettle/dev/exit_adapter"
|
|
37
38
|
autoload :RubyGemsVersions, "kettle/dev/ruby_gems_versions"
|
|
38
39
|
autoload :GemSpecReader, "kettle/dev/gem_spec_reader"
|
|
40
|
+
autoload :GemSourceProbe, "kettle/dev/gem_source_probe"
|
|
39
41
|
autoload :GitAdapter, "kettle/dev/git_adapter"
|
|
40
42
|
autoload :GitCommitFooter, "kettle/dev/git_commit_footer"
|
|
41
43
|
autoload :GhaShaPinsCLI, "kettle/dev/gha_sha_pins_cli"
|
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: 2.5.
|
|
4
|
+
version: 2.5.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -296,7 +296,7 @@ dependencies:
|
|
|
296
296
|
version: '2.0'
|
|
297
297
|
- - ">="
|
|
298
298
|
- !ruby/object:Gem::Version
|
|
299
|
-
version: 2.0.
|
|
299
|
+
version: 2.0.7
|
|
300
300
|
type: :development
|
|
301
301
|
prerelease: false
|
|
302
302
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -306,7 +306,7 @@ dependencies:
|
|
|
306
306
|
version: '2.0'
|
|
307
307
|
- - ">="
|
|
308
308
|
- !ruby/object:Gem::Version
|
|
309
|
-
version: 2.0.
|
|
309
|
+
version: 2.0.7
|
|
310
310
|
description: "\U0001F372 Kettle::Dev is a meta tool from kettle-dev to streamline
|
|
311
311
|
development and testing. Acts as a shim dependency, pulling in many other dependencies,
|
|
312
312
|
to give you OOTB productivity with a RubyGem, or Ruby app project. Configures a
|
|
@@ -350,6 +350,7 @@ files:
|
|
|
350
350
|
- lib/kettle-dev.rb
|
|
351
351
|
- lib/kettle/dev.rb
|
|
352
352
|
- lib/kettle/dev/bump_cli.rb
|
|
353
|
+
- lib/kettle/dev/bundler_env_guard.rb
|
|
353
354
|
- lib/kettle/dev/cache_progress.rb
|
|
354
355
|
- lib/kettle/dev/changelog_cli.rb
|
|
355
356
|
- lib/kettle/dev/changelog_entry_adder.rb
|
|
@@ -359,6 +360,7 @@ files:
|
|
|
359
360
|
- lib/kettle/dev/dvcs_cli.rb
|
|
360
361
|
- lib/kettle/dev/executable_version.rb
|
|
361
362
|
- lib/kettle/dev/exit_adapter.rb
|
|
363
|
+
- lib/kettle/dev/gem_source_probe.rb
|
|
362
364
|
- lib/kettle/dev/gem_spec_reader.rb
|
|
363
365
|
- lib/kettle/dev/gha_sha_pins_cli.rb
|
|
364
366
|
- lib/kettle/dev/git_adapter.rb
|
|
@@ -395,10 +397,10 @@ licenses:
|
|
|
395
397
|
- AGPL-3.0-only
|
|
396
398
|
metadata:
|
|
397
399
|
homepage_uri: https://kettle-dev.galtzo.com
|
|
398
|
-
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.5.
|
|
399
|
-
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.5.
|
|
400
|
+
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.5.5
|
|
401
|
+
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.5.5/CHANGELOG.md
|
|
400
402
|
bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
|
|
401
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.5.
|
|
403
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.5.5
|
|
402
404
|
funding_uri: https://github.com/sponsors/pboling
|
|
403
405
|
wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
|
|
404
406
|
news_uri: https://www.railsbling.com/tags/kettle-dev
|
metadata.gz.sig
CHANGED
|
Binary file
|