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

dev-cmd/pr-*: support merge workflow changes #15077

Merged
merged 12 commits into from Mar 29, 2023
Merged
12 changes: 9 additions & 3 deletions Library/Homebrew/dev-cmd/pr-automerge.rb
Expand Up @@ -23,11 +23,14 @@ def pr_automerge_args
description: "Pull requests must have this label."
comma_array "--without-labels",
description: "Pull requests must not have these labels (default: " \
"`do not merge`, `new formula`, `automerge-skip`)."
"`do not merge`, `new formula`, `automerge-skip`, `CI-published-bottle-commits`)."
switch "--without-approval",
description: "Pull requests do not require approval to be merged."
switch "--publish",
description: "Run `brew pr-publish` on matching pull requests."
switch "--autosquash",
description: "Instruct `brew pr-publish` to automatically reformat and reword commits " \
"in the pull request to the preferred format."
switch "--no-autosquash",
description: "Instruct `brew pr-publish` to skip automatically reformatting and rewording commits " \
"in the pull request to the preferred format."
Expand All @@ -41,10 +44,13 @@ def pr_automerge_args
def pr_automerge
args = pr_automerge_args.parse

odeprecated "`brew pr-publish --no-autosquash`" if args.no_autosquash?

without_labels = args.without_labels || [
"do not merge",
"new formula",
"automerge-skip",
"CI-published-bottle-commits",
]
tap = Tap.fetch(args.tap || CoreTap.instance.name)

Expand All @@ -68,10 +74,10 @@ def pr_automerge
pr_urls << pr["html_url"]
end

publish_args = ["pr-publish"]
publish_args = ["pr-publish", "--commit-bottles-to-pr-branch"]
publish_args << "--tap=#{tap}" if tap
publish_args << "--workflow=#{args.workflow}" if args.workflow
publish_args << "--no-autosquash" if args.no_autosquash?
publish_args << "--autosquash" if args.autosquash?
if args.publish?
safe_system HOMEBREW_BREW_FILE, *publish_args, *pr_urls
else
Expand Down
35 changes: 27 additions & 8 deletions Library/Homebrew/dev-cmd/pr-publish.rb
Expand Up @@ -16,47 +16,66 @@ def pr_publish_args
Publish bottles for a pull request with GitHub Actions.
Requires write access to the repository.
EOS
switch "--commit-bottles-to-pr-branch",
description: "Push bottle commits to the pull request branch."
switch "--autosquash",
description: "If supported on the target tap, automatically reformat and reword commits " \
"to our preferred format."
switch "--no-autosquash",
description: "Skip automatically reformatting and rewording commits in the pull request " \
"to the preferred format, even if supported on the target tap."
switch "--large-runner",
description: "Run the upload job on a large runner."
flag "--branch=",
description: "Branch to publish to (default: `master`)."
description: "Branch to use the workflow from (default: `master`)."
flag "--message=",
depends_on: "--autosquash",
description: "Message to include when autosquashing revision bumps, deletions, and rebuilds."
flag "--tap=",
description: "Target tap repository (default: `homebrew/core`)."
flag "--workflow=",
description: "Target workflow filename (default: `publish-commit-bottles.yml`)."

conflicts "--no-autosquash", "--message"

named_args :pull_request, min: 1
end
end

def pr_publish
args = pr_publish_args.parse

odeprecated "`brew pr-publish --no-autosquash`" if args.no_autosquash?

tap = Tap.fetch(args.tap || CoreTap.instance.name)
workflow = args.workflow || "publish-commit-bottles.yml"
ref = args.branch || "master"

extra_args = []
extra_args << "--no-autosquash" if args.no_autosquash?
extra_args << "--message='#{args.message}'" if args.message.presence
dispatch_args = extra_args.join " "
inputs = {
commit_bottles_to_pr_branch: args.commit_bottles_to_pr_branch?,
autosquash: args.autosquash?,
large_runner: args.large_runner?,
}
inputs[:message] = args.message if args.message.presence

args.named.uniq.each do |arg|
arg = "#{tap.default_remote}/pull/#{arg}" if arg.to_i.positive?
url_match = arg.match HOMEBREW_PULL_OR_COMMIT_URL_REGEX
_, user, repo, issue = *url_match
odie "Not a GitHub pull request: #{arg}" unless issue

inputs[:pull_request] = issue

pr_labels = GitHub.pull_request_labels(user, repo, issue)
if pr_labels.include?("autosquash")
oh1 "Found `autosquash` label on ##{issue}. Requesting autosquash."
inputs[:autosquash] = true
end

if args.tap.present? && !T.must("#{user}/#{repo}".casecmp(tap.full_name)).zero?
odie "Pull request URL is for #{user}/#{repo} but `--tap=#{tap.full_name}` was specified!"
end

ohai "Dispatching #{tap} pull request ##{issue}"
GitHub.workflow_dispatch_event(user, repo, workflow, ref, pull_request: issue, args: dispatch_args)
GitHub.workflow_dispatch_event(user, repo, workflow, ref, inputs)
end
end
end
32 changes: 21 additions & 11 deletions Library/Homebrew/dev-cmd/pr-pull.rb
Expand Up @@ -27,11 +27,13 @@ def self.pr_pull_args
switch "-n", "--dry-run",
description: "Print what would be done rather than doing it."
switch "--clean",
depends_on: "--no-autosquash",
description: "Do not amend the commits from pull requests."
switch "--keep-old",
description: "If the formula specifies a rebuild version, " \
"attempt to preserve its value in the generated DSL."
switch "--autosquash",
description: "Automatically reformat and reword commits in the pull request to our " \
"preferred format."
switch "--no-autosquash",
description: "Skip automatically reformatting and rewording commits in the pull request to our " \
"preferred format."
Expand All @@ -46,6 +48,7 @@ def self.pr_pull_args
flag "--committer=",
description: "Specify a committer name and email in `git`'s standard author format."
flag "--message=",
depends_on: "--autosquash",
description: "Message to include when autosquashing revision bumps, deletions, and rebuilds."
flag "--artifact=",
description: "Download artifacts with the specified name (default: `bottles`)."
Expand All @@ -62,7 +65,7 @@ def self.pr_pull_args
comma_array "--ignore-missing-artifacts",
description: "Comma-separated list of workflows which can be ignored if they have not been run."

conflicts "--no-autosquash", "--message"
conflicts "--clean", "--autosquash"

named_args :pull_request, min: 1
end
Expand Down Expand Up @@ -223,7 +226,8 @@ def self.squash_package_commits(commits, file, reason: "", verbose: false, resol
ohai bump_subject
end

def self.autosquash!(original_commit, tap:, reason: "", verbose: false, resolve: false)
# TODO: fix test in `test/dev-cmd/pr-pull_spec.rb` and assume `cherry_picked: false`.
def self.autosquash!(original_commit, tap:, reason: "", verbose: false, resolve: false, cherry_picked: true)
original_head = tap.path.git_head

commits = Utils.safe_popen_read("git", "-C", tap.path, "rev-list",
Expand Down Expand Up @@ -282,9 +286,9 @@ def self.autosquash!(original_commit, tap:, reason: "", verbose: false, resolve:
end
end
rescue
opoo "Autosquash encountered an error; resetting to original cherry-picked state at #{original_head}"
opoo "Autosquash encountered an error; resetting to original state at #{original_head}"
system "git", "-C", tap.path, "reset", "--hard", original_head
system "git", "-C", tap.path, "cherry-pick", "--abort"
system "git", "-C", tap.path, "cherry-pick", "--abort" if cherry_picked
raise
end

Expand All @@ -304,11 +308,9 @@ def self.cherry_pick_pr!(user, repo, pull_request, args:, path: ".")
Utils::Git.cherry_pick!(path, "--ff", "--allow-empty", *commits, verbose: args.verbose?, resolve: args.resolve?)
end

def self.formulae_need_bottles?(tap, original_commit, user, repo, pull_request, args:)
def self.formulae_need_bottles?(tap, original_commit, labels, args:)
return if args.dry_run?

labels = GitHub.pull_request_labels(user, repo, pull_request)

return false if labels.include?("CI-syntax-only") || labels.include?("CI-no-bottles")

changed_packages(tap, original_commit).any? do |f|
Expand Down Expand Up @@ -424,6 +426,8 @@ def self.pr_check_conflicts(repo, pull_request)
def self.pr_pull
args = pr_pull_args.parse

odeprecated "`brew pr-pull --no-autosquash`" if args.no_autosquash?

# Needed when extracting the CI artifact.
ensure_executable!("unzip", reason: "extracting CI artifacts")

Expand All @@ -450,6 +454,11 @@ def self.pr_pull
opoo "Current branch is #{tap.path.git_branch}: do you need to pull inside #{tap.path.git_origin_branch}?"
end

pr_labels = GitHub.pull_request_labels(user, repo, pr)
if pr_labels.include?("autosquash") && !args.autosquash?
opoo "Pull request is labelled `autosquash`: do you need to pass `--autosquash`?"
end

pr_check_conflicts("#{user}/#{repo}", pr)

ohai "Fetching #{tap} pull request ##{pr}"
Expand All @@ -462,17 +471,18 @@ def self.pr_pull
else
current_branch_head
end
odebug "Pull request merge-base: #{original_commit}"

unless args.no_commit?
cherry_pick_pr!(user, repo, pr, path: tap.path, args: args) unless args.no_cherry_pick?
if !args.no_autosquash? && !args.dry_run?
autosquash!(original_commit, tap: tap,
if args.autosquash? && !args.dry_run?
autosquash!(original_commit, tap: tap, cherry_picked: !args.no_cherry_pick?,
verbose: args.verbose?, resolve: args.resolve?, reason: args.message)
end
signoff!(tap.path, pull_request: pr, dry_run: args.dry_run?) unless args.clean?
end

unless formulae_need_bottles?(tap, original_commit, user, repo, pr, args: args)
unless formulae_need_bottles?(tap, original_commit, pr_labels, args: args)
ohai "Skipping artifacts for ##{pr} as the formulae don't need bottles"
next
end
Expand Down
5 changes: 5 additions & 0 deletions completions/bash/brew
Expand Up @@ -1661,6 +1661,7 @@ _brew_pr_automerge() {
case "${cur}" in
-*)
__brewcomp "
--autosquash
--debug
--help
--ignore-failures
Expand All @@ -1685,9 +1686,12 @@ _brew_pr_publish() {
case "${cur}" in
-*)
__brewcomp "
--autosquash
--branch
--commit-bottles-to-pr-branch
--debug
--help
--large-runner
--message
--no-autosquash
--quiet
Expand All @@ -1707,6 +1711,7 @@ _brew_pr_pull() {
-*)
__brewcomp "
--artifact
--autosquash
--branch-okay
--clean
--committer
Expand Down
9 changes: 7 additions & 2 deletions completions/fish/brew.fish
Expand Up @@ -1142,6 +1142,7 @@ __fish_brew_complete_arg 'postinstall' -a '(__fish_brew_suggest_formulae_install


__fish_brew_complete_cmd 'pr-automerge' 'Find pull requests that can be automatically merged using `brew pr-publish`'
__fish_brew_complete_arg 'pr-automerge' -l autosquash -d 'Instruct `brew pr-publish` to automatically reformat and reword commits in the pull request to the preferred format'
__fish_brew_complete_arg 'pr-automerge' -l debug -d 'Display any debugging information'
__fish_brew_complete_arg 'pr-automerge' -l help -d 'Show this message'
__fish_brew_complete_arg 'pr-automerge' -l ignore-failures -d 'Include pull requests that have failing status checks'
Expand All @@ -1152,14 +1153,17 @@ __fish_brew_complete_arg 'pr-automerge' -l tap -d 'Target tap repository (defaul
__fish_brew_complete_arg 'pr-automerge' -l verbose -d 'Make some output more verbose'
__fish_brew_complete_arg 'pr-automerge' -l with-label -d 'Pull requests must have this label'
__fish_brew_complete_arg 'pr-automerge' -l without-approval -d 'Pull requests do not require approval to be merged'
__fish_brew_complete_arg 'pr-automerge' -l without-labels -d 'Pull requests must not have these labels (default: `do not merge`, `new formula`, `automerge-skip`)'
__fish_brew_complete_arg 'pr-automerge' -l without-labels -d 'Pull requests must not have these labels (default: `do not merge`, `new formula`, `automerge-skip`, `CI-published-bottle-commits`)'
__fish_brew_complete_arg 'pr-automerge' -l workflow -d 'Workflow file to use with `brew pr-publish`'


__fish_brew_complete_cmd 'pr-publish' 'Publish bottles for a pull request with GitHub Actions'
__fish_brew_complete_arg 'pr-publish' -l branch -d 'Branch to publish to (default: `master`)'
__fish_brew_complete_arg 'pr-publish' -l autosquash -d 'If supported on the target tap, automatically reformat and reword commits to our preferred format'
__fish_brew_complete_arg 'pr-publish' -l branch -d 'Branch to use the workflow from (default: `master`)'
__fish_brew_complete_arg 'pr-publish' -l commit-bottles-to-pr-branch -d 'Push bottle commits to the pull request branch'
__fish_brew_complete_arg 'pr-publish' -l debug -d 'Display any debugging information'
__fish_brew_complete_arg 'pr-publish' -l help -d 'Show this message'
__fish_brew_complete_arg 'pr-publish' -l large-runner -d 'Run the upload job on a large runner'
__fish_brew_complete_arg 'pr-publish' -l message -d 'Message to include when autosquashing revision bumps, deletions, and rebuilds'
__fish_brew_complete_arg 'pr-publish' -l no-autosquash -d 'Skip automatically reformatting and rewording commits in the pull request to the preferred format, even if supported on the target tap'
__fish_brew_complete_arg 'pr-publish' -l quiet -d 'Make some output more quiet'
Expand All @@ -1170,6 +1174,7 @@ __fish_brew_complete_arg 'pr-publish' -l workflow -d 'Target workflow filename (

__fish_brew_complete_cmd 'pr-pull' 'Download and publish bottles, and apply the bottle commit from a pull request with artifacts generated by GitHub Actions'
__fish_brew_complete_arg 'pr-pull' -l artifact -d 'Download artifacts with the specified name (default: `bottles`)'
__fish_brew_complete_arg 'pr-pull' -l autosquash -d 'Automatically reformat and reword commits in the pull request to our preferred format'
__fish_brew_complete_arg 'pr-pull' -l branch-okay -d 'Do not warn if pulling to a branch besides the repository default (useful for testing)'
__fish_brew_complete_arg 'pr-pull' -l clean -d 'Do not amend the commits from pull requests'
__fish_brew_complete_arg 'pr-pull' -l committer -d 'Specify a committer name and email in `git`\'s standard author format'
Expand Down
19 changes: 12 additions & 7 deletions completions/zsh/_brew
Expand Up @@ -1403,6 +1403,7 @@ _brew_postinstall() {
# brew pr-automerge
_brew_pr_automerge() {
_arguments \
'--autosquash[Instruct `brew pr-publish` to automatically reformat and reword commits in the pull request to the preferred format]' \
'--debug[Display any debugging information]' \
'--help[Show this message]' \
'--ignore-failures[Include pull requests that have failing status checks]' \
Expand All @@ -1413,18 +1414,21 @@ _brew_pr_automerge() {
'--verbose[Make some output more verbose]' \
'--with-label[Pull requests must have this label]' \
'--without-approval[Pull requests do not require approval to be merged]' \
'--without-labels[Pull requests must not have these labels (default: `do not merge`, `new formula`, `automerge-skip`)]' \
'--without-labels[Pull requests must not have these labels (default: `do not merge`, `new formula`, `automerge-skip`, `CI-published-bottle-commits`)]' \
'--workflow[Workflow file to use with `brew pr-publish`]'
}

# brew pr-publish
_brew_pr_publish() {
_arguments \
'--branch[Branch to publish to (default: `master`)]' \
'--autosquash[If supported on the target tap, automatically reformat and reword commits to our preferred format]' \
'--branch[Branch to use the workflow from (default: `master`)]' \
'--commit-bottles-to-pr-branch[Push bottle commits to the pull request branch]' \
'--debug[Display any debugging information]' \
'--help[Show this message]' \
'(--no-autosquash)--message[Message to include when autosquashing revision bumps, deletions, and rebuilds]' \
'(--message)--no-autosquash[Skip automatically reformatting and rewording commits in the pull request to the preferred format, even if supported on the target tap]' \
'--large-runner[Run the upload job on a large runner]' \
'--message[Message to include when autosquashing revision bumps, deletions, and rebuilds]' \
'--no-autosquash[Skip automatically reformatting and rewording commits in the pull request to the preferred format, even if supported on the target tap]' \
'--quiet[Make some output more quiet]' \
'--tap[Target tap repository (default: `homebrew/core`)]' \
'--verbose[Make some output more verbose]' \
Expand All @@ -1435,16 +1439,17 @@ _brew_pr_publish() {
_brew_pr_pull() {
_arguments \
'--artifact[Download artifacts with the specified name (default: `bottles`)]' \
'(--clean)--autosquash[Automatically reformat and reword commits in the pull request to our preferred format]' \
'--branch-okay[Do not warn if pulling to a branch besides the repository default (useful for testing)]' \
'--clean[Do not amend the commits from pull requests]' \
'(--autosquash)--clean[Do not amend the commits from pull requests]' \
'--committer[Specify a committer name and email in `git`'\''s standard author format]' \
'--debug[Display any debugging information]' \
'--dry-run[Print what would be done rather than doing it]' \
'--help[Show this message]' \
'--ignore-missing-artifacts[Comma-separated list of workflows which can be ignored if they have not been run]' \
'--keep-old[If the formula specifies a rebuild version, attempt to preserve its value in the generated DSL]' \
'(--no-autosquash)--message[Message to include when autosquashing revision bumps, deletions, and rebuilds]' \
'(--message)--no-autosquash[Skip automatically reformatting and rewording commits in the pull request to our preferred format]' \
'--message[Message to include when autosquashing revision bumps, deletions, and rebuilds]' \
'--no-autosquash[Skip automatically reformatting and rewording commits in the pull request to our preferred format]' \
'--no-cherry-pick[Do not cherry-pick commits from the pull request branch]' \
'--no-commit[Do not generate a new commit before uploading]' \
'--no-upload[Download the bottles but don'\''t upload them]' \
Expand Down