Merge pull request #7347 from jonchang/jumbo-bottles-fix

pr-pull: eliminate another curl call
This commit is contained in:
Jonathan Chang 2020-04-14 19:31:59 +10:00 committed by GitHub
commit bd75fd1c9b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 64 additions and 40 deletions

View File

@ -1,18 +1,11 @@
# frozen_string_literal: true
require "download_strategy"
require "cli/parser"
require "utils/github"
require "tmpdir"
require "bintray"
class CurlNoResumeDownloadStrategy < CurlDownloadStrategy
private
def _fetch(url:, resolved_url:)
curl("--location", "--remote-time", "--create-dirs", "--output", temporary_path, resolved_url)
end
end
module Homebrew
module_function
@ -148,6 +141,27 @@ module Homebrew
nil
end
def download_artifact(url, dir, pr)
token, username = GitHub.api_credentials
case GitHub.api_credentials_type
when :env_username_password, :keychain_username_password
curl_args = ["--user", "#{username}:#{token}"]
when :env_token
curl_args = ["--header", "Authorization: token #{token}"]
when :none
raise Error, "Credentials must be set to access the Artifacts API"
end
# Download the artifact as a zip file and unpack it into `dir`. This is
# preferred over system `curl` and `tar` as this leverages the Homebrew
# cache to avoid repeated downloads of (possibly large) bottles.
FileUtils.chdir dir do
downloader = GitHubArtifactDownloadStrategy.new(url, "artifact", pr, curl_args: curl_args, secrets: [token])
downloader.fetch
downloader.stage
end
end
def pr_pull
pr_pull_args.parse
@ -163,7 +177,7 @@ module Homebrew
workflow = args.workflow || "tests.yml"
artifact = args.artifact || "bottles"
tap = Tap.fetch(args.tap || "homebrew/core")
tap = Tap.fetch(args.tap || CoreTap.instance.name)
setup_git_environment!
@ -187,9 +201,8 @@ module Homebrew
next
end
GitHub.fetch_artifact(user, repo, pr, dir, workflow_id: workflow,
artifact_name: artifact,
strategy: CurlNoResumeDownloadStrategy)
url = GitHub.get_artifact_url(user, repo, pr, workflow_id: workflow, artifact_name: artifact)
download_artifact(url, dir, pr)
if Homebrew.args.dry_run?
puts "brew bottle --merge --write #{Dir["*.json"].join " "}"
@ -209,3 +222,32 @@ module Homebrew
end
end
end
class GitHubArtifactDownloadStrategy < AbstractFileDownloadStrategy
def fetch
ohai "Downloading #{url}"
if cached_location.exist?
puts "Already downloaded: #{cached_location}"
else
begin
curl "--location", "--create-dirs", "--output", temporary_path, url,
*meta.fetch(:curl_args, []),
secrets: meta.fetch(:secrets, [])
rescue ErrorDuringExecution
raise CurlDownloadStrategyError, url
end
ignore_interrupts do
cached_location.dirname.mkpath
temporary_path.rename(cached_location)
symlink_location.dirname.mkpath
end
end
FileUtils.ln_s cached_location.relative_path_from(symlink_location.dirname), symlink_location, force: true
end
private
def resolved_basename
"artifact.zip"
end
end

View File

@ -42,17 +42,22 @@ describe GitHub do
end
end
describe "::fetch_artifact", :needs_network do
describe "::get_artifact_url", :needs_network do
it "fails to find a nonexistant workflow" do
expect {
subject.fetch_artifact("Homebrew", "homebrew-core", 1, ".")
subject.get_artifact_url("Homebrew", "homebrew-core", 1)
}.to raise_error(/No matching workflow run found/)
end
it "fails to find artifacts that don't exist" do
expect {
subject.fetch_artifact("Homebrew", "homebrew-core", 51971, ".", artifact_name: "false_bottles")
subject.get_artifact_url("Homebrew", "homebrew-core", 51971, artifact_name: "false_bottles")
}.to raise_error(/No artifact .+ was found/)
end
it "gets an artifact link" do
url = subject.get_artifact_url("Homebrew", "homebrew-core", 51971, artifact_name: "bottles")
expect(url).to eq("https://api.github.com/repos/Homebrew/homebrew-core/actions/artifacts/3557392/zip")
end
end
end

View File

@ -1,6 +1,5 @@
# frozen_string_literal: true
require "download_strategy"
require "tempfile"
require "uri"
@ -435,8 +434,7 @@ module GitHub
scopes: CREATE_ISSUE_FORK_OR_PR_SCOPES)
end
def fetch_artifact(user, repo, pr, dir,
workflow_id: "tests.yml", artifact_name: "bottles", strategy: CurlDownloadStrategy)
def get_artifact_url(user, repo, pr, workflow_id: "tests.yml", artifact_name: "bottles")
scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES
base_url = "#{API_URL}/repos/#{user}/#{repo}"
pr_payload = open_api("#{base_url}/pulls/#{pr}", scopes: scopes)
@ -479,28 +477,7 @@ module GitHub
EOS
end
artifact_url = artifact.first["archive_download_url"]
token, username = api_credentials
case api_credentials_type
when :env_username_password, :keychain_username_password
curl_args = { user: "#{username}:#{token}" }
when :env_token
curl_args = { header: "Authorization: token #{token}" }
when :none
raise Error, "Credentials must be set to access the Artifacts API"
end
# Download the artifact as a zip file and unpack it into `dir`. This is
# preferred over system `curl` and `tar` as this leverages the Homebrew
# cache to avoid repeated downloads of (possibly large) bottles.
FileUtils.chdir dir do
curl_args[:cache] = Pathname.new(dir)
curl_args[:secrets] = [token]
downloader = strategy.new(artifact_url, "artifact", pr, **curl_args)
downloader.fetch
downloader.stage
end
artifact.first["archive_download_url"]
end
def api_errors