Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Convert remaining dev commands to use AbstractCommand #16938

Merged
merged 16 commits into from
Mar 22, 2024
Merged
1 change: 1 addition & 0 deletions Library/Homebrew/dev-cmd/bottle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# frozen_string_literal: true

require "abstract_command"
require "fileutils"
require "formula"
require "utils/bottles"
require "tab"
Expand Down
1 change: 1 addition & 0 deletions Library/Homebrew/dev-cmd/bump-formula-pr.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
# frozen_string_literal: true

require "abstract_command"
require "fileutils"
require "formula"
require "cli/parser"
require "utils/pypi"
Expand Down
1 change: 1 addition & 0 deletions Library/Homebrew/dev-cmd/cat.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

require "abstract_command"
require "cli/parser"
require "fileutils"

module Homebrew
module DevCmd
Expand Down
1 change: 1 addition & 0 deletions Library/Homebrew/dev-cmd/generate-cask-api.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
require "abstract_command"
require "cli/parser"
require "cask/cask"
require "fileutils"
require "formula"

module Homebrew
Expand Down
2 changes: 2 additions & 0 deletions Library/Homebrew/dev-cmd/generate-formula-api.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
# typed: true
# frozen_string_literal: true

require "abstract_command"
require "cli/parser"
require "fileutils"
require "formula"

module Homebrew
Expand Down
904 changes: 457 additions & 447 deletions Library/Homebrew/dev-cmd/pr-pull.rb

Large diffs are not rendered by default.

273 changes: 137 additions & 136 deletions Library/Homebrew/dev-cmd/pr-upload.rb
Original file line number Diff line number Diff line change
@@ -1,166 +1,167 @@
# typed: true
# frozen_string_literal: true

require "abstract_command"
require "cli/parser"
require "formula"
require "github_packages"
require "github_releases"
require "extend/hash/deep_merge"

module Homebrew
module_function

sig { returns(CLI::Parser) }
def pr_upload_args
Homebrew::CLI::Parser.new do
description <<~EOS
Apply the bottle commit and publish bottles to a host.
EOS
switch "--keep-old",
description: "If the formula specifies a rebuild version, " \
"attempt to preserve its value in the generated DSL."
switch "-n", "--dry-run",
description: "Print what would be done rather than doing it."
switch "--no-commit",
description: "Do not generate a new commit before uploading."
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."
switch "--upload-only",
description: "Skip running `brew bottle` before uploading."
flag "--committer=",
description: "Specify a committer name and email in `git`'s standard author format."
flag "--root-url=",
description: "Use the specified <URL> as the root of the bottle's URL instead of Homebrew's default."
flag "--root-url-using=",
description: "Use the specified download strategy class for downloading the bottle's URL instead of " \
"Homebrew's default."

conflicts "--upload-only", "--keep-old"
conflicts "--upload-only", "--no-commit"

named_args :none
end
end

def check_bottled_formulae!(bottles_hash)
bottles_hash.each do |name, bottle_hash|
formula_path = HOMEBREW_REPOSITORY/bottle_hash["formula"]["path"]
formula_version = Formulary.factory(formula_path).pkg_version
bottle_version = PkgVersion.parse bottle_hash["formula"]["pkg_version"]
next if formula_version == bottle_version

odie "Bottles are for #{name} #{bottle_version} but formula is version #{formula_version}!"
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 GitHubReleases::URL_REGEX
_, _, _, tag = *url_match
module DevCmd
class PrUpload < AbstractCommand
cmd_args do
description <<~EOS
Apply the bottle commit and publish bottles to a host.
EOS
switch "--keep-old",
description: "If the formula specifies a rebuild version, " \
"attempt to preserve its value in the generated DSL."
switch "-n", "--dry-run",
description: "Print what would be done rather than doing it."
switch "--no-commit",
description: "Do not generate a new commit before uploading."
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."
switch "--upload-only",
description: "Skip running `brew bottle` before uploading."
flag "--committer=",
description: "Specify a committer name and email in `git`'s standard author format."
flag "--root-url=",
description: "Use the specified <URL> as the root of the bottle's URL instead of Homebrew's default."
flag "--root-url-using=",
description: "Use the specified download strategy class for downloading the bottle's URL instead of " \
"Homebrew's default."

conflicts "--upload-only", "--keep-old"
conflicts "--upload-only", "--no-commit"

named_args :none
end

tag
end
end
sig { override.void }
def run
json_files = Dir["*.bottle.json"]

Check warning on line 46 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L46

Added line #L46 was not covered by tests
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)

Check warning on line 48 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L48

Added line #L48 was not covered by tests

Homebrew.install_bundler_gems!(groups: ["pr_upload"])

Check warning on line 50 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L50

Added line #L50 was not covered by tests

unless args.upload_only?
bottle_args = ["bottle", "--merge", "--write"]
bottle_args << "--verbose" if args.verbose?
bottle_args << "--debug" if args.debug?
bottle_args << "--keep-old" if args.keep_old?
bottle_args << "--root-url=#{args.root_url}" if args.root_url
bottle_args << "--committer=#{args.committer}" if args.committer
bottle_args << "--no-commit" if args.no_commit?
bottle_args << "--root-url-using=#{args.root_url_using}" if args.root_url_using
bottle_args += json_files

Check warning on line 61 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L61

Added line #L61 was not covered by tests

if args.dry_run?
dry_run_service = if github_packages?(bottles_hash)
# GitHub Packages has its own --dry-run handling.
nil
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

Check warning on line 79 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L79

Added line #L79 was not covered by tests
end
end

check_bottled_formulae!(bottles_hash)

Check warning on line 83 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L83

Added line #L83 was not covered by tests

safe_system HOMEBREW_BREW_FILE, *bottle_args

Check warning on line 85 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L85

Added line #L85 was not covered by tests

json_files = Dir["*.bottle.json"]

Check warning on line 87 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L87

Added line #L87 was not covered by tests
if json_files.blank?
puts "No bottle JSON files after merge, no upload needed!"
return

Check warning on line 90 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L90

Added line #L90 was not covered by tests
end

# Reload the JSON files (in case `brew bottle --merge` generated
# `all: $SHA256` bottles)
bottles_hash = bottles_hash_from_json_files(json_files, args)

Check warning on line 95 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L95

Added line #L95 was not covered by tests

# Check the bottle commits did not break `brew audit`
unless args.no_commit?
audit_args = ["audit", "--skip-style"]
audit_args << "--verbose" if args.verbose?
audit_args << "--debug" if args.debug?
audit_args += bottles_hash.keys
safe_system HOMEBREW_BREW_FILE, *audit_args

Check warning on line 103 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L102-L103

Added lines #L102 - L103 were not covered by tests
end
end

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
if github_releases?(bottles_hash)

Check warning on line 107 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L107

Added line #L107 was not covered by tests
github_releases = GitHubReleases.new
github_releases.upload_bottles(bottles_hash)

Check warning on line 109 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L109

Added line #L109 was not covered by tests
elsif github_packages?(bottles_hash)
github_packages = GitHubPackages.new
github_packages.upload_bottles(bottles_hash,

Check warning on line 112 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L112

Added line #L112 was not covered by tests
keep_old: args.keep_old?,
dry_run: args.dry_run?,
warn_on_error: args.warn_on_upload_failure?)
else
odie "Service specified by root_url is not recognized"
end
end

def bottles_hash_from_json_files(json_files, args)
puts "Reading JSON files: #{json_files.join(", ")}" if args.verbose?
private

bottles_hash = json_files.reduce({}) do |hash, json_file|
hash.deep_merge(JSON.parse(File.read(json_file)))
end
def check_bottled_formulae!(bottles_hash)
bottles_hash.each do |name, bottle_hash|
formula_path = HOMEBREW_REPOSITORY/bottle_hash["formula"]["path"]
formula_version = Formulary.factory(formula_path).pkg_version
bottle_version = PkgVersion.parse bottle_hash["formula"]["pkg_version"]

Check warning on line 127 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L124-L127

Added lines #L124 - L127 were not covered by tests
next if formula_version == bottle_version

if args.root_url
bottles_hash.each_value do |bottle_hash|
bottle_hash["bottle"]["root_url"] = args.root_url
odie "Bottles are for #{name} #{bottle_version} but formula is version #{formula_version}!"

Check warning on line 130 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L130

Added line #L130 was not covered by tests
end
end
end

bottles_hash
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 GitHubReleases::URL_REGEX
_, _, _, tag = *url_match

Check warning on line 138 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L135-L138

Added lines #L135 - L138 were not covered by tests

def pr_upload
args = pr_upload_args.parse

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)

Homebrew.install_bundler_gems!(groups: ["pr_upload"])

unless args.upload_only?
bottle_args = ["bottle", "--merge", "--write"]
bottle_args << "--verbose" if args.verbose?
bottle_args << "--debug" if args.debug?
bottle_args << "--keep-old" if args.keep_old?
bottle_args << "--root-url=#{args.root_url}" if args.root_url
bottle_args << "--committer=#{args.committer}" if args.committer
bottle_args << "--no-commit" if args.no_commit?
bottle_args << "--root-url-using=#{args.root_url_using}" if args.root_url_using
bottle_args += json_files

if args.dry_run?
dry_run_service = if github_packages?(bottles_hash)
# GitHub Packages has its own --dry-run handling.
nil
elsif github_releases?(bottles_hash)
"GitHub Releases"
else
odie "Service specified by root_url is not recognized"
tag

Check warning on line 140 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L140

Added line #L140 was not covered by tests
end
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
def github_packages?(bottles_hash)
@github_packages ||= bottles_hash.values.all? do |bottle_hash|
bottle_hash["bottle"]["root_url"].match? GitHubPackages::URL_REGEX

Check warning on line 146 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L145-L146

Added lines #L145 - L146 were not covered by tests
end
end

check_bottled_formulae!(bottles_hash)
def bottles_hash_from_json_files(json_files, args)
puts "Reading JSON files: #{json_files.join(", ")}" if args.verbose?

safe_system HOMEBREW_BREW_FILE, *bottle_args
bottles_hash = json_files.reduce({}) do |hash, json_file|
hash.deep_merge(JSON.parse(File.read(json_file)))

Check warning on line 154 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L153-L154

Added lines #L153 - L154 were not covered by tests
end

json_files = Dir["*.bottle.json"]
if json_files.blank?
puts "No bottle JSON files after merge, no upload needed!"
return
end
if args.root_url
bottles_hash.each_value do |bottle_hash|
bottle_hash["bottle"]["root_url"] = args.root_url

Check warning on line 159 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L159

Added line #L159 was not covered by tests
end
end

# Reload the JSON files (in case `brew bottle --merge` generated
# `all: $SHA256` bottles)
bottles_hash = bottles_hash_from_json_files(json_files, args)

# Check the bottle commits did not break `brew audit`
unless args.no_commit?
audit_args = ["audit", "--skip-style"]
audit_args << "--verbose" if args.verbose?
audit_args << "--debug" if args.debug?
audit_args += bottles_hash.keys
safe_system HOMEBREW_BREW_FILE, *audit_args
bottles_hash

Check warning on line 163 in Library/Homebrew/dev-cmd/pr-upload.rb

View check run for this annotation

Codecov / codecov/patch

Library/Homebrew/dev-cmd/pr-upload.rb#L163

Added line #L163 was not covered by tests
end
end

if github_releases?(bottles_hash)
github_releases = GitHubReleases.new
github_releases.upload_bottles(bottles_hash)
elsif github_packages?(bottles_hash)
github_packages = GitHubPackages.new
github_packages.upload_bottles(bottles_hash,
keep_old: args.keep_old?,
dry_run: args.dry_run?,
warn_on_error: args.warn_on_upload_failure?)
else
odie "Service specified by root_url is not recognized"
end
end
end