Skip to content
Snippets Groups Projects
Unverified Commit 14741e36 authored by Dawid Dziurla's avatar Dawid Dziurla Committed by GitHub
Browse files

Merge pull request #8410 from dawidd6/github-releases

Support bottle uploads to GitHub Releases
parents fe40bd53 f6601cee
No related branches found
No related tags found
No related merge requests found
...@@ -148,11 +148,7 @@ class Bintray ...@@ -148,11 +148,7 @@ class Bintray
end end
end end
def upload_bottle_json(json_files, publish_package: false, warn_on_error: false) def upload_bottles(bottles_hash, publish_package: false, warn_on_error: false)
bottles_hash = json_files.reduce({}) do |hash, json_file|
hash.deep_merge(JSON.parse(IO.read(json_file)))
end
formula_packaged = {} formula_packaged = {}
bottles_hash.each do |formula_name, bottle_hash| bottles_hash.each do |formula_name, bottle_hash|
......
...@@ -11,7 +11,7 @@ module Homebrew ...@@ -11,7 +11,7 @@ module Homebrew
usage_banner <<~EOS usage_banner <<~EOS
`pr-upload` [<options>] `pr-upload` [<options>]
Apply the bottle commit and publish bottles to Bintray. Apply the bottle commit and publish bottles to Bintray or GitHub Releases.
EOS EOS
switch "--no-publish", switch "--no-publish",
description: "Apply the bottle commit and upload the bottles, but don't publish them." description: "Apply the bottle commit and upload the bottles, but don't publish them."
...@@ -30,30 +30,37 @@ module Homebrew ...@@ -30,30 +30,37 @@ module Homebrew
end end
end end
def check_bottled_formulae(json_files) def check_bottled_formulae(bottles_hash)
hashes = json_files.reduce({}) do |hash, json| bottles_hash.each do |name, bottle_hash|
hash.deep_merge(JSON.parse(IO.read(json))) formula_path = HOMEBREW_REPOSITORY/bottle_hash["formula"]["path"]
end
hashes.each do |name, hash|
formula_path = HOMEBREW_REPOSITORY/hash["formula"]["path"]
formula_version = Formulary.factory(formula_path).pkg_version formula_version = Formulary.factory(formula_path).pkg_version
bottle_version = PkgVersion.parse hash["formula"]["pkg_version"] bottle_version = PkgVersion.parse bottle_hash["formula"]["pkg_version"]
next if formula_version == bottle_version next if formula_version == bottle_version
odie "Bottles are for #{name} #{bottle_version} but formula is version #{formula_version}!" odie "Bottles are for #{name} #{bottle_version} but formula is version #{formula_version}!"
end end
end end
def github_releases?(bottles_hash)
@github_releases ||= bottles_hash.values.all? do |bottle_hash|
root_url = bottle_hash["bottle"]["root_url"]
url_match = root_url.match HOMEBREW_RELEASES_URL_REGEX
_, _, _, tag = *url_match
tag
end
end
def pr_upload def pr_upload
args = pr_upload_args.parse args = pr_upload_args.parse
bintray_org = args.bintray_org || "homebrew"
bintray = Bintray.new(org: bintray_org)
json_files = Dir["*.json"] json_files = Dir["*.json"]
odie "No JSON files found in the current working directory" if json_files.empty? odie "No JSON files found in the current working directory" if json_files.empty?
bottles_hash = json_files.reduce({}) do |hash, json_file|
hash.deep_merge(JSON.parse(IO.read(json_file)))
end
bottle_args = ["bottle", "--merge", "--write"] bottle_args = ["bottle", "--merge", "--write"]
bottle_args << "--verbose" if args.verbose? bottle_args << "--verbose" if args.verbose?
bottle_args << "--debug" if args.debug? bottle_args << "--debug" if args.debug?
...@@ -62,14 +69,51 @@ module Homebrew ...@@ -62,14 +69,51 @@ module Homebrew
bottle_args += json_files bottle_args += json_files
if args.dry_run? if args.dry_run?
service = if github_releases?(bottles_hash)
"GitHub Releases"
else
"Bintray"
end
puts "brew #{bottle_args.join " "}" puts "brew #{bottle_args.join " "}"
puts "Upload bottles described by these JSON files to Bintray:\n #{json_files.join("\n ")}" puts "Upload bottles described by these JSON files to #{service}:\n #{json_files.join("\n ")}"
return
end
check_bottled_formulae(bottles_hash)
safe_system HOMEBREW_BREW_FILE, *bottle_args
if github_releases?(bottles_hash)
# Handle uploading to GitHub Releases.
bottles_hash.each_value do |bottle_hash|
root_url = bottle_hash["bottle"]["root_url"]
url_match = root_url.match HOMEBREW_RELEASES_URL_REGEX
_, user, repo, tag = *url_match
# Ensure a release is created.
release = begin
GitHub.get_release user, repo, tag
odebug "Existing GitHub release \"#{tag}\" found"
rescue GitHub::HTTPNotFoundError
odebug "Creating new GitHub release \"#{tag}\""
GitHub.create_or_update_release user, repo, tag
end
# Upload bottles as release assets.
bottle_hash["bottle"]["tags"].each_value do |tag_hash|
remote_file = tag_hash["filename"]
local_file = tag_hash["local_filename"]
odebug "Uploading #{remote_file}"
GitHub.upload_release_asset user, repo, release["id"], local_file: local_file, remote_file: remote_file
end
end
else else
check_bottled_formulae(json_files) # Handle uploading to Bintray.
safe_system HOMEBREW_BREW_FILE, *bottle_args bintray_org = args.bintray_org || "homebrew"
bintray.upload_bottle_json(json_files, bintray = Bintray.new(org: bintray_org)
publish_package: !args.no_publish?, bintray.upload_bottles(bottles_hash,
warn_on_error: args.warn_on_upload_failure?) publish_package: !args.no_publish?,
warn_on_error: args.warn_on_upload_failure?)
end end
end end
end end
...@@ -112,6 +112,8 @@ HOMEBREW_PULL_API_REGEX = ...@@ -112,6 +112,8 @@ HOMEBREW_PULL_API_REGEX =
%r{https://api\.github\.com/repos/([\w-]+)/([\w-]+)?/pulls/(\d+)}.freeze %r{https://api\.github\.com/repos/([\w-]+)/([\w-]+)?/pulls/(\d+)}.freeze
HOMEBREW_PULL_OR_COMMIT_URL_REGEX = HOMEBREW_PULL_OR_COMMIT_URL_REGEX =
%r[https://github\.com/([\w-]+)/([\w-]+)?/(?:pull/(\d+)|commit/[0-9a-fA-F]{4,40})].freeze %r[https://github\.com/([\w-]+)/([\w-]+)?/(?:pull/(\d+)|commit/[0-9a-fA-F]{4,40})].freeze
HOMEBREW_RELEASES_URL_REGEX =
%r{https://github\.com/([\w-]+)/([\w-]+)?/releases/download/(.+)}.freeze
require "PATH" require "PATH"
......
...@@ -175,7 +175,7 @@ module GitHub ...@@ -175,7 +175,7 @@ module GitHub
end end
end end
def open_api(url, data: nil, request_method: nil, scopes: [].freeze, parse_json: true) def open_api(url, data: nil, data_binary_path: nil, request_method: nil, scopes: [].freeze, parse_json: true)
# This is a no-op if the user is opting out of using the GitHub API. # This is a no-op if the user is opting out of using the GitHub API.
return block_given? ? yield({}) : {} if Homebrew::EnvConfig.no_github_api? return block_given? ? yield({}) : {} if Homebrew::EnvConfig.no_github_api?
...@@ -200,6 +200,11 @@ module GitHub ...@@ -200,6 +200,11 @@ module GitHub
end end
end end
if data_binary_path.present?
args += ["--data-binary", "@#{data_binary_path}"]
args += ["--header", "Content-Type: application/gzip"]
end
headers_tmpfile = Tempfile.new("github_api_headers", HOMEBREW_TEMP) headers_tmpfile = Tempfile.new("github_api_headers", HOMEBREW_TEMP)
begin begin
if data if data
...@@ -468,6 +473,33 @@ module GitHub ...@@ -468,6 +473,33 @@ module GitHub
scopes: CREATE_ISSUE_FORK_OR_PR_SCOPES) scopes: CREATE_ISSUE_FORK_OR_PR_SCOPES)
end end
def get_release(user, repo, tag)
url = "#{API_URL}/repos/#{user}/#{repo}/releases/tags/#{tag}"
open_api(url, request_method: :GET)
end
def create_or_update_release(user, repo, tag, id: nil, name: nil, draft: false)
url = "#{API_URL}/repos/#{user}/#{repo}/releases"
method = if id
url += "/#{id}"
:PATCH
else
:POST
end
data = {
tag_name: tag,
name: name || tag,
draft: draft,
}
open_api(url, data: data, request_method: method, scopes: CREATE_ISSUE_FORK_OR_PR_SCOPES)
end
def upload_release_asset(user, repo, id, local_file: nil, remote_file: nil)
url = "https://uploads.github.com/repos/#{user}/#{repo}/releases/#{id}/assets"
url += "?name=#{remote_file}" if remote_file
open_api(url, data_binary_path: local_file, request_method: :POST, scopes: CREATE_ISSUE_FORK_OR_PR_SCOPES)
end
def get_artifact_url(user, repo, pr, workflow_id: "tests.yml", artifact_name: "bottles") def get_artifact_url(user, repo, pr, workflow_id: "tests.yml", artifact_name: "bottles")
scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES scopes = CREATE_ISSUE_FORK_OR_PR_SCOPES
base_url = "#{API_URL}/repos/#{user}/#{repo}" base_url = "#{API_URL}/repos/#{user}/#{repo}"
......
...@@ -1113,7 +1113,7 @@ Requires write access to the repository. ...@@ -1113,7 +1113,7 @@ Requires write access to the repository.
### `pr-upload` [*`options`*] ### `pr-upload` [*`options`*]
Apply the bottle commit and publish bottles to Bintray. Apply the bottle commit and publish bottles to Bintray or GitHub Releases.
* `--no-publish`: * `--no-publish`:
Apply the bottle commit and upload the bottles, but don't publish them. Apply the bottle commit and upload the bottles, but don't publish them.
......
...@@ -1547,7 +1547,7 @@ Use the specified \fIURL\fR as the root of the bottle\'s URL instead of Homebrew ...@@ -1547,7 +1547,7 @@ Use the specified \fIURL\fR as the root of the bottle\'s URL instead of Homebrew
Use the specified Bintray repository to automatically mirror stable URLs defined in the formulae (default: \fBmirror\fR)\. Use the specified Bintray repository to automatically mirror stable URLs defined in the formulae (default: \fBmirror\fR)\.
. .
.SS "\fBpr\-upload\fR [\fIoptions\fR]" .SS "\fBpr\-upload\fR [\fIoptions\fR]"
Apply the bottle commit and publish bottles to Bintray\. Apply the bottle commit and publish bottles to Bintray or GitHub Releases\.
. .
.TP .TP
\fB\-\-no\-publish\fR \fB\-\-no\-publish\fR
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment