From fe16b144793c3be1550861f24a3fdd470043430b Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Thu, 28 Mar 2024 11:56:25 +0000 Subject: [PATCH 1/2] dev-cmd/bump*: limit the number of open PRs to 15. Don't let users open more than 15 PRs at a time. We have other tooling to nudge them to not do this but let's put it in the worst offenders: the `bump*` commands. --- Library/Homebrew/dev-cmd/bump-cask-pr.rb | 2 + Library/Homebrew/dev-cmd/bump-formula-pr.rb | 2 + Library/Homebrew/dev-cmd/bump.rb | 4 ++ Library/Homebrew/utils/github.rb | 56 +++++++++++++++++++++ 4 files changed, 64 insertions(+) diff --git a/Library/Homebrew/dev-cmd/bump-cask-pr.rb b/Library/Homebrew/dev-cmd/bump-cask-pr.rb index cc235e9af9d3c..4f520d67c1616 100644 --- a/Library/Homebrew/dev-cmd/bump-cask-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-cask-pr.rb @@ -93,6 +93,8 @@ def run #{Formatter.url("#{cask.tap.remote}/blob/master/.github/autobump.txt")} EOS + odie "You have too many PRs open: close or merge some first!" if GitHub.too_many_open_prs?(cask.tap) + new_version = BumpVersionParser.new( general: args.version, intel: args.version_intel, diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index 6ba96dd76b225..2c972aab94ab7 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -120,6 +120,8 @@ def run #{Formatter.url("#{formula.tap.remote}/blob/master/.github/autobump.txt")} EOS + odie "You have too many PRs open: close or merge some first!" if GitHub.too_many_open_prs?(formula.tap) + formula_spec = formula.stable odie "#{formula}: no stable specification found!" if formula_spec.blank? diff --git a/Library/Homebrew/dev-cmd/bump.rb b/Library/Homebrew/dev-cmd/bump.rb index cc19ca70be6c7..3de0bd860a4ef 100644 --- a/Library/Homebrew/dev-cmd/bump.rb +++ b/Library/Homebrew/dev-cmd/bump.rb @@ -499,6 +499,10 @@ def retrieve_and_display_info_and_open_pr(formula_or_cask, name, repositories, a return unless args.open_pr? + if GitHub.too_many_open_prs?(formula_or_cask.tap) + odie "You have too many PRs open: close or merge some first!" + end + if repology_latest.is_a?(Version) && repology_latest > current_version.general && repology_latest > new_version.general && diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb index 5117f58b1268e..d3a80cbbf3246 100644 --- a/Library/Homebrew/utils/github.rb +++ b/Library/Homebrew/utils/github.rb @@ -863,4 +863,60 @@ def self.count_repo_commits(nwo, user, args, max: nil) [author_count, committer_count] end + + MAXIMUM_OPEN_PRS = 15 + + sig { params(tap: T.nilable(Tap)).returns(T::Boolean) } + def self.too_many_open_prs?(tap) + # We don't enforce unofficial taps. + return false if tap.nil? && !tap.official? + + # BrewTestBot can open as many PRs as it wants. + return false if ENV["HOMEBREW_TEST_BOT_AUTOBUMP"].present? + + odie "Cannot count PRs, HOMEBREW_NO_GITHUB_API set!" if Homebrew::EnvConfig.no_github_api? + + query = <<~EOS + query { + viewer { + login + pullRequests(first: 100, states: OPEN) { + nodes { + headRepositoryOwner { + login + } + } + pageInfo { + hasNextPage + } + } + } + } + EOS + graphql_result = API.open_graphql(query) + puts + + github_user = graphql_result.dig("viewer", "login") + odie "Cannot count PRs, cannot get GitHub username from GraphQL API!" if github_user.blank? + + # BrewTestBot can open as many PRs as it wants. + return false if github_user.casecmp("brewtestbot").zero? + + prs = graphql_result.dig("viewer", "pullRequests", "nodes") + more_graphql_data = graphql_result.dig("viewer", "pullRequests", "pageInfo", "hasNextPage") + return false if !more_graphql_data && prs.length < MAXIMUM_OPEN_PRS + + homebrew_prs_count = graphql_result.dig("viewer", "pullRequests", "nodes").count do |pr| + pr["headRepositoryOwner"]["login"] == "Homebrew" + end + return true if homebrew_prs_count >= MAXIMUM_OPEN_PRS + return false unless more_graphql_data + return false if tap.nil? + + url = "#{API_URL}/repos/#{tap.full_name}/issues?state=open&creator=#{github_user}" + rest_result = API.open_rest(url) + repo_prs_count = rest_result.count { |issue_or_pr| issue_or_pr.key?("pull_request") } + + repo_prs_count >= MAXIMUM_OPEN_PRS + end end From b3bf91acec0ec9ed66ae653c1763b41d02beaee5 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Thu, 28 Mar 2024 12:30:01 +0000 Subject: [PATCH 2/2] utils/github: fix tap logic. Co-authored-by: Carlo Cabrera <30379873+carlocab@users.noreply.github.com> --- Library/Homebrew/utils/github.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb index d3a80cbbf3246..17f6ec40b0209 100644 --- a/Library/Homebrew/utils/github.rb +++ b/Library/Homebrew/utils/github.rb @@ -869,7 +869,7 @@ def self.count_repo_commits(nwo, user, args, max: nil) sig { params(tap: T.nilable(Tap)).returns(T::Boolean) } def self.too_many_open_prs?(tap) # We don't enforce unofficial taps. - return false if tap.nil? && !tap.official? + return false if tap.nil? || !tap.official? # BrewTestBot can open as many PRs as it wants. return false if ENV["HOMEBREW_TEST_BOT_AUTOBUMP"].present?