Merge pull request #5085 from alyssais/bump_formula_pr-no_fork

bump-formula-pr: gracefully handle unforkable repositories
This commit is contained in:
Mike McQuaid 2018-10-12 11:05:08 +01:00 committed by GitHub
commit 662641557e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 25 deletions

View File

@ -345,7 +345,7 @@ module Homebrew
shallow = !git_dir.empty? && File.exist?("#{git_dir}/shallow") shallow = !git_dir.empty? && File.exist?("#{git_dir}/shallow")
if args.dry_run? if args.dry_run?
ohai "fork repository with GitHub API" ohai "try to fork repository with GitHub API"
ohai "git fetch --unshallow origin" if shallow ohai "git fetch --unshallow origin" if shallow
ohai "git checkout --no-track -b #{branch} origin/master" ohai "git checkout --no-track -b #{branch} origin/master"
ohai "git commit --no-edit --verbose --message='#{formula.name} " \ ohai "git commit --no-edit --verbose --message='#{formula.name} " \
@ -359,18 +359,24 @@ module Homebrew
response = GitHub.create_fork(formula.tap.full_name) response = GitHub.create_fork(formula.tap.full_name)
# GitHub API responds immediately but fork takes a few seconds to be ready. # GitHub API responds immediately but fork takes a few seconds to be ready.
sleep 3 sleep 3
if system("git", "config", "--local", "--get-regexp", "remote\..*\.url", "git@github.com:.*")
remote_url = response.fetch("ssh_url")
else
remote_url = response.fetch("clone_url")
end
username = response.fetch("owner").fetch("login")
rescue GitHub::AuthenticationFailedError => e
raise unless e.github_message =~ /forking is disabled/
# If the repository is private, forking might be disabled.
# Create branches in the repository itself instead.
remote_url = Utils.popen_read("git remote get-url --push origin").chomp
username = formula.tap.user
rescue *GitHub.api_errors => e rescue *GitHub.api_errors => e
formula.path.atomic_write(backup_file) unless args.dry_run? formula.path.atomic_write(backup_file) unless args.dry_run?
odie "Unable to fork: #{e.message}!" odie "Unable to fork: #{e.message}!"
end end
if system("git", "config", "--local", "--get-regexp", "remote\..*\.url", "git@github.com:.*")
remote_url = response.fetch("ssh_url")
else
remote_url = response.fetch("clone_url")
end
username = response.fetch("owner").fetch("login")
safe_system "git", "fetch", "--unshallow", "origin" if shallow safe_system "git", "fetch", "--unshallow", "origin" if shallow
safe_system "git", "checkout", "--no-track", "-b", branch, "origin/master" safe_system "git", "checkout", "--no-track", "-b", branch, "origin/master"
safe_system "git", "commit", "--no-edit", "--verbose", safe_system "git", "commit", "--no-edit", "--verbose",

View File

@ -15,13 +15,22 @@ module GitHub
PR_ENV_KEY = "HOMEBREW_NEW_FORMULA_PULL_REQUEST_URL".freeze PR_ENV_KEY = "HOMEBREW_NEW_FORMULA_PULL_REQUEST_URL".freeze
PR_ENV = ENV[PR_ENV_KEY] PR_ENV = ENV[PR_ENV_KEY]
Error = Class.new(RuntimeError) class Error < RuntimeError
HTTPNotFoundError = Class.new(Error) attr_reader :github_message
end
class HTTPNotFoundError < Error
def initialize(github_message)
@github_message = github_message
super
end
end
class RateLimitExceededError < Error class RateLimitExceededError < Error
def initialize(reset, error) def initialize(reset, github_message)
@github_message = github_message
super <<~EOS super <<~EOS
GitHub API Error: #{error} GitHub API Error: #{github_message}
Try again in #{pretty_ratelimit_reset(reset)}, or create a personal access token: Try again in #{pretty_ratelimit_reset(reset)}, or create a personal access token:
#{ALL_SCOPES_URL} #{ALL_SCOPES_URL}
and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token" and then set the token as: export HOMEBREW_GITHUB_API_TOKEN="your_new_token"
@ -34,8 +43,9 @@ module GitHub
end end
class AuthenticationFailedError < Error class AuthenticationFailedError < Error
def initialize(error) def initialize(github_message)
message = "GitHub #{error}\n" @github_message = github_message
message = "GitHub #{github_message}\n"
if ENV["HOMEBREW_GITHUB_API_TOKEN"] if ENV["HOMEBREW_GITHUB_API_TOKEN"]
message << <<~EOS message << <<~EOS
HOMEBREW_GITHUB_API_TOKEN may be invalid or expired; check: HOMEBREW_GITHUB_API_TOKEN may be invalid or expired; check:
@ -193,6 +203,13 @@ module GitHub
end end
def raise_api_error(output, errors, http_code, headers, scopes) def raise_api_error(output, errors, http_code, headers, scopes)
json = begin
JSON.parse(output)
rescue
nil
end
message = json&.[]("message") || "curl failed! #{errors}"
meta = {} meta = {}
headers.lines.each do |l| headers.lines.each do |l|
key, _, value = l.delete(":").partition(" ") key, _, value = l.delete(":").partition(" ")
@ -204,25 +221,18 @@ module GitHub
if meta.fetch("x-ratelimit-remaining", 1).to_i <= 0 if meta.fetch("x-ratelimit-remaining", 1).to_i <= 0
reset = meta.fetch("x-ratelimit-reset").to_i reset = meta.fetch("x-ratelimit-reset").to_i
error = JSON.parse(output)["message"] raise RateLimitExceededError.new(reset, message)
raise RateLimitExceededError.new(reset, error)
end end
GitHub.api_credentials_error_message(meta, scopes) GitHub.api_credentials_error_message(meta, scopes)
case http_code case http_code
when "401", "403" when "401", "403"
raise AuthenticationFailedError, output raise AuthenticationFailedError, message
when "404" when "404"
raise HTTPNotFoundError, output raise HTTPNotFoundError, message
else else
error = begin raise Error, message
JSON.parse(output)["message"]
rescue
nil
end
error ||= "curl failed! #{errors}"
raise Error, error
end end
end end