`prs = response.json().get("items", [])` will return empty when there are no merged PRs, and this will just skip the all-label replacement process.
This is a regression following the work done in #19442
Adding another part to handle closed PRs (which is the majority of the cases we have in Scylla core)
Fixes: https://github.com/scylladb/scylladb/issues/19441
(cherry picked from commit 2eb8344b9a)
Closes scylladb/scylladb#19527
88 lines
4.0 KiB
Python
Executable File
88 lines
4.0 KiB
Python
Executable File
from github import Github
|
|
import argparse
|
|
import re
|
|
import sys
|
|
import os
|
|
|
|
try:
|
|
github_token = os.environ["GITHUB_TOKEN"]
|
|
except KeyError:
|
|
print("Please set the 'GITHUB_TOKEN' environment variable")
|
|
sys.exit(1)
|
|
|
|
|
|
def parser():
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('--repository', type=str, required=True,
|
|
help='Github repository name (e.g., scylladb/scylladb)')
|
|
parser.add_argument('--commit_before_merge', type=str, required=True, help='Git commit ID to start labeling from ('
|
|
'newest commit).')
|
|
parser.add_argument('--commit_after_merge', type=str, required=True,
|
|
help='Git commit ID to end labeling at (oldest '
|
|
'commit, exclusive).')
|
|
parser.add_argument('--update_issue', type=bool, default=False, help='Set True to update issues when backport was '
|
|
'done')
|
|
parser.add_argument('--ref', type=str, required=True, help='PR target branch')
|
|
return parser.parse_args()
|
|
|
|
|
|
def add_comment_and_close_pr(pr, comment):
|
|
if pr.state == 'open':
|
|
pr.create_issue_comment(comment)
|
|
pr.edit(state="closed")
|
|
|
|
|
|
def mark_backport_done(repo, ref_pr_number, branch):
|
|
pr = repo.get_pull(int(ref_pr_number))
|
|
label_to_remove = f'backport/{branch}'
|
|
label_to_add = f'{label_to_remove}-done'
|
|
current_labels = [label.name for label in pr.get_labels()]
|
|
if label_to_remove in current_labels:
|
|
pr.remove_from_labels(label_to_remove)
|
|
if label_to_add not in current_labels:
|
|
pr.add_to_labels(label_to_add)
|
|
|
|
|
|
def main():
|
|
# This script is triggered by a push event to either the master branch or a branch named branch-x.y (where x and y represent version numbers). Based on the pushed branch, the script performs the following actions:
|
|
# - When ref branch is `master`, it will add the `promoted-to-master` label, which we need later for the auto backport process
|
|
# - When ref branch is `branch-x.y` (which means we backported a patch), it will replace in the original PR the `backport/x.y` label with `backport/x.y-done` and will close the backport PR (Since GitHub close only the one referring to default branch)
|
|
args = parser()
|
|
pr_pattern = re.compile(r'Closes .*#([0-9]+)')
|
|
target_branch = re.search(r'branch-(\d+\.\d+)', args.ref)
|
|
g = Github(github_token)
|
|
repo = g.get_repo(args.repository, lazy=False)
|
|
commits = repo.compare(head=args.commit_after_merge, base=args.commit_before_merge)
|
|
processed_prs = set()
|
|
# Print commit information
|
|
for commit in commits.commits:
|
|
print(f'Commit sha is: {commit.sha}')
|
|
match = pr_pattern.search(commit.commit.message)
|
|
if match:
|
|
pr_number = int(match.group(1))
|
|
if pr_number in processed_prs:
|
|
continue
|
|
if target_branch:
|
|
pr = repo.get_pull(pr_number)
|
|
branch_name = target_branch[1]
|
|
refs_pr = re.findall(r'Refs (?:#|https.*?)(\d+)', pr.body)
|
|
if refs_pr:
|
|
print(f'branch-{target_branch.group(1)}, pr number is: {pr_number}')
|
|
# 1. change the backport label of the parent PR to note that
|
|
# we've merge the corresponding backport PR
|
|
# 2. close the backport PR and leave a comment on it to note
|
|
# that it has been merged with a certain git commit,
|
|
ref_pr_number = refs_pr[0]
|
|
mark_backport_done(repo, ref_pr_number, branch_name)
|
|
comment = f'Closed via {commit.sha}'
|
|
add_comment_and_close_pr(pr, comment)
|
|
else:
|
|
print(f'master branch, pr number is: {pr_number}')
|
|
pr = repo.get_pull(pr_number)
|
|
pr.add_to_labels('promoted-to-master')
|
|
processed_prs.add(pr_number)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|