Merge pull request #8410 from dawidd6/github-releases
Support bottle uploads to GitHub Releases
This commit is contained in:
commit
14741e3681
@ -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
|
|||||||
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
|
|||||||
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
|
|||||||
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 =
|
|||||||
%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
|
|||||||
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
|
|||||||
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
|
|||||||
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.
|
|||||||
|
|
||||||
### `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
|
|||||||
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
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user