Compare commits
1 Commits
debug_form
...
auto-backp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dcbc6c839d |
50
.github/scripts/auto-backport.py
vendored
50
.github/scripts/auto-backport.py
vendored
@@ -29,10 +29,11 @@ def parse_args():
|
||||
parser.add_argument('--commits', default=None, type=str, help='Range of promoted commits.')
|
||||
parser.add_argument('--pull-request', type=int, help='Pull request number to be backported')
|
||||
parser.add_argument('--head-commit', type=str, required=is_pull_request(), help='The HEAD of target branch after the pull request specified by --pull-request is merged')
|
||||
parser.add_argument('--github-event', type=str, help='Get GitHub event type')
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
def create_pull_request(repo, new_branch_name, base_branch_name, pr, backport_pr_title, commits, is_draft=False):
|
||||
def create_pull_request(repo, new_branch_name, base_branch_name, pr, backport_pr_title, commits, is_draft, is_collaborator):
|
||||
pr_body = f'{pr.body}\n\n'
|
||||
for commit in commits:
|
||||
pr_body += f'- (cherry picked from commit {commit})\n\n'
|
||||
@@ -46,7 +47,8 @@ def create_pull_request(repo, new_branch_name, base_branch_name, pr, backport_pr
|
||||
draft=is_draft
|
||||
)
|
||||
logging.info(f"Pull request created: {backport_pr.html_url}")
|
||||
backport_pr.add_to_assignees(pr.user)
|
||||
if is_collaborator:
|
||||
backport_pr.add_to_assignees(pr.user)
|
||||
if is_draft:
|
||||
backport_pr.add_to_labels("conflicts")
|
||||
pr_comment = f"@{pr.user.login} - This PR was marked as draft because it has conflicts\n"
|
||||
@@ -92,18 +94,7 @@ def get_pr_commits(repo, pr, stable_branch, start_commit=None):
|
||||
return commits
|
||||
|
||||
|
||||
def create_pr_comment_and_remove_label(pr, comment_body):
|
||||
labels = pr.get_labels()
|
||||
pattern = re.compile(r"backport/\d+\.\d+$")
|
||||
for label in labels:
|
||||
if pattern.match(label.name):
|
||||
print(f"Removing label: {label.name}")
|
||||
comment_body += f'- {label.name}\n'
|
||||
pr.remove_from_labels(label)
|
||||
pr.create_issue_comment(comment_body)
|
||||
|
||||
|
||||
def backport(repo, pr, version, commits, backport_base_branch):
|
||||
def backport(repo, pr, version, commits, backport_base_branch, is_collaborator):
|
||||
new_branch_name = f'backport/{pr.number}/to-{version}'
|
||||
backport_pr_title = f'[Backport {version}] {pr.title}'
|
||||
repo_url = f'https://scylladbbot:{github_token}@github.com/{repo.full_name}.git'
|
||||
@@ -123,7 +114,7 @@ def backport(repo, pr, version, commits, backport_base_branch):
|
||||
repo_local.git.cherry_pick('--continue')
|
||||
repo_local.git.push(fork_repo, new_branch_name, force=True)
|
||||
create_pull_request(repo, new_branch_name, backport_base_branch, pr, backport_pr_title, commits,
|
||||
is_draft=is_draft)
|
||||
is_draft, is_collaborator)
|
||||
|
||||
except GitCommandError as e:
|
||||
logging.warning(f"GitCommandError: {e}")
|
||||
@@ -140,10 +131,6 @@ def with_github_keyword_prefix(repo, pr):
|
||||
break
|
||||
if not match:
|
||||
print(f'No valid close reference for {pr.number}')
|
||||
comment = f':warning: @{pr.user.login} PR body does not contain a Fixes reference to an issue '
|
||||
comment += ' and can not be backported\n\n'
|
||||
comment += 'The following labels were removed:\n'
|
||||
create_pr_comment_and_remove_label(pr, comment)
|
||||
return False
|
||||
else:
|
||||
return True
|
||||
@@ -168,6 +155,7 @@ def main():
|
||||
scylladbbot_repo = g.get_repo(fork_repo_name)
|
||||
closed_prs = []
|
||||
start_commit = None
|
||||
is_collaborator = True
|
||||
|
||||
if args.commits:
|
||||
start_commit, end_commit = args.commits.split('..')
|
||||
@@ -192,21 +180,33 @@ def main():
|
||||
if not backport_labels:
|
||||
print(f'no backport label: {pr.number}')
|
||||
continue
|
||||
if args.commits and not with_github_keyword_prefix(repo, pr):
|
||||
if not with_github_keyword_prefix(repo, pr) and args.github_event != 'unlabeled':
|
||||
comment = f''':warning: @{pr.user.login} PR body or PR commits do not contain a Fixes reference to an issue and can not be backported
|
||||
please update PR body with a valid ref to an issue. Then remove `scylladbbot/backport_error` label to re-trigger the backport process
|
||||
'''
|
||||
pr.create_issue_comment(comment)
|
||||
pr.add_to_labels("scylladbbot/backport_error")
|
||||
continue
|
||||
if not repo.private and not scylladbbot_repo.has_in_collaborators(pr.user.login):
|
||||
logging.info(f"Sending an invite to {pr.user.login} to become a collaborator to {scylladbbot_repo.full_name} ")
|
||||
scylladbbot_repo.add_to_collaborators(pr.user.login)
|
||||
comment = f':warning: @{pr.user.login} you have been added as collaborator to scylladbbot fork '
|
||||
comment += f'Please check your inbox and approve the invitation, once it is done, please add the backport labels again\n'
|
||||
create_pr_comment_and_remove_label(pr, comment)
|
||||
continue
|
||||
comment = f''':warning: @{pr.user.login} you have been added as collaborator to scylladbbot fork
|
||||
Please check your inbox and approve the invitation, otherwise you will not be able to edit PR branch when needed
|
||||
'''
|
||||
# When a pull request is pending for backport but its author is not yet a collaborator of "scylladbbot",
|
||||
# we attach a "scylladbbot/backport_error" label to the PR.
|
||||
# This prevents the workflow from proceeding with the backport process
|
||||
# until the author has been granted proper permissions
|
||||
# the author should remove the label manually to re-trigger the backport workflow.
|
||||
pr.add_to_labels("scylladbbot/backport_error")
|
||||
pr.create_issue_comment(comment)
|
||||
is_collaborator = False
|
||||
commits = get_pr_commits(repo, pr, stable_branch, start_commit)
|
||||
logging.info(f"Found PR #{pr.number} with commit {commits} and the following labels: {backport_labels}")
|
||||
for backport_label in backport_labels:
|
||||
version = backport_label.replace('backport/', '')
|
||||
backport_base_branch = backport_label.replace('backport/', backport_branch)
|
||||
backport(repo, pr, version, commits, backport_base_branch)
|
||||
backport(repo, pr, version, commits, backport_base_branch, is_collaborator)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
31
.github/workflows/add-label-when-promoted.yaml
vendored
31
.github/workflows/add-label-when-promoted.yaml
vendored
@@ -7,7 +7,7 @@ on:
|
||||
- branch-*.*
|
||||
- enterprise
|
||||
pull_request_target:
|
||||
types: [labeled]
|
||||
types: [labeled, unlabeled]
|
||||
branches: [master, next, enterprise]
|
||||
|
||||
jobs:
|
||||
@@ -53,19 +53,28 @@ jobs:
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.AUTO_BACKPORT_TOKEN }}
|
||||
run: python .github/scripts/auto-backport.py --repo ${{ github.repository }} --base-branch ${{ github.ref }} --commits ${{ github.event.before }}..${{ github.sha }}
|
||||
- name: Check if label starts with 'backport/' and contains digits
|
||||
- name: Check if a valid backport label exists and no backport_error
|
||||
id: check_label
|
||||
run: |
|
||||
label_name="${{ github.event.label.name }}"
|
||||
if [[ "$label_name" =~ ^backport/[0-9]+\.[0-9]+$ ]]; then
|
||||
echo "Label matches backport/X.X pattern."
|
||||
echo "backport_label=true" >> $GITHUB_OUTPUT
|
||||
labels_json='${{ toJson(github.event.pull_request.labels) }}'
|
||||
echo "Checking labels: $(echo "$labels_json" | jq -r '.[].name')"
|
||||
|
||||
# Check if a valid backport label exists
|
||||
if echo "$labels_json" | jq -e 'any(.[] | .name; test("backport/[0-9]+\\.[0-9]+$"))' > /dev/null; then
|
||||
# Ensure scylladbbot/backport_error is NOT present
|
||||
if ! echo "$labels_json" | jq -e '.[] | select(.name == "scylladbbot/backport_error")' > /dev/null; then
|
||||
echo "A matching backport label was found and no backport_error label exists."
|
||||
echo "ready_for_backport=true" >> "$GITHUB_OUTPUT"
|
||||
exit 0
|
||||
else
|
||||
echo "The label 'scylladbbot/backport_error' is present, invalidating backport."
|
||||
fi
|
||||
else
|
||||
echo "Label does not match the required pattern."
|
||||
echo "backport_label=false" >> $GITHUB_OUTPUT
|
||||
echo "No matching backport label found."
|
||||
fi
|
||||
- name: Run auto-backport.py when label was added
|
||||
if: ${{ github.event_name == 'pull_request_target' && steps.check_label.outputs.backport_label == 'true' && github.event.pull_request.state == 'closed' }}
|
||||
echo "ready_for_backport=false" >> "$GITHUB_OUTPUT"
|
||||
- name: Run auto-backport.py when PR is closed
|
||||
if: ${{ github.event_name == 'pull_request_target' && steps.check_label.outputs.ready_for_backport == 'true' && github.event.pull_request.state == 'closed' }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.AUTO_BACKPORT_TOKEN }}
|
||||
run: python .github/scripts/auto-backport.py --repo ${{ github.repository }} --base-branch ${{ github.ref }} --pull-request ${{ github.event.pull_request.number }} --head-commit ${{ github.event.pull_request.base.sha }}
|
||||
run: python .github/scripts/auto-backport.py --repo ${{ github.repository }} --base-branch ${{ github.ref }} --pull-request ${{ github.event.pull_request.number }} --head-commit ${{ github.event.pull_request.base.sha }} --github-event ${{ github.event.action }}
|
||||
|
||||
Reference in New Issue
Block a user