Merge pull request #23409 from Homebrew/bump-release-cooldown-output

bump: show upstream versions in release cooldown
This commit is contained in:
Mike McQuaid
2026-08-04 09:56:52 +00:00
committed by GitHub
2 changed files with 103 additions and 13 deletions
+37 -11
View File
@@ -48,6 +48,7 @@ module Homebrew
const :resource_versions, T::Array[ResourceVersionInfo], default: []
const :repology_latest, T.any(String, Version)
const :newer_than_upstream, T::Hash[Symbol, T::Boolean], default: {}
const :cooldown_skipped_versions, T::Hash[Symbol, Version], default: {}
const :duplicate_pull_requests, T.nilable(T.any(T::Array[String], String))
const :maybe_duplicate_pull_requests, T.nilable(T.any(T::Array[String], String))
end
@@ -230,6 +231,7 @@ module Homebrew
deprecated = {}
current_versions = {}
new_versions = {}
cooldown_skipped_versions = {}
repology_latest = repositories.present? ? Repology.latest_version(repositories) : "not found"
repology_latest_is_a_version = repology_latest.is_a?(Version)
@@ -271,7 +273,8 @@ module Homebrew
deprecated[version_key] = loaded_formula_or_cask.deprecated?
formula_or_cask_has_livecheck = loaded_formula_or_cask.livecheck_defined?
livecheck_latest = livecheck_result(loaded_formula_or_cask, current_version_value)
livecheck_latest, cooldown_skipped = livecheck_result(loaded_formula_or_cask, current_version_value)
cooldown_skipped_versions[version_key] = cooldown_skipped if cooldown_skipped
livecheck_latest_is_a_version = livecheck_latest.is_a?(Version)
new_version_value = if (livecheck_latest_is_a_version &&
@@ -307,6 +310,7 @@ module Homebrew
single_arch = arch_options[0]
current_versions = { general: current_versions[single_arch] }
new_versions = { general: new_versions[single_arch] }
cooldown_skipped_versions = { general: cooldown_skipped_versions[single_arch] }.compact
else
if current_versions[:arm].present? && current_versions[:arm] == current_versions[:intel]
current_versions = { general: current_versions[:arm] }
@@ -314,6 +318,10 @@ module Homebrew
if new_versions[:arm].present? && new_versions[:arm] == new_versions[:intel]
new_versions = { general: new_versions[:arm] }
end
if cooldown_skipped_versions[:arm].present? &&
cooldown_skipped_versions[:arm] == cooldown_skipped_versions[:intel]
cooldown_skipped_versions = { general: cooldown_skipped_versions[:arm] }
end
end
current_version = BumpVersionParser.new(general: current_versions[:general],
@@ -386,6 +394,7 @@ module Homebrew
resource_versions:,
repology_latest:,
newer_than_upstream:,
cooldown_skipped_versions:,
duplicate_pull_requests:,
maybe_duplicate_pull_requests:,
)
@@ -410,6 +419,7 @@ module Homebrew
new_version = version_info.new_version
repology_latest = version_info.repology_latest
newer_than_upstream = version_info.newer_than_upstream
cooldown_skipped_version = version_info.cooldown_skipped_versions.values.max
duplicate_pull_requests = version_info.duplicate_pull_requests
maybe_duplicate_pull_requests = version_info.maybe_duplicate_pull_requests
@@ -418,7 +428,11 @@ module Homebrew
title_name = ambiguous_cask ? "#{name} (cask)" : name
title = if (repology_latest == current_version.general || !repology_latest.is_a?(Version)) && versions_equal
"#{title_name} #{Tty.green}is up to date!#{Tty.reset}"
if cooldown_skipped_version
"#{title_name} #{Tty.yellow}has a new version in release cooldown#{Tty.reset}"
else
"#{title_name} #{Tty.green}is up to date!#{Tty.reset}"
end
else
title_name
end
@@ -446,11 +460,18 @@ module Homebrew
end
throttled = formula_or_cask.livecheck.throttle || formula_or_cask.livecheck.throttle_days
latest_versions = if cooldown_skipped_version
cooldown_days = Utils.pluralize("day", Homebrew::RELEASE_COOLDOWN_DAYS, include_count: true)
"#{cooldown_skipped_version} (released less than #{cooldown_days} ago)"
else
"#{new_versions}#{" (throttled)" if throttled}"
end
ohai title
puts <<~EOS
Current #{version_info.version_name} #{current_versions}
Latest livecheck version: #{new_versions}#{" (throttled)" if throttled}
Latest livecheck version: #{latest_versions}
EOS
puts "Bump-ready version: #{new_versions}" if cooldown_skipped_version
puts <<~EOS unless skip_repology?(formula_or_cask)
Latest Repology version: #{repology_latest}
EOS
@@ -851,11 +872,13 @@ module Homebrew
end
end
# Returns the new version (or a message string) and the newest upstream
# version skipped due to the release cooldown, if any.
sig {
params(
formula_or_cask: T.any(Formula, Cask::Cask),
current: T.nilable(T.any(Version, Cask::DSL::Version)),
).returns(T.any(Version, String))
).returns([T.any(Version, String), T.nilable(Version)])
}
def livecheck_result(formula_or_cask, current)
name = Livecheck.package_or_resource_name(formula_or_cask)
@@ -886,9 +909,9 @@ module Homebrew
skip_status = skip_info[:status]
skip_messages = skip_info[:messages]
skip_message = skip_messages.join("; ") if skip_messages.present?
return "error: #{skip_message}" if skip_status == "error" && skip_message
return "error: #{skip_message}", nil if skip_status == "error" && skip_message
return "skipped - #{skip_message || skip_status}"
return "skipped - #{skip_message || skip_status}", nil
end
version_info = Livecheck.latest_version(
@@ -896,17 +919,20 @@ module Homebrew
referenced_formula_or_cask:,
json: true, full_name: false, verbose: true, debug: false
)
return "unable to get versions" if version_info.blank?
return "unable to get versions", nil if version_info.blank?
if !version_info.key?(:latest_throttled)
version_with_cooldown(version_info, current) || Version.new(version_info[:latest])
latest = Version.new(version_info[:latest])
cooldown_version = version_with_cooldown(version_info, current)
cooldown_skipped = (latest if cooldown_version && cooldown_version < latest)
[cooldown_version || latest, cooldown_skipped]
elsif version_info[:latest_throttled].nil?
"unable to get throttled versions"
["unable to get throttled versions", nil]
else
Version.new(version_info[:latest_throttled])
[Version.new(version_info[:latest_throttled]), nil]
end
rescue => e
"error: #{e}"
["error: #{e}", nil]
end
sig {
+66 -2
View File
@@ -222,6 +222,31 @@ RSpec.describe Homebrew::DevCmd::Bump do
bump.retrieve_and_display_info_and_open_pr(c_basic, "basic-cask", [], ambiguous_cask: false)
end
it "notes when a newer upstream version was skipped due to release cooldown" do
version_info = Homebrew::DevCmd::Bump::VersionBumpInfo.new(
type: :formula,
deprecated: { general: false },
multiple_versions: { current: false, new: false },
version_name: "formula version:",
current_version: Homebrew::BumpVersionParser.new(general: Version.new("1.2.3")),
new_version: Homebrew::BumpVersionParser.new(general: Version.new("1.2.3")),
repology_latest: "not found",
newer_than_upstream: { general: false },
cooldown_skipped_versions: { general: Version.new("1.2.4") },
duplicate_pull_requests: nil,
maybe_duplicate_pull_requests: nil,
)
allow(bump).to receive(:retrieve_versions_by_arch).and_return(version_info)
expect { bump.retrieve_and_display_info_and_open_pr(f_basic, "basic_formula", [], ambiguous_cask: false) }
.to output(<<~EOS).to_stdout
==> basic_formula has a new version in release cooldown
Current formula version: 1.2.3
Latest livecheck version: 1.2.4 (released less than 1 day ago)
Bump-ready version: 1.2.3
EOS
end
end
describe "::retrieve_versions_by_arch" do
@@ -263,11 +288,26 @@ RSpec.describe Homebrew::DevCmd::Bump do
end
RUBY
end
let(:c_multi_arch) do
Cask::CaskLoader.load(+<<-RUBY)
cask "multi_arch_cask" do
arch arm: "arm64", intel: "x64"
version "1.2.3"
sha256 :no_check
url "https://brew.sh/test-\#{arch}.dmg"
name "Multi Arch Cask"
desc "Multi arch cask"
homepage "https://brew.sh"
end
RUBY
end
it "simulates only arm and consolidates to a general version when `depends_on arch:` restricts to arm-only" do
allow(c_arm_only).to receive(:sourcefile_path).and_return(Pathname("arm_only_cask.rb"))
allow(Cask::CaskLoader).to receive(:load).and_return(c_arm_only)
expect(bump).to receive(:livecheck_result).once.and_return(Version.new("1.2.4"))
expect(bump).to receive(:livecheck_result).once.and_return([Version.new("1.2.4"), nil])
version_info = bump.retrieve_versions_by_arch(
formula_or_cask: c_arm_only, repositories: [], name: "arm-only-cask",
@@ -278,13 +318,37 @@ RSpec.describe Homebrew::DevCmd::Bump do
it "simulates only intel and consolidates to a general version when `depends_on arch:` restricts to intel-only" do
allow(c_intel_only).to receive(:sourcefile_path).and_return(Pathname("intel_only_cask.rb"))
allow(Cask::CaskLoader).to receive(:load).and_return(c_intel_only)
expect(bump).to receive(:livecheck_result).once.and_return(Version.new("1.2.4"))
expect(bump).to receive(:livecheck_result).once.and_return([Version.new("1.2.4"), nil])
version_info = bump.retrieve_versions_by_arch(
formula_or_cask: c_intel_only, repositories: [], name: "intel-only-cask",
)
expect(version_info.new_version).to eq(Homebrew::BumpVersionParser.new(general: Version.new("1.2.4")))
end
it "records the upstream version skipped due to release cooldown" do
expect(bump).to receive(:livecheck_result).once.and_return([Version.new("1.2.3"), Version.new("1.2.4")])
version_info = bump.retrieve_versions_by_arch(
formula_or_cask: f_basic, repositories: [], name: "basic_formula",
)
expect(version_info.cooldown_skipped_versions).to eq({ general: Version.new("1.2.4") })
end
it "records cooldown-skipped versions per architecture" do
allow(c_multi_arch).to receive(:sourcefile_path).and_return(Pathname("multi_arch_cask.rb"))
allow(Cask::CaskLoader).to receive(:load).and_return(c_multi_arch)
expect(bump).to receive(:livecheck_result).twice.and_return(
[Version.new("1.2.3"), Version.new("1.2.4")],
[Version.new("1.2.3"), Version.new("1.2.5")],
)
version_info = bump.retrieve_versions_by_arch(
formula_or_cask: c_multi_arch, repositories: [], name: "multi-arch-cask",
)
expect(version_info.cooldown_skipped_versions).to eq({ arm: Version.new("1.2.5"),
intel: Version.new("1.2.4") })
end
end
describe "::message?" do