mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-10 01:25:21 +00:00
Merge pull request #18195 from abyss7/backport-lts
Add support for LTS branches in backport automation
This commit is contained in:
commit
839e873aa0
@ -1,8 +1,13 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
from clickhouse.utils.github.cherrypick import CherryPick
|
||||
from clickhouse.utils.github.query import Query as RemoteRepo
|
||||
from clickhouse.utils.github.local import Repository as LocalRepo
|
||||
try:
|
||||
from clickhouse.utils.github.cherrypick import CherryPick
|
||||
from clickhouse.utils.github.query import Query as RemoteRepo
|
||||
from clickhouse.utils.github.local import Repository as LocalRepo
|
||||
except:
|
||||
from .cherrypick import CherryPick
|
||||
from .query import Query as RemoteRepo
|
||||
from .local import Repository as LocalRepo
|
||||
|
||||
import argparse
|
||||
import logging
|
||||
@ -20,9 +25,25 @@ class Backport:
|
||||
def getPullRequests(self, from_commit):
|
||||
return self._gh.get_pull_requests(from_commit)
|
||||
|
||||
def execute(self, repo, until_commit, number, run_cherrypick):
|
||||
def getBranchesWithLTS(self):
|
||||
branches = []
|
||||
for pull_request in self._gh.find_pull_requests("release-lts"):
|
||||
if not pull_request['merged'] and not pull_request['closed']:
|
||||
branches.append(pull_request['headRefName'])
|
||||
return branches
|
||||
|
||||
def execute(self, repo, until_commit, number, run_cherrypick, find_lts=False):
|
||||
repo = LocalRepo(repo, 'origin', self.default_branch_name)
|
||||
branches = repo.get_release_branches()[-number:] # [(branch_name, base_commit)]
|
||||
all_branches = repo.get_release_branches() # [(branch_name, base_commit)]
|
||||
|
||||
last_branches = set([branch[0] for branch in all_branches[-number:]])
|
||||
lts_branches = set(self.getBranchesWithLTS() if find_lts else [])
|
||||
|
||||
branches = []
|
||||
# iterate over all branches to preserve their precedence.
|
||||
for branch in all_branches:
|
||||
if branch in last_branches or branch in lts_branches:
|
||||
branches.append(branch)
|
||||
|
||||
if not branches:
|
||||
logging.info('No release branches found!')
|
||||
@ -95,6 +116,7 @@ if __name__ == "__main__":
|
||||
parser.add_argument('--repo', type=str, required=True, help='path to full repository', metavar='PATH')
|
||||
parser.add_argument('--til', type=str, help='check PRs from HEAD til this commit', metavar='COMMIT')
|
||||
parser.add_argument('-n', type=int, dest='number', help='number of last release branches to consider')
|
||||
parser.add_argument('--lts', action='store_true', help='consider branches with LTS')
|
||||
parser.add_argument('--dry-run', action='store_true', help='do not create or merge any PRs', default=False)
|
||||
parser.add_argument('--verbose', '-v', action='store_true', help='more verbose output', default=False)
|
||||
args = parser.parse_args()
|
||||
@ -106,4 +128,4 @@ if __name__ == "__main__":
|
||||
|
||||
cherrypick_run = lambda token, pr, branch: CherryPick(token, 'ClickHouse', 'ClickHouse', 'core', pr, branch).execute(args.repo, args.dry_run)
|
||||
bp = Backport(args.token, 'ClickHouse', 'ClickHouse', 'core')
|
||||
bp.execute(args.repo, args.til, args.number, cherrypick_run)
|
||||
bp.execute(args.repo, args.til, args.number, cherrypick_run, args.lts)
|
||||
|
@ -14,7 +14,10 @@ Second run checks PR from previous run to be merged or at least being mergeable.
|
||||
Third run creates PR from backport branch (with merged previous PR) to release branch.
|
||||
'''
|
||||
|
||||
from clickhouse.utils.github.query import Query as RemoteRepo
|
||||
try:
|
||||
from clickhouse.utils.github.query import Query as RemoteRepo
|
||||
except:
|
||||
from .query import Query as RemoteRepo
|
||||
|
||||
import argparse
|
||||
from enum import Enum
|
||||
|
@ -39,6 +39,7 @@ class Query:
|
||||
|
||||
baseRefName
|
||||
closed
|
||||
headRefName
|
||||
id
|
||||
mergeable
|
||||
merged
|
||||
@ -158,6 +159,24 @@ class Query:
|
||||
else:
|
||||
return {}
|
||||
|
||||
def find_pull_requests(self, label_name):
|
||||
'''
|
||||
Get all pull-requests filtered by label name
|
||||
'''
|
||||
_QUERY = '''
|
||||
repository(owner: "{owner}" name: "{name}") {{
|
||||
pullRequests(first: {min_page_size} labels: "{label_name}") {{
|
||||
nodes {{
|
||||
{pull_request_data}
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
'''
|
||||
|
||||
query = _QUERY.format(owner=self._owner, name=self._name, label_name=label_name,
|
||||
pull_request_data=self._PULL_REQUEST, min_page_size=self._min_page_size)
|
||||
return self._run(query)['repository']['pullRequests']['nodes']
|
||||
|
||||
def get_pull_requests(self, before_commit):
|
||||
'''
|
||||
Get all merged pull-requests from the HEAD of default branch to the last commit (excluding)
|
||||
@ -342,130 +361,6 @@ class Query:
|
||||
query = _SET_LABEL.format(pr_id=pull_request['id'], label_id=labels[0]['id'])
|
||||
self._run(query, is_mutation=True)
|
||||
|
||||
# OLD METHODS
|
||||
|
||||
# _LABELS = '''
|
||||
# repository(owner: "ClickHouse" name: "ClickHouse") {{
|
||||
# pullRequest(number: {number}) {{
|
||||
# labels(first: {max_page_size} {next}) {{
|
||||
# pageInfo {{
|
||||
# hasNextPage
|
||||
# endCursor
|
||||
# }}
|
||||
# nodes {{
|
||||
# name
|
||||
# color
|
||||
# }}
|
||||
# }}
|
||||
# }}
|
||||
# }}
|
||||
# '''
|
||||
# def get_labels(self, pull_request):
|
||||
# '''Fetchs all labels for given pull-request
|
||||
|
||||
# Args:
|
||||
# pull_request: JSON object returned by `get_pull_requests()`
|
||||
|
||||
# Returns:
|
||||
# labels: a list of JSON nodes with the name and color fields
|
||||
# '''
|
||||
# labels = [label for label in pull_request['labels']['nodes']]
|
||||
# not_end = pull_request['labels']['pageInfo']['hasNextPage']
|
||||
# query = Query._LABELS.format(number = pull_request['number'],
|
||||
# max_page_size = self._max_page_size,
|
||||
# next=f'after: "{pull_request["labels"]["pageInfo"]["endCursor"]}"')
|
||||
|
||||
# while not_end:
|
||||
# result = self._run(query)['repository']['pullRequest']['labels']
|
||||
# not_end = result['pageInfo']['hasNextPage']
|
||||
# query = Query._LABELS.format(number=pull_request['number'],
|
||||
# max_page_size=self._max_page_size,
|
||||
# next=f'after: "{result["pageInfo"]["endCursor"]}"')
|
||||
|
||||
# labels += [label for label in result['nodes']]
|
||||
|
||||
# return labels
|
||||
|
||||
# _TIMELINE = '''
|
||||
# repository(owner: "ClickHouse" name: "ClickHouse") {{
|
||||
# pullRequest(number: {number}) {{
|
||||
# timeline(first: {max_page_size} {next}) {{
|
||||
# pageInfo {{
|
||||
# hasNextPage
|
||||
# endCursor
|
||||
# }}
|
||||
# nodes {{
|
||||
# ... on CrossReferencedEvent {{
|
||||
# isCrossRepository
|
||||
# source {{
|
||||
# ... on PullRequest {{
|
||||
# number
|
||||
# baseRefName
|
||||
# merged
|
||||
# labels(first: {max_page_size}) {{
|
||||
# pageInfo {{
|
||||
# hasNextPage
|
||||
# endCursor
|
||||
# }}
|
||||
# nodes {{
|
||||
# name
|
||||
# color
|
||||
# }}
|
||||
# }}
|
||||
# }}
|
||||
# }}
|
||||
# target {{
|
||||
# ... on PullRequest {{
|
||||
# number
|
||||
# }}
|
||||
# }}
|
||||
# }}
|
||||
# }}
|
||||
# }}
|
||||
# }}
|
||||
# }}
|
||||
# '''
|
||||
# def get_timeline(self, pull_request):
|
||||
# '''Fetchs all cross-reference events from pull-request's timeline
|
||||
|
||||
# Args:
|
||||
# pull_request: JSON object returned by `get_pull_requests()`
|
||||
|
||||
# Returns:
|
||||
# events: a list of JSON nodes for CrossReferenceEvent
|
||||
# '''
|
||||
# events = [event for event in pull_request['timeline']['nodes'] if event and event['source']]
|
||||
# not_end = pull_request['timeline']['pageInfo']['hasNextPage']
|
||||
# query = Query._TIMELINE.format(number = pull_request['number'],
|
||||
# max_page_size = self._max_page_size,
|
||||
# next=f'after: "{pull_request["timeline"]["pageInfo"]["endCursor"]}"')
|
||||
|
||||
# while not_end:
|
||||
# result = self._run(query)['repository']['pullRequest']['timeline']
|
||||
# not_end = result['pageInfo']['hasNextPage']
|
||||
# query = Query._TIMELINE.format(number=pull_request['number'],
|
||||
# max_page_size=self._max_page_size,
|
||||
# next=f'after: "{result["pageInfo"]["endCursor"]}"')
|
||||
|
||||
# events += [event for event in result['nodes'] if event and event['source']]
|
||||
|
||||
# return events
|
||||
|
||||
# _DEFAULT = '''
|
||||
# repository(owner: "ClickHouse", name: "ClickHouse") {
|
||||
# defaultBranchRef {
|
||||
# name
|
||||
# }
|
||||
# }
|
||||
# '''
|
||||
# def get_default_branch(self):
|
||||
# '''Get short name of the default branch
|
||||
|
||||
# Returns:
|
||||
# name (string): branch name
|
||||
# '''
|
||||
# return self._run(Query._DEFAULT)['repository']['defaultBranchRef']['name']
|
||||
|
||||
def _run(self, query, is_mutation=False):
|
||||
from requests.adapters import HTTPAdapter
|
||||
from urllib3.util.retry import Retry
|
||||
|
Loading…
Reference in New Issue
Block a user