blob: 2886a0dd458f0deef67836f85a972521ca52cc9a [file] [log] [blame]
#!/usr/bin/python3
##############################################################################
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements. See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership. The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License. You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
##############################################################################
# This script is designed to create a cherry pick PR to a target branch
#
# Usage: python3 cherry_pick_pr.py
#
# To test locally:
#
# git clone git@github.com:apache/arrow-rs.git /tmp/arrow-rs
#
# pip3 install PyGithub
# ARROW_GITHUB_API_TOKEN=<..>
# CHECKOUT_ROOT=<path>
# CHERRY_PICK_SHA=<sha> python3 cherry-pick-pr.py
#
import os
import sys
import six
import subprocess
from pathlib import Path
TARGET_BRANCH = 'active_release'
TARGET_REPO = 'apache/arrow-rs'
p = Path(__file__)
# Use github workspace if specified
repo_root = os.environ.get("CHECKOUT_ROOT")
if repo_root is None:
print("arrow-rs checkout must be supplied in CHECKOUT_ROOT environment")
sys.exit(1)
print("Using checkout in {}".format(repo_root))
token = os.environ.get('ARROW_GITHUB_API_TOKEN', None)
if token is None:
print("GITHUB token must be supplied in ARROW_GITHUB_API_TOKEN environmet")
sys.exit(1)
new_sha = os.environ.get('CHERRY_PICK_SHA', None)
if new_sha is None:
print("SHA to cherry pick must be supplied in CHERRY_PICK_SHA environment")
sys.exit(1)
# from merge_pr.py from arrow repo
def run_cmd(cmd):
if isinstance(cmd, six.string_types):
cmd = cmd.split(' ')
try:
output = subprocess.check_output(cmd)
except subprocess.CalledProcessError as e:
# this avoids hiding the stdout / stderr of failed processes
print('Command failed: %s' % cmd)
print('With output:')
print('--------------')
print(e.output)
print('--------------')
raise e
if isinstance(output, six.binary_type):
output = output.decode('utf-8')
return output
os.chdir(repo_root)
new_sha_short = run_cmd("git rev-parse --short {}".format(new_sha)).strip()
new_branch = 'cherry_pick_{}'.format(new_sha_short)
def make_cherry_pick():
if os.environ.get('GITHUB_SHA', None) is not None:
print("Running on github runner, setting email/username")
run_cmd(['git', 'config', 'user.email', 'dev@arrow.apache.com'])
run_cmd(['git', 'config', 'user.name', 'Arrow-RS Automation'])
#
# Create a new branch from active_release
# and cherry pick to there.
#
print("Creating cherry pick from {} to {}".format(
new_sha_short, new_branch
))
# The following tortured dance is required due to how the github
# actions/checkout works (it doesn't pull other branches and pulls
# only one commit back)
# pull 10 commits back so we can get the proper cherry pick
# (probably only need 2 but 10 must be better, right?)
run_cmd(['git', 'fetch', '--depth', '10', 'origin', 'master'])
run_cmd(['git', 'fetch', 'origin', 'active_release'])
run_cmd(['git', 'checkout', '-b', new_branch])
run_cmd(['git', 'reset', '--hard', 'origin/active_release'])
run_cmd(['git', 'cherry-pick', new_sha])
run_cmd(['git', 'push', '-u', 'origin', new_branch])
def make_cherry_pick_pr():
from github import Github
g = Github(token)
repo = g.get_repo(TARGET_REPO)
release_cherry_pick_label = repo.get_label('release-cherry-pick')
cherry_picked_label = repo.get_label('cherry-picked')
# Default titles
new_title = 'Cherry pick {} to active_release'.format(new_sha)
new_commit_message = 'Automatic cherry-pick of {}\n'.format(new_sha)
# try and get info from github api
commit = repo.get_commit(new_sha)
for orig_pull in commit.get_pulls():
new_commit_message += '* Originally appeared in {}: {}\n'.format(
orig_pull.html_url, orig_pull.title)
new_title = 'Cherry pick {} to active_release'.format(orig_pull.title)
orig_pull.add_to_labels(cherry_picked_label)
pr = repo.create_pull(title=new_title,
body=new_commit_message,
base='refs/heads/active_release',
head='refs/heads/{}'.format(new_branch),
maintainer_can_modify=True,
)
pr.add_to_labels(release_cherry_pick_label)
print('Created PR {}'.format(pr.html_url))
make_cherry_pick()
make_cherry_pick_pr()