From 1e0f9fb835533c7c31ff3ebea36b7dbdeff4c0a7 Mon Sep 17 00:00:00 2001 From: Gautham Goli Date: Sun, 4 Mar 2018 00:12:59 +0530 Subject: [PATCH 1/2] bump-formula-pr: Replace hub with GH API calls to fork and open Pull request --- Library/Homebrew/cmd/gist-logs.rb | 2 +- Library/Homebrew/dev-cmd/bump-formula-pr.rb | 72 ++++++++------------- Library/Homebrew/utils/github.rb | 18 +++++- 3 files changed, 43 insertions(+), 49 deletions(-) diff --git a/Library/Homebrew/cmd/gist-logs.rb b/Library/Homebrew/cmd/gist-logs.rb index c30ee85cd9..df87b327c8 100644 --- a/Library/Homebrew/cmd/gist-logs.rb +++ b/Library/Homebrew/cmd/gist-logs.rb @@ -119,7 +119,7 @@ module Homebrew def create_issue(repo, title, body) url = "https://api.github.com/repos/#{repo}/issues" data = { "title" => title, "body" => body } - scopes = GitHub::CREATE_ISSUE_SCOPES + scopes = GitHub::CREATE_ISSUE_FORK_OR_PR_SCOPES GitHub.open_api(url, data: data, scopes: scopes)["html_url"] end diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index 1f44fa549e..9bc38c9bf2 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -131,6 +131,9 @@ module Homebrew ENV[env] = homebrew_env end + gh_api_errors = [GitHub::AuthenticationFailedError, GitHub::HTTPNotFoundError, + GitHub::RateLimitExceededError, GitHub::Error, JSON::ParserError].freeze + formula = ARGV.formulae.first if formula @@ -314,73 +317,39 @@ module Homebrew end end - unless Formula["hub"].any_version_installed? - if ARGV.dry_run? - ohai "brew install hub" - else - safe_system "brew", "install", "hub" - end - end - formula.path.parent.cd do branch = "#{formula.name}-#{new_formula_version}" git_dir = Utils.popen_read("git rev-parse --git-dir").chomp shallow = !git_dir.empty? && File.exist?("#{git_dir}/shallow") - hub_args = [] - git_final_checkout_args = [] - if ARGV.include?("--no-browse") - git_final_checkout_args << "--quiet" - else - hub_args << "--browse" - end - if ARGV.dry_run? - ohai "hub fork # read $HUB_REMOTE" + ohai "fork repository with GitHub API" ohai "git fetch --unshallow origin" if shallow ohai "git checkout --no-track -b #{branch} origin/master" ohai "git commit --no-edit --verbose --message='#{formula.name} #{new_formula_version}#{devel_message}' -- #{formula.path}" ohai "git push --set-upstream $HUB_REMOTE #{branch}:#{branch}" - ohai "hub pull-request #{hub_args.join(" ")} -m '#{formula.name} #{new_formula_version}#{devel_message}'" + ohai "create pull request with GitHub API" ohai "git checkout -" else - reply = IO.popen(["hub", "fork"], "r+", err: "/dev/null") do |io| - reader = Thread.new { io.read } - sleep 1 - io.close_write - reader.value - end - if reply.to_s.include? "username:" + begin + response = GitHub.create_fork(formula.tap.full_name) + rescue *gh_api_errors => e formula.path.atomic_write(backup_file) unless ARGV.dry_run? - git_path = "$(brew --repo #{formula.tap})" if formula.tap - git_path ||= formula.path.parent - odie <<~EOS - Retry after configuring hub by running: - hub -C "#{git_path}" fork - Or setting HOMEBREW_GITHUB_TOKEN with at least 'public_repo' scope. - EOS + odie "Unable to fork: #{e.message}!" end - remote = reply[/remote:? (\S+)/, 1] - - # repeat for hub 2.2 backwards compatibility: - remote = Utils.popen_read("hub", "fork", err: :out)[/remote:? (\S+)/, 1] if remote.to_s.empty? - - if remote.to_s.empty? - formula.path.atomic_write(backup_file) unless ARGV.dry_run? - odie "cannot get remote from 'hub'!" - end + remote_url = response.fetch("clone_url") + username = response.fetch("owner").fetch("login") safe_system "git", "fetch", "--unshallow", "origin" if shallow safe_system "git", "checkout", "--no-track", "-b", branch, "origin/master" safe_system "git", "commit", "--no-edit", "--verbose", "--message=#{formula.name} #{new_formula_version}#{devel_message}", "--", formula.path - safe_system "git", "push", "--set-upstream", remote, "#{branch}:#{branch}" + safe_system "git", "push", "--set-upstream", remote_url, "#{branch}:#{branch}" + safe_system "git", "checkout", "--quiet", "-" pr_message = <<~EOS - #{formula.name} #{new_formula_version}#{devel_message} - Created with `brew bump-formula-pr`. EOS user_message = ARGV.value("message") @@ -391,8 +360,19 @@ module Homebrew #{user_message} EOS end - safe_system "hub", "pull-request", *hub_args, "-m", pr_message - safe_system "git", "checkout", *git_final_checkout_args, "-" + pr_title = "#{formula.name} #{new_formula_version}#{devel_message}" + + begin + url = GitHub.create_pull_request(formula.tap.full_name, pr_title, + "#{username}:#{branch}", "master", pr_message)["html_url"] + if ARGV.include?("--no-browse") + puts url + else + exec_browser url + end + rescue *gh_api_errors => e + odie "Unable to open pull request: #{e.message}!" + end end end end diff --git a/Library/Homebrew/utils/github.rb b/Library/Homebrew/utils/github.rb index b6a27b3283..e69e37cc5e 100644 --- a/Library/Homebrew/utils/github.rb +++ b/Library/Homebrew/utils/github.rb @@ -7,8 +7,8 @@ module GitHub API_URL = "https://api.github.com".freeze CREATE_GIST_SCOPES = ["gist"].freeze - CREATE_ISSUE_SCOPES = ["public_repo"].freeze - ALL_SCOPES = (CREATE_GIST_SCOPES + CREATE_ISSUE_SCOPES).freeze + CREATE_ISSUE_FORK_OR_PR_SCOPES = ["public_repo"].freeze + ALL_SCOPES = (CREATE_GIST_SCOPES + CREATE_ISSUE_FORK_OR_PR_SCOPES).freeze ALL_SCOPES_URL = Formatter.url("https://github.com/settings/tokens/new?scopes=#{ALL_SCOPES.join(",")}&description=Homebrew").freeze Error = Class.new(RuntimeError) @@ -253,6 +253,20 @@ module GitHub prs.each { |i| puts "#{i["title"]} (#{i["html_url"]})" } end + def create_fork(repo) + url = "https://api.github.com/repos/#{repo}/forks" + data = {} + scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES + open_api(url, data: data, scopes: scopes) + end + + def create_pull_request(repo, title, head, base, body) + url = "https://api.github.com/repos/#{repo}/pulls" + data = { title: title, head: head, base: base, body: body } + scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES + open_api(url, data: data, scopes: scopes) + end + def private_repo?(full_name) uri = url_to "repos", full_name open_api(uri) { |json| json["private"] } From 010d593a8d0d4d5e4b2602613ce4bf1581ef8985 Mon Sep 17 00:00:00 2001 From: Mike McQuaid Date: Sun, 8 Apr 2018 15:37:16 -0700 Subject: [PATCH 2/2] bump-formula-pr: sleep for fork creation. --- Library/Homebrew/dev-cmd/bump-formula-pr.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Library/Homebrew/dev-cmd/bump-formula-pr.rb b/Library/Homebrew/dev-cmd/bump-formula-pr.rb index 9bc38c9bf2..b5c1dccdd7 100644 --- a/Library/Homebrew/dev-cmd/bump-formula-pr.rb +++ b/Library/Homebrew/dev-cmd/bump-formula-pr.rb @@ -334,6 +334,8 @@ module Homebrew begin response = GitHub.create_fork(formula.tap.full_name) + # GitHub API responds immediately but fork takes a few seconds to be ready. + sleep 3 rescue *gh_api_errors => e formula.path.atomic_write(backup_file) unless ARGV.dry_run? odie "Unable to fork: #{e.message}!"