mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-21 15:12:02 +00:00
Add --branch option to backporting script
This commit is contained in:
parent
c83014bc76
commit
39feb4f0d4
@ -1,3 +1 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# REMOVE ME
|
||||
|
@ -7,15 +7,15 @@
|
||||
- All pull-requests must be squash-merged or explicitly merged without rebase.
|
||||
- All pull-requests to master must have at least one label prefixed with `pr-`.
|
||||
- Labels that require pull-request to be backported must be red colored (#ff0000).
|
||||
- Stable branch name must be of form `YY.NUMBER`.
|
||||
- All stable branches must be forked directly from the master branch and never be merged back,
|
||||
- Release branch name must be of form `YY.NUMBER`.
|
||||
- All release branches must be forked directly from the master branch and never be merged back,
|
||||
or merged with any other branches based on the master branch (including master branch itself).
|
||||
|
||||
Output of this script:
|
||||
|
||||
- Commits without references from pull-requests.
|
||||
- Pull-requests to master without proper labels.
|
||||
- Pull-requests that need to be backported, with statuses per stable branch.
|
||||
- Pull-requests that need to be backported, with statuses per release branch.
|
||||
|
||||
'''
|
||||
|
||||
@ -29,7 +29,7 @@ import sys
|
||||
try:
|
||||
from termcolor import colored # `pip install termcolor`
|
||||
except ImportError:
|
||||
sys.exit("Package 'termcolor' not found. Try run: `pip3 install termcolor`")
|
||||
sys.exit("Package 'termcolor' not found. Try run: `pip3 install [--user] termcolor`")
|
||||
|
||||
|
||||
CHECK_MARK = colored('🗸', 'green')
|
||||
@ -45,8 +45,6 @@ parser.add_argument('--repo', '-r', type=str, default='', metavar='PATH',
|
||||
help='path to the root of the ClickHouse repository')
|
||||
parser.add_argument('--remote', type=str, default='origin',
|
||||
help='remote name of the "ClickHouse/ClickHouse" upstream')
|
||||
parser.add_argument('-n', type=int, default=3, dest='number',
|
||||
help='number of last stable branches to consider')
|
||||
parser.add_argument('--token', type=str, required=True,
|
||||
help='token for Github access')
|
||||
parser.add_argument('--login', type=str,
|
||||
@ -54,31 +52,46 @@ parser.add_argument('--login', type=str,
|
||||
parser.add_argument('--auto-label', action='store_true', dest='autolabel', default=True,
|
||||
help='try to automatically parse PR description and put labels')
|
||||
|
||||
# Either select last N release branches, or specify them manually.
|
||||
group = parser.add_mutually_exclusive_group(required=True)
|
||||
group.add_argument('-n', type=int, default=3, dest='number',
|
||||
help='number of last release branches to consider')
|
||||
group.add_argument('--branch', type=str, action='append', metavar='BRANCH',
|
||||
help='specific release branch name to consider')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
github = query.Query(args.token, 30)
|
||||
repo = local.Local(args.repo, args.remote, github.get_default_branch())
|
||||
|
||||
stables = repo.get_stables()[-args.number:] # [(branch name, base)]
|
||||
if not stables:
|
||||
if not args.branch:
|
||||
release_branches = repo.get_release_branches()[-args.number:] # [(branch name, base)]
|
||||
else:
|
||||
release_branches = []
|
||||
all_release_branches = repo.get_release_branches()
|
||||
for branch in all_release_branches:
|
||||
if branch[0] in args.branch:
|
||||
release_branches.append(branch)
|
||||
|
||||
if not release_branches:
|
||||
sys.exit('No release branches found!')
|
||||
else:
|
||||
print('Found release branches:')
|
||||
for stable in stables:
|
||||
print(f'{CHECK_MARK} {stable[0]} forked from {stable[1]}')
|
||||
for branch in release_branches:
|
||||
print(f'{CHECK_MARK} {branch[0]} forked from {branch[1]}')
|
||||
|
||||
first_commit = stables[0][1]
|
||||
first_commit = release_branches[0][1]
|
||||
pull_requests = github.get_pull_requests(first_commit, args.login)
|
||||
good_commits = set(pull_request['mergeCommit']['oid'] for pull_request in pull_requests)
|
||||
|
||||
bad_commits = [] # collect and print them in the end
|
||||
from_commit = repo.get_head_commit()
|
||||
for i in reversed(range(len(stables))):
|
||||
for commit in repo.iterate(from_commit, stables[i][1]):
|
||||
for i in reversed(range(len(release_branches))):
|
||||
for commit in repo.iterate(from_commit, release_branches[i][1]):
|
||||
if str(commit) not in good_commits and commit.author.name != 'robot-clickhouse':
|
||||
bad_commits.append(commit)
|
||||
|
||||
from_commit = stables[i][1]
|
||||
from_commit = release_branches[i][1]
|
||||
|
||||
members = set(github.get_members("ClickHouse", "ClickHouse"))
|
||||
def print_responsible(pull_request):
|
||||
@ -146,22 +159,22 @@ if need_backporting:
|
||||
no_backport_labeled = set()
|
||||
wait = set()
|
||||
|
||||
for stable in stables:
|
||||
if repo.comparator(stable[1]) < repo.comparator(pull_request['mergeCommit']['oid']):
|
||||
targets.append(stable[0])
|
||||
for branch in release_branches:
|
||||
if repo.comparator(branch[1]) < repo.comparator(pull_request['mergeCommit']['oid']):
|
||||
targets.append(branch[0])
|
||||
|
||||
# FIXME: compatibility logic - check for a manually set label, that indicates status 'backported'.
|
||||
# FIXME: O(n²) - no need to iterate all labels for every `stable`
|
||||
# FIXME: O(n²) - no need to iterate all labels for every `branch`
|
||||
for label in github.get_labels(pull_request):
|
||||
if re_vlabel.match(label['name']) or re_vlabel_backported.match(label['name']):
|
||||
if f'v{stable[0]}' == label['name'] or f'v{stable[0]}-backported' == label['name']:
|
||||
backport_labeled.add(stable[0])
|
||||
if f'v{branch[0]}' == label['name'] or f'v{branch[0]}-backported' == label['name']:
|
||||
backport_labeled.add(branch[0])
|
||||
if re_vlabel_conflicts.match(label['name']):
|
||||
if f'v{stable[0]}-conflicts' == label['name']:
|
||||
conflict_labeled.add(stable[0])
|
||||
if f'v{branch[0]}-conflicts' == label['name']:
|
||||
conflict_labeled.add(branch[0])
|
||||
if re_vlabel_no_backport.match(label['name']):
|
||||
if f'v{stable[0]}-no-backport' == label['name']:
|
||||
no_backport_labeled.add(stable[0])
|
||||
if f'v{branch[0]}-no-backport' == label['name']:
|
||||
no_backport_labeled.add(branch[0])
|
||||
|
||||
for event in github.get_timeline(pull_request):
|
||||
if(event['isCrossRepository'] or
|
||||
|
@ -1,7 +1,9 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# `pip install …`
|
||||
import git # gitpython
|
||||
try:
|
||||
import git # `pip3 install gitpython`
|
||||
except ImportError:
|
||||
sys.exit("Package 'gitpython' not found. Try run: `pip3 install [--user] gitpython`")
|
||||
|
||||
import functools
|
||||
import os
|
||||
@ -11,7 +13,7 @@ import re
|
||||
class Local:
|
||||
'''Implements some useful methods atop of the local repository
|
||||
'''
|
||||
RE_STABLE_REF = re.compile(r'^refs/remotes/.+/\d+\.\d+$')
|
||||
RE_RELEASE_BRANCH_REF = re.compile(r'^refs/remotes/.+/\d+\.\d+$')
|
||||
|
||||
def __init__(self, repo_path, remote_name, default_branch_name):
|
||||
self._repo = git.Repo(repo_path, search_parent_directories=(not repo_path))
|
||||
@ -42,16 +44,16 @@ class Local:
|
||||
* head (git.Commit)).
|
||||
List is sorted by commits in ascending order.
|
||||
'''
|
||||
def get_stables(self):
|
||||
stables = []
|
||||
def get_release_branches(self):
|
||||
release_branches = []
|
||||
|
||||
for stable in [r for r in self._remote.refs if Local.RE_STABLE_REF.match(r.path)]:
|
||||
base = self._repo.merge_base(self._default, self._repo.commit(stable))
|
||||
for branch in [r for r in self._remote.refs if Local.RE_RELEASE_BRANCH_REF.match(r.path)]:
|
||||
base = self._repo.merge_base(self._default, self._repo.commit(branch))
|
||||
if not base:
|
||||
print(f'Branch {stable.path} is not based on branch {self._default}. Ignoring.')
|
||||
print(f'Branch {branch.path} is not based on branch {self._default}. Ignoring.')
|
||||
elif len(base) > 1:
|
||||
print(f'Branch {stable.path} has more than one base commit. Ignoring.')
|
||||
print(f'Branch {branch.path} has more than one base commit. Ignoring.')
|
||||
else:
|
||||
stables.append((os.path.basename(stable.name), base[0]))
|
||||
release_branches.append((os.path.basename(branch.name), base[0]))
|
||||
|
||||
return sorted(stables, key=lambda x : self.comparator(x[1]))
|
||||
return sorted(release_branches, key=lambda x : self.comparator(x[1]))
|
||||
|
Loading…
Reference in New Issue
Block a user