2020-10-10 14:16:11 +02:00
|
|
|
# typed: false
|
2020-04-20 10:17:42 +02:00
|
|
|
# frozen_string_literal: true
|
|
|
|
|
|
|
|
require "cli/parser"
|
2021-02-21 22:12:17 -08:00
|
|
|
require "archive"
|
2020-04-20 10:17:42 +02:00
|
|
|
require "bintray"
|
2021-03-11 15:15:35 +00:00
|
|
|
require "github_packages"
|
2021-03-10 16:08:45 +00:00
|
|
|
require "github_releases"
|
2020-04-20 10:17:42 +02:00
|
|
|
|
|
|
|
module Homebrew
|
2020-10-20 12:03:48 +02:00
|
|
|
extend T::Sig
|
|
|
|
|
2020-04-20 10:17:42 +02:00
|
|
|
module_function
|
|
|
|
|
2020-10-20 12:03:48 +02:00
|
|
|
sig { returns(CLI::Parser) }
|
2020-04-20 10:17:42 +02:00
|
|
|
def pr_upload_args
|
|
|
|
Homebrew::CLI::Parser.new do
|
2021-01-15 15:04:02 -05:00
|
|
|
description <<~EOS
|
2021-03-10 16:08:45 +00:00
|
|
|
Apply the bottle commit and publish bottles to a host.
|
2020-04-20 10:17:42 +02:00
|
|
|
EOS
|
|
|
|
switch "--no-publish",
|
|
|
|
description: "Apply the bottle commit and upload the bottles, but don't publish them."
|
2020-07-06 17:41:07 +02:00
|
|
|
switch "--keep-old",
|
|
|
|
description: "If the formula specifies a rebuild version, " \
|
|
|
|
"attempt to preserve its value in the generated DSL."
|
2020-06-25 12:01:52 -04:00
|
|
|
switch "-n", "--dry-run",
|
2020-04-20 10:17:42 +02:00
|
|
|
description: "Print what would be done rather than doing it."
|
2020-10-03 12:33:47 -04:00
|
|
|
switch "--no-commit",
|
|
|
|
description: "Do not generate a new commit before uploading."
|
2020-07-02 00:11:55 +10:00
|
|
|
switch "--warn-on-upload-failure",
|
|
|
|
description: "Warn instead of raising an error if the bottle upload fails. "\
|
|
|
|
"Useful for repairing bottle uploads that previously failed."
|
2021-04-01 16:23:39 +05:30
|
|
|
flag "--committer=",
|
|
|
|
description: "Specify a committer name and email in `git`'s standard author format."
|
2021-02-21 22:12:17 -08:00
|
|
|
flag "--archive-item=",
|
2021-02-23 11:22:55 -08:00
|
|
|
description: "Upload to the specified Internet Archive item (default: `homebrew`)."
|
2020-06-25 12:01:52 -04:00
|
|
|
flag "--bintray-org=",
|
|
|
|
description: "Upload to the specified Bintray organisation (default: `homebrew`)."
|
2021-03-11 15:15:35 +00:00
|
|
|
flag "--github-org=",
|
|
|
|
description: "Upload to the specified GitHub organisation's GitHub Packages (default: `homebrew`)."
|
2020-06-25 12:01:52 -04:00
|
|
|
flag "--root-url=",
|
|
|
|
description: "Use the specified <URL> as the root of the bottle's URL instead of Homebrew's default."
|
2021-04-28 14:57:41 -04:00
|
|
|
flag "--root-url-using=",
|
2021-04-29 10:13:53 -04:00
|
|
|
description: "Use the specified download strategy class for downloading the bottle's URL instead of Homebrew's default."
|
2021-01-10 14:26:40 -05:00
|
|
|
|
|
|
|
named_args :none
|
2020-04-20 10:17:42 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-04-21 17:10:05 +01:00
|
|
|
def check_bottled_formulae!(bottles_hash)
|
2020-08-20 14:21:55 +02:00
|
|
|
bottles_hash.each do |name, bottle_hash|
|
|
|
|
formula_path = HOMEBREW_REPOSITORY/bottle_hash["formula"]["path"]
|
2020-07-29 09:22:09 +02:00
|
|
|
formula_version = Formulary.factory(formula_path).pkg_version
|
2020-08-20 14:21:55 +02:00
|
|
|
bottle_version = PkgVersion.parse bottle_hash["formula"]["pkg_version"]
|
2020-07-26 21:46:37 +10:00
|
|
|
next if formula_version == bottle_version
|
|
|
|
|
|
|
|
odie "Bottles are for #{name} #{bottle_version} but formula is version #{formula_version}!"
|
2020-07-26 19:03:02 +10:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-03-10 16:08:45 +00:00
|
|
|
def internet_archive?(bottles_hash)
|
|
|
|
@internet_archive ||= bottles_hash.values.all? do |bottle_hash|
|
|
|
|
bottle_hash["bottle"]["root_url"].start_with? "#{Archive::URL_PREFIX}/"
|
2021-02-21 22:12:17 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
def bintray?(bottles_hash)
|
|
|
|
@bintray ||= bottles_hash.values.all? do |bottle_hash|
|
2021-03-10 16:08:45 +00:00
|
|
|
bottle_hash["bottle"]["root_url"].match? Bintray::URL_REGEX
|
2021-02-21 22:12:17 -08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2020-08-20 14:21:55 +02:00
|
|
|
def github_releases?(bottles_hash)
|
|
|
|
@github_releases ||= bottles_hash.values.all? do |bottle_hash|
|
|
|
|
root_url = bottle_hash["bottle"]["root_url"]
|
2021-03-10 16:08:45 +00:00
|
|
|
url_match = root_url.match GitHubReleases::URL_REGEX
|
2020-08-20 14:21:55 +02:00
|
|
|
_, _, _, tag = *url_match
|
|
|
|
|
|
|
|
tag
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-03-11 15:15:35 +00:00
|
|
|
def github_packages?(bottles_hash)
|
|
|
|
@github_packages ||= bottles_hash.values.all? do |bottle_hash|
|
|
|
|
bottle_hash["bottle"]["root_url"].match? GitHubPackages::URL_REGEX
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-04-29 14:48:45 +01:00
|
|
|
def bottles_hash_from_json_files(json_files, args)
|
2021-04-28 12:48:24 +01:00
|
|
|
puts "Reading JSON files: #{json_files.join(", ")}" if args.verbose?
|
2020-07-26 19:03:02 +10:00
|
|
|
|
2020-08-20 14:21:55 +02:00
|
|
|
bottles_hash = json_files.reduce({}) do |hash, json_file|
|
2021-04-14 12:42:26 +01:00
|
|
|
hash.deep_merge(JSON.parse(File.read(json_file)))
|
2020-08-20 14:21:55 +02:00
|
|
|
end
|
|
|
|
|
2021-04-28 12:48:24 +01:00
|
|
|
if args.root_url
|
2021-03-30 17:35:13 +01:00
|
|
|
bottles_hash.each_value do |bottle_hash|
|
2021-04-28 12:48:24 +01:00
|
|
|
bottle_hash["bottle"]["root_url"] = args.root_url
|
2021-03-30 17:35:13 +01:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2021-04-29 14:48:45 +01:00
|
|
|
bottles_hash
|
2021-04-21 17:10:05 +01:00
|
|
|
end
|
|
|
|
|
|
|
|
def pr_upload
|
|
|
|
args = pr_upload_args.parse
|
|
|
|
|
2021-04-29 14:48:45 +01:00
|
|
|
json_files = Dir["*.bottle.json"]
|
|
|
|
odie "No bottle JSON files found in the current working directory" if json_files.blank?
|
|
|
|
bottles_hash = bottles_hash_from_json_files(json_files, args)
|
2021-04-21 17:10:05 +01:00
|
|
|
|
2020-04-20 10:31:59 -07:00
|
|
|
bottle_args = ["bottle", "--merge", "--write"]
|
2020-06-22 00:21:22 +10:00
|
|
|
bottle_args << "--verbose" if args.verbose?
|
|
|
|
bottle_args << "--debug" if args.debug?
|
2020-07-06 17:41:07 +02:00
|
|
|
bottle_args << "--keep-old" if args.keep_old?
|
2020-04-20 10:31:59 -07:00
|
|
|
bottle_args << "--root-url=#{args.root_url}" if args.root_url
|
2021-04-02 00:17:43 +02:00
|
|
|
bottle_args << "--committer=#{args.committer}" if args.committer
|
2020-10-03 12:33:47 -04:00
|
|
|
bottle_args << "--no-commit" if args.no_commit?
|
2021-04-28 14:57:41 -04:00
|
|
|
bottle_args << "--root-url-using=#{args.root_url_using}" if args.root_url_using
|
2020-07-26 19:03:02 +10:00
|
|
|
bottle_args += json_files
|
2020-04-20 10:31:59 -07:00
|
|
|
|
2020-04-20 10:17:42 +02:00
|
|
|
if args.dry_run?
|
2021-03-30 08:42:15 +01:00
|
|
|
dry_run_service = if github_packages?(bottles_hash)
|
|
|
|
# GitHub Packages has its own --dry-run handling.
|
|
|
|
nil
|
|
|
|
elsif internet_archive?(bottles_hash)
|
|
|
|
"Internet Archive"
|
|
|
|
elsif bintray?(bottles_hash)
|
|
|
|
"Bintray"
|
|
|
|
elsif github_releases?(bottles_hash)
|
|
|
|
"GitHub Releases"
|
|
|
|
else
|
|
|
|
odie "Service specified by root_url is not recognized"
|
|
|
|
end
|
|
|
|
|
|
|
|
if dry_run_service
|
|
|
|
puts <<~EOS
|
|
|
|
brew #{bottle_args.join " "}
|
|
|
|
Upload bottles described by these JSON files to #{dry_run_service}:
|
|
|
|
#{json_files.join("\n ")}
|
|
|
|
EOS
|
|
|
|
return
|
|
|
|
end
|
2020-08-20 14:21:55 +02:00
|
|
|
end
|
|
|
|
|
2021-04-21 17:10:05 +01:00
|
|
|
check_bottled_formulae!(bottles_hash)
|
2020-08-20 14:21:55 +02:00
|
|
|
|
|
|
|
safe_system HOMEBREW_BREW_FILE, *bottle_args
|
|
|
|
|
2021-04-29 14:48:45 +01:00
|
|
|
json_files = Dir["*.bottle.json"]
|
|
|
|
if json_files.blank?
|
|
|
|
puts "No bottle JSON files after merge, no upload needed!"
|
|
|
|
return
|
|
|
|
end
|
|
|
|
|
2021-04-21 17:10:05 +01:00
|
|
|
# Reload the JSON files (in case `brew bottle --merge` generated
|
|
|
|
# `all: $SHA256` bottles)
|
2021-04-29 14:48:45 +01:00
|
|
|
bottles_hash = bottles_hash_from_json_files(json_files, args)
|
2021-04-21 17:10:05 +01:00
|
|
|
|
2020-11-09 09:59:59 +00:00
|
|
|
# Check the bottle commits did not break `brew audit`
|
|
|
|
unless args.no_commit?
|
2020-11-09 13:49:40 +00:00
|
|
|
audit_args = ["audit", "--skip-style"]
|
2020-11-09 09:59:59 +00:00
|
|
|
audit_args << "--verbose" if args.verbose?
|
|
|
|
audit_args << "--debug" if args.debug?
|
2020-11-12 20:04:20 +01:00
|
|
|
audit_args += bottles_hash.keys
|
2020-11-09 09:59:59 +00:00
|
|
|
safe_system HOMEBREW_BREW_FILE, *audit_args
|
|
|
|
end
|
|
|
|
|
2021-03-10 16:08:45 +00:00
|
|
|
if internet_archive?(bottles_hash)
|
2021-02-21 22:12:17 -08:00
|
|
|
archive_item = args.archive_item || "homebrew"
|
|
|
|
archive = Archive.new(item: archive_item)
|
|
|
|
archive.upload_bottles(bottles_hash,
|
|
|
|
warn_on_error: args.warn_on_upload_failure?)
|
|
|
|
elsif bintray?(bottles_hash)
|
2021-04-12 14:48:58 +01:00
|
|
|
odeprecated "brew pr-upload for Bintray (Bintray will be shut down on 1st May 2021)"
|
|
|
|
|
2021-02-21 22:12:17 -08:00
|
|
|
bintray_org = args.bintray_org || "homebrew"
|
|
|
|
bintray = Bintray.new(org: bintray_org)
|
|
|
|
bintray.upload_bottles(bottles_hash,
|
|
|
|
publish_package: !args.no_publish?,
|
|
|
|
warn_on_error: args.warn_on_upload_failure?)
|
|
|
|
elsif github_releases?(bottles_hash)
|
2021-03-10 16:08:45 +00:00
|
|
|
github_releases = GitHubReleases.new
|
|
|
|
github_releases.upload_bottles(bottles_hash)
|
2021-03-11 15:15:35 +00:00
|
|
|
elsif github_packages?(bottles_hash)
|
|
|
|
github_org = args.github_org || "homebrew"
|
|
|
|
github_packages = GitHubPackages.new(org: github_org)
|
2021-04-07 12:48:31 +01:00
|
|
|
github_packages.upload_bottles(bottles_hash,
|
2021-04-09 16:39:28 +01:00
|
|
|
keep_old: args.keep_old?,
|
2021-04-07 12:48:31 +01:00
|
|
|
dry_run: args.dry_run?,
|
|
|
|
warn_on_error: args.warn_on_upload_failure?)
|
2020-04-20 10:17:42 +02:00
|
|
|
else
|
2021-02-21 22:12:17 -08:00
|
|
|
odie "Service specified by root_url is not recognized"
|
2020-04-20 10:17:42 +02:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end
|