From 7ff01d86d5056a4fd0ba9d5b498756bfab4337bb Mon Sep 17 00:00:00 2001 From: Michael Cho Date: Tue, 19 Mar 2024 11:17:00 -0400 Subject: [PATCH] livecheck: support throttle DSL Signed-off-by: Michael Cho --- Library/Homebrew/dev-cmd/bump-formula-pr.rb | 1 + Library/Homebrew/dev-cmd/bump.rb | 27 +++++++++++++++------ Library/Homebrew/livecheck.rb | 19 +++++++++++++++ Library/Homebrew/livecheck/livecheck.rb | 22 +++++++++++++++++ Library/Homebrew/test/livecheck_spec.rb | 12 +++++++++ 5 files changed, 73 insertions(+), 8 deletions(-) diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index 4ed5dbb345ca37..80fb3d910a14e4 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -472,6 +472,7 @@ def check_new_version(formula, tap_remote_repo, args:, version: nil, url: nil, t 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 diff --git a/Library/Homebrew/dev-cmd/bump.rb b/Library/Homebrew/dev-cmd/bump.rb index 008d2f7794f7aa..dc506d3455a944 100644 --- a/Library/Homebrew/dev-cmd/bump.rb +++ b/Library/Homebrew/dev-cmd/bump.rb @@ -252,7 +252,9 @@ def skip_ineligible_formulae(formula_or_cask) 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) @@ -280,7 +282,7 @@ def livecheck_result(formula_or_cask) ) 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( @@ -288,13 +290,20 @@ def livecheck_result(formula_or_cask) 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 { @@ -350,7 +359,9 @@ def retrieve_versions_by_arch(formula_or_cask:, repositories:, args:, name:) 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" @@ -478,7 +489,7 @@ def retrieve_and_display_info_and_open_pr(formula_or_cask, name, repositories, a 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, args:) Latest Repology version: #{repology_latest} diff --git a/Library/Homebrew/livecheck.rb b/Library/Homebrew/livecheck.rb index 353607a4144c9f..1022c4059cd5b0 100644 --- a/Library/Homebrew/livecheck.rb +++ b/Library/Homebrew/livecheck.rb @@ -25,6 +25,7 @@ def initialize(package_or_resource) @referenced_cask_name = nil @referenced_formula_name = nil @regex = nil + @throttle = nil @skip = false @skip_msg = nil @strategy = nil @@ -87,6 +88,23 @@ def regex(pattern = T.unsafe(nil)) 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 @@ def to_hash "cask" => @referenced_cask_name, "formula" => @referenced_formula_name, "regex" => @regex, + "throttle" => @throttle, "skip" => @skip, "skip_msg" => @skip_msg, "strategy" => @strategy, diff --git a/Library/Homebrew/livecheck/livecheck.rb b/Library/Homebrew/livecheck/livecheck.rb index 6ab47d4992ba74..3aa30dd6a833c2 100644 --- a/Library/Homebrew/livecheck/livecheck.rb +++ b/Library/Homebrew/livecheck/livecheck.rb @@ -810,6 +810,28 @@ def latest_version( 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] = {} diff --git a/Library/Homebrew/test/livecheck_spec.rb b/Library/Homebrew/test/livecheck_spec.rb index a3fd7e6dd4550b..2540eb7da3edf3 100644 --- a/Library/Homebrew/test/livecheck_spec.rb +++ b/Library/Homebrew/test/livecheck_spec.rb @@ -66,6 +66,17 @@ 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 @@ "cask" => nil, "formula" => nil, "regex" => nil, + "throttle" => nil, "skip" => false, "skip_msg" => nil, "strategy" => nil,