Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ZOOKEEPER-3771: Update zk-merge-pr script to Python3 #1295

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
116 changes: 58 additions & 58 deletions zk-merge-pr.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
import re
import subprocess
import sys
import urllib2
import urllib.request, urllib.error, urllib.parse
import getpass

try:
Expand Down Expand Up @@ -75,48 +75,48 @@

def get_json(url):
try:
request = urllib2.Request(url)
request = urllib.request.Request(url)
if GITHUB_OAUTH_KEY:
request.add_header('Authorization', 'token %s' % GITHUB_OAUTH_KEY)
return json.load(urllib2.urlopen(request))
except urllib2.HTTPError as e:
return json.load(urllib.request.urlopen(request))
except urllib.error.HTTPError as e:
if "X-RateLimit-Remaining" in e.headers and e.headers["X-RateLimit-Remaining"] == '0':
print "Exceeded the GitHub API rate limit; see the instructions in " + \
print("Exceeded the GitHub API rate limit; see the instructions in " + \
"zk-merge-pr.py to configure an OAuth token for making authenticated " + \
"GitHub requests."
"GitHub requests.")
else:
print "Unable to fetch URL, exiting: %s" % url
print("Unable to fetch URL, exiting: %s" % url)
sys.exit(-1)


def fail(msg):
print msg
print(msg)
clean_up()
sys.exit(-1)


def run_cmd(cmd):
print cmd
print(cmd)
if isinstance(cmd, list):
return subprocess.check_output(cmd)
return subprocess.check_output(cmd, encoding='utf8')
else:
return subprocess.check_output(cmd.split(" "))
return subprocess.check_output(cmd.split(" "), encoding='utf8')


def continue_maybe(prompt):
result = raw_input("\n%s (y/n): " % prompt)
result = input("\n%s (y/n): " % prompt)
if result.lower().strip() != "y":
fail("Okay, exiting")

def clean_up():
if original_head != get_current_branch():
print "Restoring head pointer to %s" % original_head
print("Restoring head pointer to %s" % original_head)
run_cmd("git checkout %s" % original_head)

branches = run_cmd("git branch").replace(" ", "").split("\n")

for branch in filter(lambda x: x.startswith(TEMP_BRANCH_PREFIX), branches):
print "Deleting local branch %s" % branch
for branch in [x for x in branches if x.startswith(TEMP_BRANCH_PREFIX)]:
print("Deleting local branch %s" % branch)
run_cmd("git branch -D %s" % branch)

def get_current_branch():
Expand Down Expand Up @@ -144,20 +144,20 @@ def merge_pr(pr_num, target_ref, title, body, pr_repo_desc):
'--pretty=format:%an <%ae>']).split("\n")
distinct_authors = sorted(set(commit_authors),
key=lambda x: commit_authors.count(x), reverse=True)
primary_author = raw_input(
primary_author = input(
"Enter primary author in the format of \"name <email>\" [%s]: " %
distinct_authors[0])
if primary_author == "":
primary_author = distinct_authors[0]

reviewers = raw_input(
reviewers = input(
"Enter reviewers in the format of \"name1 <email1>, name2 <email2>\": ").strip()

commits = run_cmd(['git', 'log', 'HEAD..%s' % pr_branch_name,
'--pretty=format:%h [%an] %s']).split("\n")

if len(commits) > 1:
result = raw_input("List pull request commits in squashed commit message? (y/n): ")
result = input("List pull request commits in squashed commit message? (y/n): ")
if result.lower().strip() == "y":
should_list_commits = True
else:
Expand Down Expand Up @@ -209,13 +209,13 @@ def merge_pr(pr_num, target_ref, title, body, pr_repo_desc):

merge_hash = run_cmd("git rev-parse %s" % target_branch_name)[:8]
clean_up()
print("Pull request #%s merged!" % pr_num)
print("Merge hash: %s" % merge_hash)
print(("Pull request #%s merged!" % pr_num))
print(("Merge hash: %s" % merge_hash))
return merge_hash


def cherry_pick(pr_num, merge_hash, default_branch):
pick_ref = raw_input("Enter a branch name [%s]: " % default_branch)
pick_ref = input("Enter a branch name [%s]: " % default_branch)
if pick_ref == "":
pick_ref = default_branch

Expand Down Expand Up @@ -244,21 +244,21 @@ def cherry_pick(pr_num, merge_hash, default_branch):
pick_hash = run_cmd("git rev-parse %s" % pick_branch_name)[:8]
clean_up()

print("Pull request #%s picked into %s!" % (pr_num, pick_ref))
print("Pick hash: %s" % pick_hash)
print(("Pull request #%s picked into %s!" % (pr_num, pick_ref)))
print(("Pick hash: %s" % pick_hash))
return pick_ref


def fix_version_from_branch(branch, versions):
# Note: Assumes this is a sorted (newest->oldest) list of un-released versions
if branch == DEV_BRANCH_NAME:
versions = filter(lambda x: x == DEFAULT_FIX_VERSION, versions)
versions = [x for x in versions if x == DEFAULT_FIX_VERSION]
if len(versions) > 0:
return versions[0]
else:
return None
else:
versions = filter(lambda x: x.startswith(branch), versions)
versions = [x for x in versions if x.startswith(branch)]
if len(versions) > 0:
return versions[-1]
else:
Expand All @@ -269,7 +269,7 @@ def resolve_jira_issue(merge_branches, comment, default_jira_id=""):
asf_jira = jira.client.JIRA({'server': JIRA_API_BASE},
basic_auth=(JIRA_USERNAME, JIRA_PASSWORD))

jira_id = raw_input("Enter a JIRA id [%s]: " % default_jira_id)
jira_id = input("Enter a JIRA id [%s]: " % default_jira_id)
if jira_id == "":
jira_id = default_jira_id

Expand All @@ -288,36 +288,36 @@ def resolve_jira_issue(merge_branches, comment, default_jira_id=""):

if cur_status == "Resolved" or cur_status == "Closed":
fail("JIRA issue %s already has status '%s'" % (jira_id, cur_status))
print ("=== JIRA %s ===" % jira_id)
print ("summary\t\t%s\nassignee\t%s\nstatus\t\t%s\nurl\t\t%s/%s\n" % (
cur_summary, cur_assignee, cur_status, JIRA_BASE, jira_id))
print(("=== JIRA %s ===" % jira_id))
print(("summary\t\t%s\nassignee\t%s\nstatus\t\t%s\nurl\t\t%s/%s\n" % (
cur_summary, cur_assignee, cur_status, JIRA_BASE, jira_id)))

versions = asf_jira.project_versions(CAPITALIZED_PROJECT_NAME)
versions = sorted(versions, key=lambda x: x.name, reverse=True)
versions = filter(lambda x: x.raw['released'] is False, versions)
versions = [x for x in versions if x.raw['released'] is False]

version_names = map(lambda x: x.name, versions)
default_fix_versions = map(lambda x: fix_version_from_branch(x, version_names), merge_branches)
default_fix_versions = filter(lambda x: x != None, default_fix_versions)
version_names = [x.name for x in versions]
default_fix_versions = [fix_version_from_branch(x, version_names) for x in merge_branches]
default_fix_versions = [x for x in default_fix_versions if x != None]
default_fix_versions = ",".join(default_fix_versions)

fix_versions = raw_input("Enter comma-separated fix version(s) [%s]: " % default_fix_versions)
fix_versions = input("Enter comma-separated fix version(s) [%s]: " % default_fix_versions)
if fix_versions == "":
fix_versions = default_fix_versions
fix_versions = fix_versions.replace(" ", "").split(",")

def get_version_json(version_str):
return filter(lambda v: v.name == version_str, versions)[0].raw

jira_fix_versions = map(lambda v: get_version_json(v), fix_versions)
jira_fix_versions = [get_version_json(v) for v in fix_versions]

resolve = filter(lambda a: a['name'] == "Resolve Issue", asf_jira.transitions(jira_id))[0]
resolution = filter(lambda r: r.raw['name'] == "Fixed", asf_jira.resolutions())[0]
asf_jira.transition_issue(
jira_id, resolve["id"], fixVersions = jira_fix_versions,
comment = comment, resolution = {'id': resolution.raw['id']})

print "Successfully resolved %s with fixVersions=%s!" % (jira_id, fix_versions)
print("Successfully resolved %s with fixVersions=%s!" % (jira_id, fix_versions))


def resolve_jira_issues(title, merge_branches, comment):
Expand Down Expand Up @@ -401,7 +401,7 @@ def check_git_remote():

# check if all remote endpoints' URLs point to project git repo
name = PROJECT_NAME + ".git"
for url in repos.values():
for url in list(repos.values()):
if not url.endswith(name):
fail("Error: not a %s git repo or at least one remote is invalid" % PROJECT_NAME)

Expand All @@ -419,7 +419,7 @@ def check_jira_env():
if JIRA_IMPORTED:

if JIRA_USERNAME.strip() != "" and JIRA_PASSWORD.strip() == "":
inform_pwd = raw_input("JIRA_USERNAME set but JIRA_PASSWORD is not. Want to inform it? ")
inform_pwd = input("JIRA_USERNAME set but JIRA_PASSWORD is not. Want to inform it? ")
if inform_pwd.strip() == "y":
JIRA_PASSWORD = getpass.getpass('JIRA PASSWORD: ')

Expand All @@ -440,34 +440,34 @@ def main():
check_git_remote()

branches = get_json("%s/branches" % GITHUB_API_BASE)
branch_names = filter(lambda x: x.startswith(RELEASE_BRANCH_PREFIX), [x['name'] for x in branches])
branch_names = [x for x in [x['name'] for x in branches] if x.startswith(RELEASE_BRANCH_PREFIX)]
# Assumes branch names can be sorted lexicographically
latest_branch = sorted(branch_names, reverse=True)[0]

pr_num = raw_input("Which pull request would you like to merge? (e.g. 34): ")
pr_num = input("Which pull request would you like to merge? (e.g. 34): ")
pr = get_json("%s/pulls/%s" % (GITHUB_API_BASE, pr_num))
pr_events = get_json("%s/issues/%s/events" % (GITHUB_API_BASE, pr_num))

url = pr["url"]

pr_title = pr["title"]
commit_title = raw_input("Commit title [%s]: " % pr_title.encode("utf-8")).decode("utf-8")
commit_title = input("Commit title [%s]: " % pr_title.encode("utf-8")).decode("utf-8")
if commit_title == "":
commit_title = pr_title

# Decide whether to use the modified title or not
modified_title = standardize_jira_ref(commit_title)
if modified_title != commit_title:
print "I've re-written the title as follows to match the standard format:"
print "Original: %s" % commit_title
print "Modified: %s" % modified_title
result = raw_input("Would you like to use the modified title? (y/n): ")
print("I've re-written the title as follows to match the standard format:")
print("Original: %s" % commit_title)
print("Modified: %s" % modified_title)
result = input("Would you like to use the modified title? (y/n): ")
if result.lower().strip() == "y":
commit_title = modified_title
print "Using modified title:"
print("Using modified title:")
else:
print "Using original title:"
print commit_title
print("Using original title:")
print(commit_title)

body = pr["body"]
target_ref = pr["base"]["ref"]
Expand All @@ -484,13 +484,13 @@ def main():
merge_hash = merge_commits[0]["commit_id"]
message = get_json("%s/commits/%s" % (GITHUB_API_BASE, merge_hash))["commit"]["message"]

print "Pull request %s has already been merged, assuming you want to backport" % pr_num
print("Pull request %s has already been merged, assuming you want to backport" % pr_num)
commit_is_downloaded = run_cmd(['git', 'rev-parse', '--quiet', '--verify',
"%s^{commit}" % merge_hash]).strip() != ""
if not commit_is_downloaded:
fail("Couldn't find any merge commit for #%s, you may need to update HEAD." % pr_num)

print "Found commit %s:\n%s" % (merge_hash, message)
print("Found commit %s:\n%s" % (merge_hash, message))
cherry_pick(pr_num, merge_hash, latest_branch)
sys.exit(0)

Expand All @@ -499,17 +499,17 @@ def main():
"Continue? (experts only!)"
continue_maybe(msg)

print ("\n=== Pull Request #%s ===" % pr_num)
print ("PR title\t%s\nCommit title\t%s\nSource\t\t%s\nTarget\t\t%s\nURL\t\t%s" % (
pr_title, commit_title, pr_repo_desc, target_ref, url))
print(("\n=== Pull Request #%s ===" % pr_num))
print(("PR title\t%s\nCommit title\t%s\nSource\t\t%s\nTarget\t\t%s\nURL\t\t%s" % (
pr_title, commit_title, pr_repo_desc, target_ref, url)))
continue_maybe("Proceed with merging pull request #%s?" % pr_num)

merged_refs = [target_ref]

merge_hash = merge_pr(pr_num, target_ref, commit_title, body, pr_repo_desc)

pick_prompt = "Would you like to pick %s into another branch?" % merge_hash
while raw_input("\n%s (y/n): " % pick_prompt).lower().strip() == "y":
while input("\n%s (y/n): " % pick_prompt).lower().strip() == "y":
merged_refs = merged_refs + [cherry_pick(pr_num, merge_hash, latest_branch)]

if JIRA_IMPORTED:
Expand All @@ -518,11 +518,11 @@ def main():
jira_comment = "Issue resolved by pull request %s\n[%s/%s]" % (pr_num, GITHUB_BASE, pr_num)
resolve_jira_issues(commit_title, merged_refs, jira_comment)
else:
print "JIRA_USERNAME and JIRA_PASSWORD not set"
print "Exiting without trying to close the associated JIRA."
print("JIRA_USERNAME and JIRA_PASSWORD not set")
print("Exiting without trying to close the associated JIRA.")
else:
print "Could not find jira-python library. Run 'sudo pip install jira' to install."
print "Exiting without trying to close the associated JIRA."
print("Could not find jira-python library. Run 'sudo pip install jira' to install.")
print("Exiting without trying to close the associated JIRA.")

if __name__ == "__main__":
import doctest
Expand Down