kettle-dev 2.3.8 → 2.3.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fb500cfcc82a5cb325eb83ae9a5464e8333cce1c3ec03814b597063d41ec0e8a
4
- data.tar.gz: 124a6c4ad4a3dd9172c131d6d5276a685d7e15f2be8f5fc51722c028fc83f136
3
+ metadata.gz: 846ffb7540c0c7d69659591baf978274184f722f726aacc6e4915c0f376dbeb4
4
+ data.tar.gz: '08818034dfa875f33cdc89579cf455a011ecebf25be759b31af8702458e8eb6b'
5
5
  SHA512:
6
- metadata.gz: 1dd9b51023413bc9301d87dfc989dcec0844190b0cccfa90d8344bcd428403c70837f3972fdedc0cf2b4dee103af88923cc41ec43f80a869098a8a20da8a579d
7
- data.tar.gz: 94084430abf75c714d2b5be26a25f1a9c1be691fc9c4f2fa760fc767e7ce1698e01ab71f5b978ec744f9981eeedc7b474a663b51504c6d842c0569ffe7e79cb0
6
+ metadata.gz: 0014c68a3e93d78a01c8b561956cbf474eaf25c6c8491b8ff1d229e7070eca06d3a3ed0282f739b1a3e4c38040f9bd8e5155e030a6baf1e7694a731a4bce5e2d
7
+ data.tar.gz: eeb028f65feddaac27a4f268a627d77fa686836bf368ca62c8b4b169acff3b43abf8aa432d96dc24341b4d27a61d74cd1197a529db1f2287c05661257f67880c
checksums.yaml.gz.sig CHANGED
Binary file
data/CHANGELOG.md CHANGED
@@ -30,6 +30,24 @@ Please file a bug if you notice a violation of semantic versioning.
30
30
 
31
31
  ### Security
32
32
 
33
+ ## [2.3.9] - 2026-07-21
34
+
35
+ - TAG: [v2.3.9][2.3.9t]
36
+ - COVERAGE: 92.06% -- 4443/4826 lines in 37 files
37
+ - BRANCH COVERAGE: 74.09% -- 1733/2339 branches in 37 files
38
+ - 54.64% documented
39
+
40
+ ### Fixed
41
+
42
+ - `kettle-release` now records a short-lived gem.coop release-state cache-bust
43
+ marker after publishing, and `kettle-changelog --release-state` uses it to
44
+ refresh just-published gem version lookups.
45
+
46
+ - `dep-heads.yml` now runs each engine directly from
47
+ `gemfiles/dep_heads.gemfile`, avoiding `Appraisal.root.gemfile` bootstrap
48
+ failures with RubyGems/Bundler and gem.coop before the dep-heads appraisal is
49
+ selected.
50
+
33
51
  ## [2.3.8] - 2026-07-21
34
52
 
35
53
  - TAG: [v2.3.8][2.3.8t]
@@ -2568,7 +2586,9 @@ Please file a bug if you notice a violation of semantic versioning.
2568
2586
  - Selecting will run the selected workflow via `act`
2569
2587
  - This may move to its own gem in the future.
2570
2588
 
2571
- [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.3.8...HEAD
2589
+ [Unreleased]: https://github.com/kettle-dev/kettle-dev/compare/v2.3.9...HEAD
2590
+ [2.3.9]: https://github.com/kettle-dev/kettle-dev/compare/v2.3.8...v2.3.9
2591
+ [2.3.9t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.3.9
2572
2592
  [2.3.8]: https://github.com/kettle-dev/kettle-dev/compare/v2.3.7...v2.3.8
2573
2593
  [2.3.8t]: https://github.com/kettle-dev/kettle-dev/releases/tag/v2.3.8
2574
2594
  [2.3.7]: https://github.com/kettle-dev/kettle-dev/compare/v2.3.6...v2.3.7
data/README.md CHANGED
@@ -889,7 +889,7 @@ Thanks for RTFM. ☺️
889
889
  [📌gitmoji]: https://gitmoji.dev
890
890
  [📌gitmoji-img]: https://img.shields.io/badge/gitmoji_commits-%20%F0%9F%98%9C%20%F0%9F%98%8D-34495e.svg?style=flat-square
891
891
  [🧮kloc]: https://www.youtube.com/watch?v=dQw4w9WgXcQ
892
- [🧮kloc-img]: https://img.shields.io/badge/KLOC-4.761-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
892
+ [🧮kloc-img]: https://img.shields.io/badge/KLOC-4.826-FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
893
893
  [🔐security]: https://github.com/kettle-dev/kettle-dev/blob/main/SECURITY.md
894
894
  [🔐security-img]: https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
895
895
  [📄copyright-notice-explainer]: https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
data/exe/kettle-changelog CHANGED
@@ -55,7 +55,7 @@ end
55
55
 
56
56
  if ARGV.include?("-h") || ARGV.include?("--help")
57
57
  puts <<~USAGE
58
- Usage: kettle-changelog [--version VERSION] [--update-prep] [--pending-release] [--release-state] [--add-unreleased-entry --section SECTION --entry TEXT] [--json] [--no-strict] [--no-coverage-threshold]
58
+ Usage: kettle-changelog [--version VERSION] [--update-prep] [--pending-release] [--release-state] [--refresh-cache] [--add-unreleased-entry --section SECTION --entry TEXT] [--json] [--no-strict] [--no-coverage-threshold]
59
59
 
60
60
  Detects the current version from lib/**/version.rb, the latest live release, and
61
61
  the most recent CHANGELOG.md release section, then prompts to confirm the selected plan:
@@ -70,6 +70,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
70
70
  --pending-release Query whether the changelog has release work pending; exits 0 for yes, 1 for no
71
71
  --release-state,
72
72
  --release-status Print changelog release state, including latest published release and pending sources
73
+ --refresh-cache Bypass cached gem.coop version data for this invocation
73
74
  --add-unreleased-entry Add one entry to an existing section under ## [Unreleased]
74
75
  --section SECTION Unreleased section to receive the entry (Added, Changed, Deprecated, Removed, Fixed, Security)
75
76
  --entry TEXT Changelog entry text; "- " is added when omitted
@@ -82,6 +83,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
82
83
  K_CHANGELOG_COVERAGE_HARD=false Disable coverage threshold hard-failure
83
84
  K_CHANGELOG_VERSION_FILE=path Read VERSION from this file instead of lib/**/version.rb
84
85
  K_CHANGELOG_GEM_NAME=name Read live release data as this gem instead of root .gemspec
86
+ KETTLE_GEM_COOP_REFRESH=true Bypass cached gem.coop version data
85
87
 
86
88
  Data generation:
87
89
  Strict mode is the default. Release plans remove stale coverage output,
@@ -131,6 +133,7 @@ begin
131
133
  update_prep = ARGV.delete("--update-prep")
132
134
  pending_release_query = ARGV.delete("--pending-release")
133
135
  release_state_query = ARGV.delete("--release-state") || ARGV.delete("--release-status")
136
+ refresh_cache = ARGV.delete("--refresh-cache")
134
137
  add_unreleased_entry = ARGV.delete("--add-unreleased-entry") || ARGV.delete("--add-changelog-entry")
135
138
  json_output = ARGV.delete("--json")
136
139
  coverage_threshold_disabled = ARGV.include?("--no-coverage-threshold") || ARGV.include?("--no-coverage-thresholds")
@@ -167,7 +170,7 @@ begin
167
170
  exit(0)
168
171
  end
169
172
 
170
- cli = Kettle::Dev::ChangelogCLI.new(strict: strict_mode, enforce_coverage_thresholds: coverage_hard, update_prep: update_prep, version: version_override)
173
+ cli = Kettle::Dev::ChangelogCLI.new(strict: strict_mode, enforce_coverage_thresholds: coverage_hard, update_prep: update_prep, version: version_override, refresh_cache: refresh_cache)
171
174
  if release_state_query
172
175
  state = cli.release_state
173
176
  puts(json_output ? JSON.pretty_generate(state) : cli.release_state_table(state))
@@ -27,7 +27,7 @@ module Kettle
27
27
  # @param enforce_coverage_thresholds [Boolean] when true, fail strict coverage generation below project thresholds
28
28
  # @param update_prep [Boolean] when true, update the most recent prepared release section in place
29
29
  # @param version [String, nil] explicit version override for gems without a literal VERSION constant
30
- def initialize(strict: true, enforce_coverage_thresholds: true, update_prep: false, version: nil, root: Kettle::Dev::CIHelpers.project_root)
30
+ def initialize(strict: true, enforce_coverage_thresholds: true, update_prep: false, version: nil, root: Kettle::Dev::CIHelpers.project_root, refresh_cache: false)
31
31
  @root = root
32
32
  @changelog_path = File.join(@root, "CHANGELOG.md")
33
33
  @coverage_path = File.join(@root, "coverage", "coverage.json")
@@ -35,6 +35,7 @@ module Kettle
35
35
  @enforce_coverage_thresholds = enforce_coverage_thresholds
36
36
  @update_prep = update_prep
37
37
  @version_override = Kettle::Dev::Versioning.normalize_explicit_version(version)
38
+ @refresh_cache = refresh_cache
38
39
  end
39
40
 
40
41
  # Main entry point to update CHANGELOG.md
@@ -399,11 +400,9 @@ module Kettle
399
400
  end
400
401
 
401
402
  def latest_released_versions(gem_name, current_version)
402
- uri = URI("https://gem.coop/api/v1/versions/#{gem_name}.json")
403
- res = Net::HTTP.get_response(uri)
404
- return [nil, nil] unless res.is_a?(Net::HTTPSuccess)
403
+ data = Kettle::Dev::GemCoopVersions.fetch(gem_name, version_hint: current_version, refresh: @refresh_cache)
404
+ return [nil, nil, nil] unless data.is_a?(Array)
405
405
 
406
- data = JSON.parse(res.body)
407
406
  versions = data.map { |h| h["number"] }.compact
408
407
  versions.reject! { |v| v.to_s.include?("-pre") || v.to_s.include?(".pre") || v.to_s.match?(/[a-zA-Z]/) }
409
408
  gversions = versions.map { |s| Gem::Version.new(s) }.sort
@@ -0,0 +1,92 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+ require "json"
5
+ require "net/http"
6
+ require "time"
7
+ require "uri"
8
+
9
+ module Kettle
10
+ module Dev
11
+ module GemCoopVersions
12
+ CACHE_BUST_TTL_SECONDS = 15 * 60
13
+ ENV_REFRESH = "KETTLE_GEM_COOP_REFRESH"
14
+ ENV_MARKER_PATH = "KETTLE_GEM_COOP_CACHE_BUST_PATH"
15
+
16
+ class << self
17
+ def fetch(gem_name, version_hint: nil, refresh: false)
18
+ cache_bust = refresh || env_refresh? || fresh_release_marker?(gem_name, version_hint)
19
+ uri = versions_uri(gem_name, cache_bust: cache_bust)
20
+ request = Net::HTTP::Get.new(uri)
21
+ if cache_bust
22
+ request["Cache-Control"] = "no-cache"
23
+ request["Pragma"] = "no-cache"
24
+ end
25
+ response = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == "https") do |http|
26
+ http.request(request)
27
+ end
28
+ return nil unless response.is_a?(Net::HTTPSuccess)
29
+
30
+ JSON.parse(response.body)
31
+ end
32
+
33
+ def mark_released(gem_name, version)
34
+ return if gem_name.to_s.empty? || version.to_s.empty?
35
+
36
+ path = marker_path
37
+ data = read_marker(path)
38
+ data["releases"] ||= {}
39
+ data["releases"][gem_name.to_s] = {
40
+ "version" => version.to_s,
41
+ "released_at" => Time.now.utc.iso8601
42
+ }
43
+ FileUtils.mkdir_p(File.dirname(path))
44
+ File.write(path, JSON.pretty_generate(data) << "\n")
45
+ rescue => error
46
+ warn("[kettle-dev] could not update gem.coop cache-bust marker: #{error.class}: #{error.message}") if Kettle::Dev::DEBUGGING
47
+ end
48
+
49
+ def marker_path
50
+ configured = ENV.fetch(ENV_MARKER_PATH, "").to_s
51
+ return configured unless configured.empty?
52
+
53
+ state_home = ENV["XDG_STATE_HOME"]
54
+ state_home = File.join(Dir.home, ".local", "state") if state_home.to_s.empty?
55
+ File.join(state_home, "kettle-dev", "gem-coop-cache-bust.json")
56
+ end
57
+
58
+ private
59
+
60
+ def versions_uri(gem_name, cache_bust:)
61
+ uri = URI("https://gem.coop/api/v1/versions/#{gem_name}.json")
62
+ uri.query = "_kettle_cache_bust=#{Time.now.to_i}" if cache_bust
63
+ uri
64
+ end
65
+
66
+ def fresh_release_marker?(gem_name, version_hint)
67
+ entry = read_marker(marker_path).fetch("releases", {})[gem_name.to_s]
68
+ return false unless entry
69
+ return false if version_hint && entry["version"].to_s != version_hint.to_s
70
+
71
+ released_at = Time.iso8601(entry["released_at"].to_s)
72
+ released_at >= Time.now.utc - CACHE_BUST_TTL_SECONDS
73
+ rescue ArgumentError
74
+ false
75
+ end
76
+
77
+ def read_marker(path)
78
+ return {} unless File.file?(path)
79
+
80
+ parsed = JSON.parse(File.read(path))
81
+ parsed.is_a?(Hash) ? parsed : {}
82
+ rescue JSON::ParserError
83
+ {}
84
+ end
85
+
86
+ def env_refresh?
87
+ ENV.fetch(ENV_REFRESH, "").match?(Kettle::Dev::ENV_TRUE_RE)
88
+ end
89
+ end
90
+ end
91
+ end
92
+ end
@@ -344,6 +344,7 @@ module Kettle
344
344
  else
345
345
  puts "Running release (you may be prompted for signing key password and RubyGems MFA OTP)..."
346
346
  run_cmd!("bundle exec rake release")
347
+ mark_gem_coop_release_cache_bust(version || detect_version)
347
348
  end
348
349
  end
349
350
 
@@ -954,6 +955,7 @@ module Kettle
954
955
 
955
956
  puts "Publishing #{File.basename(gem_path)} to RubyGems without pushing git refs..."
956
957
  run_cmd!("gem push #{Shellwords.escape(gem_path)}")
958
+ mark_gem_coop_release_cache_bust(version, gem_name: gem_name_from_gem_path(gem_path, version))
957
959
  end
958
960
 
959
961
  def detect_version
@@ -971,11 +973,9 @@ module Kettle
971
973
  end
972
974
 
973
975
  def latest_released_versions(gem_name, current_version)
974
- uri = URI("https://gem.coop/api/v1/versions/#{gem_name}.json")
975
- res = Net::HTTP.get_response(uri)
976
- return [nil, nil] unless res.is_a?(Net::HTTPSuccess)
976
+ data = Kettle::Dev::GemCoopVersions.fetch(gem_name, version_hint: current_version)
977
+ return [nil, nil] unless data.is_a?(Array)
977
978
 
978
- data = JSON.parse(res.body)
979
979
  versions = data.map { |h| h["number"] }.compact
980
980
  versions.reject! { |v| v.to_s.include?("-pre") || v.to_s.include?(".pre") || /[a-zA-Z]/.match?(v.to_s) }
981
981
  gversions = versions.map { |s| Gem::Version.new(s) }.sort
@@ -991,6 +991,18 @@ module Kettle
991
991
  [nil, nil]
992
992
  end
993
993
 
994
+ def mark_gem_coop_release_cache_bust(version, gem_name: nil)
995
+ gem_name ||= detect_gem_name
996
+ Kettle::Dev::GemCoopVersions.mark_released(gem_name, version)
997
+ rescue => error
998
+ warn("[kettle-release] could not mark gem.coop cache-bust for release-state: #{error.class}: #{error.message}") if Kettle::Dev::DEBUGGING
999
+ end
1000
+
1001
+ def gem_name_from_gem_path(gem_path, version)
1002
+ basename = File.basename(gem_path, ".gem")
1003
+ basename.delete_suffix("-#{version}")
1004
+ end
1005
+
994
1006
  def commit_release_prep!(version)
995
1007
  msg = "🔖 Prepare release v#{version}"
996
1008
  # Stage all changes (including new/untracked files) prior to committing
@@ -3,7 +3,7 @@
3
3
  module Kettle
4
4
  module Dev
5
5
  module Version
6
- VERSION = "2.3.8"
6
+ VERSION = "2.3.9"
7
7
  end
8
8
  VERSION = Version::VERSION # Traditional Constant Location
9
9
  end
data/lib/kettle/dev.rb CHANGED
@@ -5,6 +5,7 @@ require_relative "dev/version"
5
5
  if Gem.ruby_version < Gem::Version.new("2.7")
6
6
  begin
7
7
  require "backports/2.7.0/enumerable/filter_map"
8
+ require "backports/2.5.0/string/delete_suffix"
8
9
  rescue LoadError => error
9
10
  message = "kettle-dev on Ruby <= 2.6 requires the backports gem; " \
10
11
  "add `gem \"backports\", \">= 3.25\"` to your Gemfile (#{error.message})"
@@ -33,6 +34,7 @@ module Kettle
33
34
  autoload :CommitMsg, "kettle/dev/commit_msg"
34
35
  autoload :DvcsCLI, "kettle/dev/dvcs_cli"
35
36
  autoload :ExitAdapter, "kettle/dev/exit_adapter"
37
+ autoload :GemCoopVersions, "kettle/dev/gem_coop_versions"
36
38
  autoload :GemSpecReader, "kettle/dev/gem_spec_reader"
37
39
  autoload :GitAdapter, "kettle/dev/git_adapter"
38
40
  autoload :GitCommitFooter, "kettle/dev/git_commit_footer"
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.3.8
4
+ version: 2.3.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter H. Boling
@@ -282,6 +282,7 @@ files:
282
282
  - lib/kettle/dev/commit_msg.rb
283
283
  - lib/kettle/dev/dvcs_cli.rb
284
284
  - lib/kettle/dev/exit_adapter.rb
285
+ - lib/kettle/dev/gem_coop_versions.rb
285
286
  - lib/kettle/dev/gem_spec_reader.rb
286
287
  - lib/kettle/dev/gha_sha_pins_cli.rb
287
288
  - lib/kettle/dev/git_adapter.rb
@@ -313,10 +314,10 @@ licenses:
313
314
  - AGPL-3.0-only
314
315
  metadata:
315
316
  homepage_uri: https://kettle-dev.galtzo.com
316
- source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.3.8
317
- changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.3.8/CHANGELOG.md
317
+ source_code_uri: https://github.com/kettle-dev/kettle-dev/tree/v2.3.9
318
+ changelog_uri: https://github.com/kettle-dev/kettle-dev/blob/v2.3.9/CHANGELOG.md
318
319
  bug_tracker_uri: https://github.com/kettle-dev/kettle-dev/issues
319
- documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.3.8
320
+ documentation_uri: https://www.rubydoc.info/gems/kettle-dev/2.3.9
320
321
  funding_uri: https://github.com/sponsors/pboling
321
322
  wiki_uri: https://github.com/kettle-dev/kettle-dev/wiki
322
323
  news_uri: https://www.railsbling.com/tags/kettle-dev
metadata.gz.sig CHANGED
Binary file