kettle-dev 3.0.26 → 3.0.27
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 +18 -1
- data/README.md +1 -1
- data/exe/kettle-gh-release +5 -14
- data/lib/kettle/dev/release_cli.rb +72 -5
- data/lib/kettle/dev/version.rb +1 -1
- data.tar.gz.sig +0 -0
- metadata +6 -6
- metadata.gz.sig +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f2c4229bf9687d5eeb37b3969ae097bd1826819756082e26053970f9c953048f
|
|
4
|
+
data.tar.gz: 6eaf217455b0f4215bb3c4699e0a5651d1367524208567121ea869a482cf9ca9
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 21ba6652f5ed37d6b67674b7869604c4700a94b8618185c8891e652271de5c71b85ea9eea576b5936ec1c43715c4a95f18ef9c117b3f2b74fac07546ad1d3fed
|
|
7
|
+
data.tar.gz: dc321c0c5531ff7b006bcbb83f3dee87a693b70b000619e4907e7e037fd597791446b1e75907a2895cc6135f0c25af62caaf4e782baa9ef4f089dca8ac504255
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data/CHANGELOG.md
CHANGED
|
@@ -30,6 +30,21 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
30
30
|
|
|
31
31
|
### Security
|
|
32
32
|
|
|
33
|
+
## [3.0.27] - 2026-08-31
|
|
34
|
+
|
|
35
|
+
- TAG: [v3.0.27][3.0.27t]
|
|
36
|
+
- COVERAGE: 91.68% -- 5998/6542 lines in 47 files
|
|
37
|
+
- BRANCH COVERAGE: 76.20% -- 2296/3013 branches in 47 files
|
|
38
|
+
- 50.24% documented
|
|
39
|
+
|
|
40
|
+
### Added
|
|
41
|
+
|
|
42
|
+
- Emit GitHub Release creation and asset-upload lifecycle events, including retry attempts.
|
|
43
|
+
|
|
44
|
+
### Fixed
|
|
45
|
+
|
|
46
|
+
- Retry transient GitHub Release asset uploads and report every failed asset.
|
|
47
|
+
|
|
33
48
|
## [3.0.26] - 2026-08-31
|
|
34
49
|
|
|
35
50
|
- TAG: [v3.0.26][3.0.26t]
|
|
@@ -3747,7 +3762,9 @@ Please file a bug if you notice a violation of semantic versioning.
|
|
|
3747
3762
|
- Selecting will run the selected workflow via `act`
|
|
3748
3763
|
- This may move to its own gem in the future.
|
|
3749
3764
|
|
|
3750
|
-
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.
|
|
3765
|
+
[Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.27...HEAD
|
|
3766
|
+
[3.0.27]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.26...v3.0.27
|
|
3767
|
+
[3.0.27t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.27
|
|
3751
3768
|
[3.0.26]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.25...v3.0.26
|
|
3752
3769
|
[3.0.26t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v3.0.26
|
|
3753
3770
|
[3.0.25]: https://github.com/kettle-dev/kettle-dev/compare/v3.0.24...v3.0.25
|
data/README.md
CHANGED
|
@@ -1066,7 +1066,7 @@ Thanks for RTFM. ☺️
|
|
|
1066
1066
|
[📌gitmoji]: https://gitmoji.dev
|
|
1067
1067
|
[📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
|
|
1068
1068
|
[🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
|
|
1069
|
-
[🧮kloc-img]: https://img.shields.io/badge/KLOC-6.
|
|
1069
|
+
[🧮kloc-img]: https://img.shields.io/badge/KLOC-6.542-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
|
|
1070
1070
|
[🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
|
|
1071
1071
|
[🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
|
|
1072
1072
|
[📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
|
data/exe/kettle-gh-release
CHANGED
|
@@ -26,6 +26,7 @@ $LOAD_PATH.unshift(repo_lib) if File.directory?(repo_lib) && !$LOAD_PATH.include
|
|
|
26
26
|
|
|
27
27
|
begin
|
|
28
28
|
require "kettle/dev"
|
|
29
|
+
require "kettle/ndjson"
|
|
29
30
|
require "kettle/dev/executable_version"
|
|
30
31
|
Kettle::Dev::ExecutableVersion.print_and_exit!(script_basename, ARGV)
|
|
31
32
|
Kettle::Dev::ExecutableVersion.print_header(script_basename)
|
|
@@ -52,7 +53,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
|
|
|
52
53
|
version=<VERSION> # Backward-compatible explicit version form
|
|
53
54
|
--check # Verify RubyGems, remote tag, changelog, and token without creating a release
|
|
54
55
|
--update # Update an existing GitHub Release title/body from CHANGELOG.md
|
|
55
|
-
--events # Emit
|
|
56
|
+
--events # Emit GitHub Release lifecycle and asset NDJSON events
|
|
56
57
|
--allow-unpublished # Skip the RubyGems publication requirement (for intentionally non-RubyGems projects)
|
|
57
58
|
--asset PATH # Attach an artifact to the GitHub release (repeatable)
|
|
58
59
|
|
|
@@ -106,7 +107,8 @@ if !explicit_version.nil? && explicit_version.empty?
|
|
|
106
107
|
end
|
|
107
108
|
|
|
108
109
|
begin
|
|
109
|
-
|
|
110
|
+
event_stream = events ? Kettle::Ndjson.event_stream($stdout, types: "github_release") : nil
|
|
111
|
+
cli = Kettle::Dev::ReleaseCLI.new(start_step: 18, event_stream: event_stream)
|
|
110
112
|
version = explicit_version || cli.send(:detect_version)
|
|
111
113
|
result = cli.send(:github_release_backfill_check, version, require_rubygems: !allow_unpublished)
|
|
112
114
|
|
|
@@ -135,22 +137,11 @@ begin
|
|
|
135
137
|
exit 1 unless result.fetch("ok")
|
|
136
138
|
exit 0 if check_only
|
|
137
139
|
|
|
138
|
-
created,
|
|
140
|
+
created, _message = if update_only
|
|
139
141
|
cli.send(:maybe_update_github_release!, version)
|
|
140
142
|
else
|
|
141
143
|
cli.send(:maybe_create_github_release!, version, assets: assets)
|
|
142
144
|
end
|
|
143
|
-
if events
|
|
144
|
-
puts JSON.generate(
|
|
145
|
-
event_version: 1,
|
|
146
|
-
type: "github_release",
|
|
147
|
-
action: update_only ? "update" : "create",
|
|
148
|
-
status: created ? "ok" : "failed",
|
|
149
|
-
version: result.fetch("version"),
|
|
150
|
-
tag: result.fetch("tag"),
|
|
151
|
-
result: message
|
|
152
|
-
)
|
|
153
|
-
end
|
|
154
145
|
exit(created ? 0 : 1)
|
|
155
146
|
rescue LoadError => e
|
|
156
147
|
warn("#{script_basename}: could not load dependency: #{e.class}: #{e.message}")
|
|
@@ -7,6 +7,7 @@ require "shellwords"
|
|
|
7
7
|
require "time"
|
|
8
8
|
require "fileutils"
|
|
9
9
|
require "net/http"
|
|
10
|
+
require "openssl"
|
|
10
11
|
require "json"
|
|
11
12
|
require "uri"
|
|
12
13
|
require "yaml"
|
|
@@ -27,6 +28,8 @@ module Kettle
|
|
|
27
28
|
class ReleaseCLI
|
|
28
29
|
RUBYGEMS_INVALID_OTP = /Your OTP code is incorrect\. Please check it and retry\./.freeze
|
|
29
30
|
OTP_RETRY_DELAY_SECONDS = 2
|
|
31
|
+
GITHUB_RELEASE_ASSET_UPLOAD_ATTEMPTS = 3
|
|
32
|
+
GITHUB_RELEASE_ASSET_UPLOAD_RETRY_DELAY_SECONDS = 1
|
|
30
33
|
QUIET_ENV = {
|
|
31
34
|
"KETTLE_JEM_QUIET" => "true",
|
|
32
35
|
"KETTLE_JEM_DEBUG" => "false",
|
|
@@ -2880,7 +2883,9 @@ module Kettle
|
|
|
2880
2883
|
|
|
2881
2884
|
tag = "v#{version}"
|
|
2882
2885
|
puts "Creating GitHub release #{owner}/#{repo} #{tag}..."
|
|
2886
|
+
emit_github_release_event(action: "create", status: "started", tag: tag, assets: Array(assets).length)
|
|
2883
2887
|
ok, msg = github_create_release(owner: owner, repo: repo, token: token, tag: tag, title: tag, body: body, assets: assets)
|
|
2888
|
+
emit_github_release_event(action: "create", status: ok ? "ok" : "failed", tag: tag, assets: Array(assets).length, reason: msg)
|
|
2884
2889
|
if ok
|
|
2885
2890
|
puts "GitHub release created for #{tag}."
|
|
2886
2891
|
else
|
|
@@ -3063,8 +3068,7 @@ module Kettle
|
|
|
3063
3068
|
|
|
3064
3069
|
release = JSON.parse(res.body)
|
|
3065
3070
|
asset_messages = Array(assets).map { |asset| github_upload_release_asset(release.fetch("id"), owner: owner, repo: repo, token: token, path: asset) }
|
|
3066
|
-
|
|
3067
|
-
failed_asset || [true, "created with #{asset_messages.length} assets"]
|
|
3071
|
+
github_release_asset_result(asset_messages, "created")
|
|
3068
3072
|
else
|
|
3069
3073
|
if res.code.to_s == "422" && res.body.to_s.include?("already_exists")
|
|
3070
3074
|
return [true, "already exists"] if Array(assets).empty?
|
|
@@ -3107,9 +3111,15 @@ module Kettle
|
|
|
3107
3111
|
asset_messages = missing_assets.map do |asset|
|
|
3108
3112
|
github_upload_release_asset(release.fetch("id"), owner: owner, repo: repo, token: token, path: asset)
|
|
3109
3113
|
end
|
|
3110
|
-
|
|
3114
|
+
github_release_asset_result(asset_messages, "updated existing release")
|
|
3115
|
+
end
|
|
3116
|
+
|
|
3117
|
+
def github_release_asset_result(asset_messages, success_prefix)
|
|
3118
|
+
failures = asset_messages.reject(&:first).map(&:last)
|
|
3119
|
+
return [false, failures.join("; ")] unless failures.empty?
|
|
3120
|
+
|
|
3111
3121
|
asset_noun = asset_messages.one? ? "asset" : "assets"
|
|
3112
|
-
|
|
3122
|
+
[true, "#{success_prefix} with #{asset_messages.length} #{asset_noun} uploaded"]
|
|
3113
3123
|
end
|
|
3114
3124
|
|
|
3115
3125
|
def github_release_for_tag(owner:, repo:, token:, tag:)
|
|
@@ -3130,6 +3140,42 @@ module Kettle
|
|
|
3130
3140
|
path = File.expand_path(path)
|
|
3131
3141
|
return [false, "asset does not exist: #{path}"] unless File.file?(path)
|
|
3132
3142
|
|
|
3143
|
+
attempts = GITHUB_RELEASE_ASSET_UPLOAD_ATTEMPTS
|
|
3144
|
+
attempts.times do |attempt|
|
|
3145
|
+
emit_github_release_event(
|
|
3146
|
+
action: "asset_upload",
|
|
3147
|
+
status: "started",
|
|
3148
|
+
asset: File.basename(path),
|
|
3149
|
+
attempt: attempt + 1,
|
|
3150
|
+
attempts: attempts
|
|
3151
|
+
)
|
|
3152
|
+
result = github_upload_release_asset_once(release_id, owner: owner, repo: repo, token: token, path: path)
|
|
3153
|
+
retrying = !result.first && retryable_github_release_asset_upload_result?(result.last) && attempt < attempts - 1
|
|
3154
|
+
status = if result.first
|
|
3155
|
+
"ok"
|
|
3156
|
+
elsif retrying
|
|
3157
|
+
"retrying"
|
|
3158
|
+
else
|
|
3159
|
+
"failed"
|
|
3160
|
+
end
|
|
3161
|
+
emit_github_release_event(
|
|
3162
|
+
action: "asset_upload",
|
|
3163
|
+
status: status,
|
|
3164
|
+
asset: File.basename(path),
|
|
3165
|
+
attempt: attempt + 1,
|
|
3166
|
+
attempts: attempts,
|
|
3167
|
+
reason: result.first ? nil : result.last
|
|
3168
|
+
)
|
|
3169
|
+
return result unless retrying
|
|
3170
|
+
|
|
3171
|
+
warn("GitHub release asset upload failed for #{File.basename(path)}; retrying #{attempt + 2}/#{attempts}.")
|
|
3172
|
+
sleep(GITHUB_RELEASE_ASSET_UPLOAD_RETRY_DELAY_SECONDS)
|
|
3173
|
+
end
|
|
3174
|
+
rescue => e
|
|
3175
|
+
[false, "asset #{File.basename(path)}: #{e.class}: #{e.message}"]
|
|
3176
|
+
end
|
|
3177
|
+
|
|
3178
|
+
def github_upload_release_asset_once(release_id, owner:, repo:, token:, path:)
|
|
3133
3179
|
uri = URI("https://uploads.github.com/repos/#{owner}/#{repo}/releases/#{release_id}/assets")
|
|
3134
3180
|
uri.query = URI.encode_www_form(name: File.basename(path))
|
|
3135
3181
|
req = Net::HTTP::Post.new(uri)
|
|
@@ -3142,10 +3188,31 @@ module Kettle
|
|
|
3142
3188
|
return [true, File.basename(path)] if res.is_a?(Net::HTTPSuccess) || res.is_a?(Net::HTTPCreated)
|
|
3143
3189
|
|
|
3144
3190
|
[false, "asset #{File.basename(path)}: HTTP #{res.code}: #{res.body}"]
|
|
3145
|
-
rescue => e
|
|
3191
|
+
rescue OpenSSL::SSL::SSLError, IOError, SystemCallError, Timeout::Error => e
|
|
3146
3192
|
[false, "asset #{File.basename(path)}: #{e.class}: #{e.message}"]
|
|
3147
3193
|
end
|
|
3148
3194
|
|
|
3195
|
+
def retryable_github_release_asset_upload_result?(message)
|
|
3196
|
+
message.match?(/(?:OpenSSL::SSL::SSLError|IOError|Errno::|(?:Net::)?(?:Open|Read)Timeout|HTTP (?:429|5\d\d))/)
|
|
3197
|
+
end
|
|
3198
|
+
|
|
3199
|
+
def emit_github_release_event(action:, status:, tag: nil, asset: nil, assets: nil, attempt: nil, attempts: nil, reason: nil)
|
|
3200
|
+
Kettle::Ndjson.emit_event(
|
|
3201
|
+
@event_recorder,
|
|
3202
|
+
"github_release",
|
|
3203
|
+
action: action,
|
|
3204
|
+
phase: "release",
|
|
3205
|
+
status: status,
|
|
3206
|
+
tag: tag,
|
|
3207
|
+
asset: asset,
|
|
3208
|
+
assets: assets,
|
|
3209
|
+
attempt: attempt,
|
|
3210
|
+
attempts: attempts,
|
|
3211
|
+
reason: reason,
|
|
3212
|
+
mark: release_progress_mark(status)
|
|
3213
|
+
)
|
|
3214
|
+
end
|
|
3215
|
+
|
|
3149
3216
|
def github_update_release(owner:, repo:, token:, tag:, title:, body:)
|
|
3150
3217
|
release, error = github_release_for_tag(owner: owner, repo: repo, token: token, tag: tag)
|
|
3151
3218
|
return [false, error] unless release
|
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.27"
|
|
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.27
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Peter H. Boling
|
|
@@ -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.15
|
|
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.15
|
|
94
94
|
- !ruby/object:Gem::Dependency
|
|
95
95
|
name: kettle-rb
|
|
96
96
|
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.27
|
|
404
|
+
changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v3.0.27/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.27
|
|
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
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
�n�v��zmbb��L@b}B^z-wW��ba*�s�ɰ�F<��hl4Uo��n���[�'�0!�����]�lMg�!�*�z�r�.��� �@;2����V�
|
|
2
|
+
c4Ȱ�ě9�_��
|