livecheck: support throttle DSL

Signed-off-by: Michael Cho <michael@michaelcho.dev>
This commit is contained in:
Michael Cho 2024-03-19 11:17:00 -04:00
parent a2378f29d9
commit bfec6eecac
No known key found for this signature in database
GPG Key ID: 55E85E28A7CD1E85
5 changed files with 75 additions and 8 deletions

View File

@ -472,6 +472,7 @@ module Homebrew
def check_throttle(formula, new_version)
throttled_rate = formula.tap.audit_exceptions.dig(:throttled_formulae, formula.name)
throttled_rate ||= formula.livecheck.throttle
return if throttled_rate.blank?
formula_suffix = Version.new(new_version).patch.to_i

View File

@ -248,7 +248,9 @@ module Homebrew
end
sig {
params(formula_or_cask: T.any(Formula, Cask::Cask)).returns(T.any(Version, String))
params(
formula_or_cask: T.any(Formula, Cask::Cask),
).returns([T.any(Version, String), T.nilable(T.any(Version, String))])
}
def livecheck_result(formula_or_cask)
name = Livecheck.package_or_resource_name(formula_or_cask)
@ -276,7 +278,9 @@ module Homebrew
)
if skip_info.present?
return "#{skip_info[:status]}#{" - #{skip_info[:messages].join(", ")}" if skip_info[:messages].present?}"
return "#{skip_info[:status]}" \
"#{" - #{skip_info[:messages].join(", ")}" if skip_info[:messages].present?}",
nil
end
version_info = Livecheck.latest_version(
@ -284,13 +288,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?
latest = version_info[:latest]
latest = Version.new(version_info[:latest])
latest_throttled = if !version_info.key?(:latest_throttled)
nil
elsif version_info[:latest_throttled].nil?
"unable to get throttled versions"
else
Version.new(version_info[:latest_throttled])
end
Version.new(latest)
[latest, latest_throttled]
rescue => e
"error: #{e}"
["error: #{e}", nil]
end
sig {
@ -349,7 +360,9 @@ module Homebrew
current_version_value = Version.new(loaded_formula_or_cask.version)
end
livecheck_latest = livecheck_result(loaded_formula_or_cask)
livecheck_latest, livecheck_latest_throttled = livecheck_result(loaded_formula_or_cask)
# TODO: Pass down `livecheck_latest` info to print output for throttled formulae or casks
livecheck_latest = livecheck_latest_throttled if livecheck_latest_throttled
new_version_value = if (livecheck_latest.is_a?(Version) && livecheck_latest >= current_version_value) ||
current_version_value == "latest"
@ -475,7 +488,7 @@ module Homebrew
ohai title
puts <<~EOS
Current #{version_label} #{current_versions}
Latest livecheck version: #{new_versions}
Latest livecheck version: #{new_versions}#{" (throttled)" if formula_or_cask.livecheck.throttle}
EOS
puts <<~EOS unless skip_repology?(formula_or_cask)
Latest Repology version: #{repology_latest}

View File

@ -25,6 +25,7 @@ class Livecheck
@referenced_cask_name = nil
@referenced_formula_name = nil
@regex = nil
@throttle = nil
@skip = false
@skip_msg = nil
@strategy = nil
@ -87,6 +88,23 @@ class Livecheck
end
end
# Sets the `@throttle` instance variable to the provided `Integer` or returns
# the `@throttle` instance variable when no argument is provided.
sig {
params(
# Throttle rate of version patch number to use for bumpable versions.
rate: T.nilable(Integer),
).returns(T.nilable(Integer))
}
def throttle(rate = T.unsafe(nil))
case rate
when nil
@throttle
when Integer
@throttle = rate
end
end
# Sets the `@skip` instance variable to `true` and sets the `@skip_msg`
# instance variable if a `String` is provided. `@skip` is used to indicate
# that the formula/cask/resource should be skipped and the `skip_msg` very
@ -168,6 +186,7 @@ class Livecheck
"cask" => @referenced_cask_name,
"formula" => @referenced_formula_name,
"regex" => @regex,
"throttle" => @throttle,
"skip" => @skip,
"skip_msg" => @skip_msg,
"strategy" => @strategy,

View File

@ -826,6 +826,28 @@ module Homebrew
latest: Version.new(match_version_map.values.max_by { |v| LivecheckVersion.create(formula_or_cask, v) }),
}
if (throttle = livecheck.throttle || referenced_livecheck&.throttle)
match_version_map.keep_if { |_match, version| version.patch.to_i.modulo(throttle).zero? }
version_info[:latest_throttled] = if match_version_map.blank?
nil
else
Version.new(match_version_map.values.max_by { |v| LivecheckVersion.create(formula_or_cask, v) })
end
if debug
puts
puts "Matched Throttled Versions:"
if verbose
match_version_map.each do |match, version|
puts "#{match} => #{version.inspect}"
end
else
puts match_version_map.values.join(", ")
end
end
end
if json && verbose
version_info[:meta] = {}

View File

@ -66,6 +66,17 @@ RSpec.describe Livecheck do
end
end
describe "#throttle" do
it "returns nil if not set" do
expect(livecheckable_f.throttle).to be_nil
end
it "returns the Integer if set" do
livecheckable_f.throttle(10)
expect(livecheckable_f.throttle).to eq(10)
end
end
describe "#skip" do
it "sets @skip to true when no argument is provided" do
expect(livecheckable_f.skip).to be true
@ -140,6 +151,7 @@ RSpec.describe Livecheck do
"cask" => nil,
"formula" => nil,
"regex" => nil,
"throttle" => nil,
"skip" => false,
"skip_msg" => nil,
"strategy" => nil,