kettle-dev 2.4.1 → 2.4.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 +17 -1
- data/README.md +1 -1
- data/lib/kettle/dev/release_cli.rb +137 -4
- data/lib/kettle/dev/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +4 -4
- 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: a251345bb56780a5c5b9efcfb53d394ca469581b5798f10839ac8ed5b4cae682
|
|
4
|
+
data.tar.gz: 4a81578792afe11fd09299ea7d1836d66f0cd8c76af00235491b8234fcec1553
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0cfa39888af23e14856d9874d965248c8d68a83b88c42bd3cc722b1a84fe8564b3c1381aa714aaebe0df531822365b70e4f2e7e2eff913f5e781e201e5f49b13
|
|
7
|
+
data.tar.gz: aefab75e861bc0c2132385b4e7411904b01cb6562c82d3485cdbdbb27d407004450b8e0a7030f33abf869bc73df4074f2cbdd1c3ef7abcfb21e9222b5c1c7f9e
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,20 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [2.4.2] - 2026-07-24
|
|
34
|
+
|
|
35
|
+
- TAG: [v2.4.2][2.4.2t]
|
|
36
|
+
- COVERAGE: 92.36% -- 3991/4321 lines in 38 files
|
|
37
|
+
- BRANCH COVERAGE: 76.06% -- 1563/2055 branches in 38 files
|
|
38
|
+
- 59.00% documented
|
|
39
|
+
|
|
40
|
+
### Fixed
|
|
41
|
+
|
|
42
|
+
- `kettle-release` now validates published gem availability with an isolated
|
|
43
|
+
Bundler probe against gem.coop before continuing past the publish step, and
|
|
44
|
+
uninstalls newly introduced local candidate gems when the release did not
|
|
45
|
+
happen or cannot be validated.
|
|
46
|
+
|
|
33
47
|
## [2.4.1] - 2026-07-24
|
|
34
48
|
|
|
35
49
|
- TAG: [v2.4.1][2.4.1t]
|
|
@@ -2660,7 +2674,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
2660
2674
|
- Selecting will run the selected workflow via `act`
|
|
2661
2675
|
- This may move to its own gem in the future.
|
|
2662
2676
|
|
|
2663
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.4.
|
|
2677
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.4.2...HEAD
|
|
2678
|
+
[2.4.2]: https://github.com/kettle-dev/kettle-dev/compare/v2.4.1...v2.4.2
|
|
2679
|
+
[2.4.2t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.4.2
|
|
2664
2680
|
[2.4.1]: https://github.com/kettle-dev/kettle-dev/compare/v2.4.0...v2.4.1
|
|
2665
2681
|
[2.4.1t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.4.1
|
|
2666
2682
|
[2.4.0]: https://github.com/kettle-dev/kettle-dev/compare/v2.3.11...v2.4.0
|
data/README.md
CHANGED
|
@@ -891,7 +891,7 @@ Thanks for RTFM. ☺️
|
|
|
891
891
|
[📌gitmoji]: https://gitmoji.dev
|
|
892
892
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
893
893
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
894
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-4.
|
|
894
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-4.321-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
895
895
|
[🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
|
|
896
896
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
897
897
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
|
@@ -40,6 +40,8 @@ module Kettle
|
|
|
40
40
|
"BUNDLE_SUPPRESS_INSTALL_USING_MESSAGES" => "true"
|
|
41
41
|
}.freeze
|
|
42
42
|
DEBUG_TRUE_VALUES = %w[1 true yes on].freeze
|
|
43
|
+
RELEASE_VALIDATION_SOURCE = "https://gem.coop"
|
|
44
|
+
|
|
43
45
|
class << self
|
|
44
46
|
def run_cmd!(cmd)
|
|
45
47
|
# For Bundler-invoked build/release, explicitly prefix SKIP_GEM_SIGNING so
|
|
@@ -121,6 +123,7 @@ module Kettle
|
|
|
121
123
|
@skip_bundle_audit = truthy_value?(skip_bundle_audit) || truthy_value?(ENV["KETTLE_DEV_SKIP_BUNDLE_AUDIT"])
|
|
122
124
|
@version_override = Kettle::Dev::Versioning.normalize_explicit_version(version)
|
|
123
125
|
@appraisal_task = normalize_appraisal_task(appraisal_task || ENV["KETTLE_RELEASE_APPRAISAL_TASK"])
|
|
126
|
+
@release_candidate = nil
|
|
124
127
|
end
|
|
125
128
|
|
|
126
129
|
def run
|
|
@@ -346,13 +349,18 @@ module Kettle
|
|
|
346
349
|
|
|
347
350
|
# 15. release and tag
|
|
348
351
|
if run_step?(15)
|
|
352
|
+
version ||= detect_version
|
|
353
|
+
gem_name = detect_gem_name
|
|
354
|
+
@release_candidate = build_release_candidate(gem_name, version)
|
|
349
355
|
if local_ci?
|
|
350
|
-
version
|
|
351
|
-
release_gem_and_tag_locally!(version)
|
|
356
|
+
with_unpublished_candidate_cleanup { release_gem_and_tag_locally!(version) }
|
|
352
357
|
else
|
|
353
358
|
puts "Running release (you may be prompted for signing key password and RubyGems MFA OTP)..."
|
|
354
|
-
|
|
355
|
-
|
|
359
|
+
with_unpublished_candidate_cleanup do
|
|
360
|
+
run_cmd!("bundle exec rake release")
|
|
361
|
+
confirm_release_candidate_available!(@release_candidate)
|
|
362
|
+
end
|
|
363
|
+
mark_gem_coop_release_cache_bust(version)
|
|
356
364
|
end
|
|
357
365
|
end
|
|
358
366
|
|
|
@@ -1144,9 +1152,123 @@ module Kettle
|
|
|
1144
1152
|
|
|
1145
1153
|
puts "Publishing #{File.basename(gem_path)} to RubyGems without pushing git refs..."
|
|
1146
1154
|
run_cmd!("gem push #{Shellwords.escape(gem_path)}")
|
|
1155
|
+
confirm_release_candidate_available!(@release_candidate || build_release_candidate(gem_name_from_gem_path(gem_path, version), version))
|
|
1147
1156
|
mark_gem_coop_release_cache_bust(version, gem_name: gem_name_from_gem_path(gem_path, version))
|
|
1148
1157
|
end
|
|
1149
1158
|
|
|
1159
|
+
def build_release_candidate(gem_name, version)
|
|
1160
|
+
ReleaseCandidate.new(
|
|
1161
|
+
gem_name: gem_name.to_s,
|
|
1162
|
+
version: version.to_s,
|
|
1163
|
+
installed_before: gem_version_installed?(gem_name, version),
|
|
1164
|
+
published: false
|
|
1165
|
+
)
|
|
1166
|
+
end
|
|
1167
|
+
|
|
1168
|
+
def with_unpublished_candidate_cleanup
|
|
1169
|
+
yield
|
|
1170
|
+
rescue SystemExit, StandardError
|
|
1171
|
+
cleanup_unpublished_release_candidate(@release_candidate)
|
|
1172
|
+
raise
|
|
1173
|
+
end
|
|
1174
|
+
|
|
1175
|
+
def cleanup_unpublished_release_candidate(candidate)
|
|
1176
|
+
return unless candidate
|
|
1177
|
+
return if candidate.published
|
|
1178
|
+
return if candidate.installed_before
|
|
1179
|
+
return unless gem_version_installed?(candidate.gem_name, candidate.version)
|
|
1180
|
+
|
|
1181
|
+
warn(
|
|
1182
|
+
"Release of #{candidate.gem_name} #{candidate.version} was not validated; " \
|
|
1183
|
+
"uninstalling the local candidate gem so future bundle updates cannot resolve an unreleased version."
|
|
1184
|
+
)
|
|
1185
|
+
uninstall_release_candidate(candidate)
|
|
1186
|
+
end
|
|
1187
|
+
|
|
1188
|
+
def uninstall_release_candidate(candidate)
|
|
1189
|
+
run_cmd!(
|
|
1190
|
+
"gem uninstall #{Shellwords.escape(candidate.gem_name)} " \
|
|
1191
|
+
"-v #{Shellwords.escape(candidate.version)} -x -I --ignore-dependencies"
|
|
1192
|
+
)
|
|
1193
|
+
rescue SystemExit, StandardError => error
|
|
1194
|
+
warn("Could not uninstall local candidate #{candidate.gem_name} #{candidate.version}: #{error.message}")
|
|
1195
|
+
warn("Manual cleanup: gem uninstall #{candidate.gem_name} -v #{candidate.version} -x -I --ignore-dependencies")
|
|
1196
|
+
end
|
|
1197
|
+
|
|
1198
|
+
def gem_version_installed?(gem_name, version)
|
|
1199
|
+
Gem::Specification.reset
|
|
1200
|
+
Gem::Specification.find_all_by_name(gem_name.to_s, "= #{version}").any?
|
|
1201
|
+
rescue Gem::LoadError
|
|
1202
|
+
false
|
|
1203
|
+
end
|
|
1204
|
+
|
|
1205
|
+
def confirm_release_candidate_available!(candidate)
|
|
1206
|
+
run_release_availability_probe(candidate)
|
|
1207
|
+
candidate.published = true
|
|
1208
|
+
true
|
|
1209
|
+
rescue SystemExit
|
|
1210
|
+
raise
|
|
1211
|
+
rescue => error
|
|
1212
|
+
abort(<<~MSG)
|
|
1213
|
+
Published gem availability could not be validated for #{candidate.gem_name} #{candidate.version}: #{error.class}: #{error.message}
|
|
1214
|
+
kettle-release will clean up any local candidate install that was introduced by this failed release attempt.
|
|
1215
|
+
If the push actually succeeded, resolve the registry/checksum state manually before resuming.
|
|
1216
|
+
MSG
|
|
1217
|
+
end
|
|
1218
|
+
|
|
1219
|
+
def run_release_availability_probe(candidate)
|
|
1220
|
+
script_path = write_release_availability_probe(candidate)
|
|
1221
|
+
stdout_str = nil
|
|
1222
|
+
stderr_str = nil
|
|
1223
|
+
status = nil
|
|
1224
|
+
with_unbundled_release_probe_env do
|
|
1225
|
+
stdout_str, stderr_str, status = Open3.capture3(self.class.send(:command_env), Gem.ruby, script_path)
|
|
1226
|
+
end
|
|
1227
|
+
$stdout.print(stdout_str) unless stdout_str.to_s.empty?
|
|
1228
|
+
return true if status.success?
|
|
1229
|
+
|
|
1230
|
+
diag = stderr_str.to_s.empty? ? "" : "\n--- STDERR ---\n#{stderr_str}".rstrip
|
|
1231
|
+
abort("Published gem availability probe failed for #{candidate.gem_name} #{candidate.version} (exit #{status.exitstatus})#{diag}")
|
|
1232
|
+
ensure
|
|
1233
|
+
FileUtils.rm_f(script_path) if script_path
|
|
1234
|
+
end
|
|
1235
|
+
|
|
1236
|
+
def with_unbundled_release_probe_env(&block)
|
|
1237
|
+
if defined?(Bundler)
|
|
1238
|
+
Bundler.with_unbundled_env(&block)
|
|
1239
|
+
else
|
|
1240
|
+
yield
|
|
1241
|
+
end
|
|
1242
|
+
end
|
|
1243
|
+
|
|
1244
|
+
def write_release_availability_probe(candidate)
|
|
1245
|
+
dir = File.join(@root, "tmp", "kettle-release")
|
|
1246
|
+
FileUtils.mkdir_p(dir)
|
|
1247
|
+
path = File.join(dir, "validate-#{candidate.gem_name}-#{candidate.version}-#{$$}.rb")
|
|
1248
|
+
File.write(path, release_availability_probe_script(candidate))
|
|
1249
|
+
path
|
|
1250
|
+
end
|
|
1251
|
+
|
|
1252
|
+
def release_availability_probe_script(candidate)
|
|
1253
|
+
<<~RUBY
|
|
1254
|
+
# frozen_string_literal: true
|
|
1255
|
+
|
|
1256
|
+
gem_name = #{candidate.gem_name.dump}
|
|
1257
|
+
version = #{candidate.version.dump}
|
|
1258
|
+
|
|
1259
|
+
require "bundler/inline"
|
|
1260
|
+
|
|
1261
|
+
gemfile(true) do
|
|
1262
|
+
source #{RELEASE_VALIDATION_SOURCE.dump}
|
|
1263
|
+
gem gem_name, "= \#{version}"
|
|
1264
|
+
end
|
|
1265
|
+
|
|
1266
|
+
spec = Gem.loaded_specs.fetch(gem_name)
|
|
1267
|
+
abort("loaded \#{gem_name} \#{spec.version}, expected \#{version}") unless spec.version.to_s == version
|
|
1268
|
+
puts "Validated \#{gem_name} \#{version} from #{RELEASE_VALIDATION_SOURCE}"
|
|
1269
|
+
RUBY
|
|
1270
|
+
end
|
|
1271
|
+
|
|
1150
1272
|
def detect_version
|
|
1151
1273
|
Kettle::Dev::Versioning.detect_version(@root, override: @version_override)
|
|
1152
1274
|
end
|
|
@@ -1709,3 +1831,14 @@ module Kettle
|
|
|
1709
1831
|
end
|
|
1710
1832
|
end
|
|
1711
1833
|
end
|
|
1834
|
+
|
|
1835
|
+
class Kettle::Dev::ReleaseCLI::ReleaseCandidate
|
|
1836
|
+
attr_accessor :gem_name, :version, :installed_before, :published
|
|
1837
|
+
|
|
1838
|
+
def initialize(gem_name:, version:, installed_before:, published:)
|
|
1839
|
+
@gem_name = gem_name
|
|
1840
|
+
@version = version
|
|
1841
|
+
@installed_before = installed_before
|
|
1842
|
+
@published = published
|
|
1843
|
+
end
|
|
1844
|
+
end
|
data/lib/kettle/dev/version.rb
CHANGED
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.4.
|
|
4
|
+
version: 2.4.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -349,10 +349,10 @@ licenses:
|
|
|
349
349
|
- AGPL-3.0-only
|
|
350
350
|
metadata:
|
|
351
351
|
homepage_uri: https://kettle-dev.galtzo.com
|
|
352
|
-
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.4.
|
|
353
|
-
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.4.
|
|
352
|
+
source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.4.2
|
|
353
|
+
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.4.2/CHANGELOG.md
|
|
354
354
|
bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
|
|
355
|
-
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.4.
|
|
355
|
+
documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.4.2
|
|
356
356
|
funding_uri: https://github.com/sponsors/pboling
|
|
357
357
|
wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
|
|
358
358
|
news_uri: https://www.railsbling.com/tags/kettle-dev
|
metadata.gz.sig
CHANGED
|
Binary file
|