diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index 84cfe7328d57f..5cfa65c839c0a 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -471,7 +471,8 @@ def check_new_version(formula, tap_remote_repo, version: nil, url: nil, tag: nil end def check_throttle(formula, new_version) - throttled_rate = formula.tap.audit_exceptions.dig(:throttled_formulae, formula.name) + throttled_rate = formula.livecheck.throttle + throttled_rate ||= formula.tap.audit_exceptions.dig(:throttled_formulae, formula.name) 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 c1260fde51267..cc19ca70be6c7 100644 --- a/Library/Homebrew/dev-cmd/bump.rb +++ b/Library/Homebrew/dev-cmd/bump.rb @@ -276,7 +276,8 @@ 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?}" end version_info = Livecheck.latest_version( @@ -286,9 +287,13 @@ def livecheck_result(formula_or_cask) ) return "unable to get versions" if version_info.blank? - latest = version_info[:latest] - - Version.new(latest) + if !version_info.key?(:latest_throttled) + Version.new(version_info[:latest]) + elsif version_info[:latest_throttled].nil? + "unable to get throttled versions" + else + Version.new(version_info[:latest_throttled]) + end rescue => e "error: #{e}" end @@ -475,7 +480,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) Latest Repology version: #{repology_latest} diff --git a/Library/Homebrew/livecheck.rb b/Library/Homebrew/livecheck.rb index 353607a4144c9..761ac38b7b250 100644 --- a/Library/Homebrew/livecheck.rb +++ b/Library/Homebrew/livecheck.rb @@ -29,6 +29,7 @@ def initialize(package_or_resource) @skip_msg = nil @strategy = nil @strategy_block = nil + @throttle = nil @url = nil end @@ -135,6 +136,23 @@ def strategy(symbol = T.unsafe(nil), &block) sig { returns(T.nilable(Proc)) } attr_reader :strategy_block + # 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: Integer, + ).returns(T.nilable(Integer)) + } + def throttle(rate = T.unsafe(nil)) + case rate + when nil + @throttle + when Integer + @throttle = rate + end + end + # Sets the `@url` instance variable to the provided argument or returns the # `@url` instance variable when no argument is provided. The argument can be # a `String` (a URL) or a supported `Symbol` corresponding to a URL in the @@ -171,6 +189,7 @@ def to_hash "skip" => @skip, "skip_msg" => @skip_msg, "strategy" => @strategy, + "throttle" => @throttle, "url" => @url, } end diff --git a/Library/Homebrew/livecheck/livecheck.rb b/Library/Homebrew/livecheck/livecheck.rb index 6285345d4c63e..965e9c3c8b742 100644 --- a/Library/Homebrew/livecheck/livecheck.rb +++ b/Library/Homebrew/livecheck/livecheck.rb @@ -372,9 +372,10 @@ def run_checks( info[:version] = { current: current_str, latest: latest_str, + latest_throttled: version_info&.dig(:latest_throttled), outdated: is_outdated, newer_than_upstream: is_newer_than_upstream, - } + }.compact info[:meta] = { livecheckable: formula_or_cask.livecheckable?, } @@ -678,6 +679,7 @@ def latest_version( livecheck_regex = livecheck.regex || referenced_livecheck&.regex livecheck_strategy = livecheck.strategy || referenced_livecheck&.strategy livecheck_strategy_block = livecheck.strategy_block || referenced_livecheck&.strategy_block + livecheck_throttle = livecheck.throttle || referenced_livecheck&.throttle livecheck_url_string = livecheck_url_to_string( livecheck_url, @@ -695,6 +697,7 @@ def latest_version( puts "Cask: #{cask_name(formula_or_cask, full_name:)}" end puts "Livecheckable?: #{has_livecheckable ? "Yes" : "No"}" + puts "Throttle: #{livecheck_throttle}" if livecheck_throttle livecheck_references.each do |ref_formula_or_cask| case ref_formula_or_cask @@ -826,6 +829,28 @@ def latest_version( latest: Version.new(match_version_map.values.max_by { |v| LivecheckVersion.create(formula_or_cask, v) }), } + if livecheck_throttle + match_version_map.keep_if { |_match, version| version.patch.to_i.modulo(livecheck_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] = {} @@ -854,6 +879,7 @@ def latest_version( version_info[:meta][:strategies] = strategies.map { |s| livecheck_strategy_names[s] } if strategies.present? version_info[:meta][:regex] = regex.inspect if regex.present? version_info[:meta][:cached] = true if strategy_data[:cached] == true + version_info[:meta][:throttle] = livecheck_throttle if livecheck_throttle end return version_info diff --git a/Library/Homebrew/test/livecheck_spec.rb b/Library/Homebrew/test/livecheck_spec.rb index a3fd7e6dd4550..f0136ca886e1b 100644 --- a/Library/Homebrew/test/livecheck_spec.rb +++ b/Library/Homebrew/test/livecheck_spec.rb @@ -100,6 +100,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 "#url" do let(:url_string) { "https://brew.sh" } @@ -143,6 +154,7 @@ "skip" => false, "skip_msg" => nil, "strategy" => nil, + "throttle" => nil, "url" => nil, }, )