From 137e96d81a0d40eee2608c470bbfba4add14556e Mon Sep 17 00:00:00 2001 From: Nicolas Ruflin Date: Mon, 8 May 2017 14:28:06 +0200 Subject: [PATCH] Backport cherrypick script changes to 5.x branches (#4229) This makes it possible to use the new features without having to copy it to a separate location. --- dev-tools/cherrypick_pr | 71 ++++++++++++++++++++++++++++++++++------- 1 file changed, 60 insertions(+), 11 deletions(-) diff --git a/dev-tools/cherrypick_pr b/dev-tools/cherrypick_pr index 88dc0309f5a..ca2e1c19232 100755 --- a/dev-tools/cherrypick_pr +++ b/dev-tools/cherrypick_pr @@ -1,17 +1,22 @@ #!/usr/bin/env python +"""Cherry pick and backport a PR""" + import sys import argparse +from os.path import expanduser +import re from subprocess import check_call, call, check_output +import requests -""" +usage = """ Example usage: -./dev-tools/cherrypick_pr 5.0 2565 6490604aa0cf7fa61932a90700e6ca988fc8a527 +./dev-tools/cherrypick_pr --create_pr 5.0 2565 6490604aa0cf7fa61932a90700e6ca988fc8a527 In case of backporting errors, fix them, then run: git cherry-pick --continue -./dev-tools/cherrypick_pr 5.0 2565 6490604aa0cf7fa61932a90700e6ca988fc8a527 --continue +./dev-tools/cherrypick_pr --create_pr 5.0 2565 6490604aa0cf7fa61932a90700e6ca988fc8a527 --continue This script does the following: @@ -20,8 +25,9 @@ This script does the following: * calls the git cherry-pick command in this branch * after fixing the merge errors (if needed), pushes the branch to your remote - -You then just need to go to Github and open the PR. +* if the --create_pr flag is used, it uses the GitHub API to create the PR + for you. Note that this requires you to have a Github token with the + public_repo scope in the `~/.elastic/github.token` file Note that you need to take the commit hashes from `git log` on the from_branch, copying the IDs from Github doesn't work in case we squashed the @@ -30,8 +36,11 @@ PR. def main(): + """Main""" parser = argparse.ArgumentParser( - description="Creates a PR for merging two branches") + description="Creates a PR for merging two branches", + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=usage) parser.add_argument("to_branch", help="To branch (e.g 5.0)") parser.add_argument("pr_number", @@ -45,15 +54,18 @@ def main(): help="Continue after fixing merging errors.") parser.add_argument("--from_branch", default="master", help="From branch") + parser.add_argument("--create_pr", action="store_true", + help="Create a PR using the Github API " + + "(requires token in ~/.elastic/github.token)") args = parser.parse_args() - print args + print(args) tmp_branch = "backport_{}_{}".format(args.pr_number, args.to_branch) if not vars(args)["continue"]: if not args.yes and raw_input("This will destroy all local changes. " + - "Continue? [y/n]: ") != "y": + "Continue? [y/n]: ") != "y": return 1 check_call("git reset --hard", shell=True) check_call("git clean -df", shell=True) @@ -91,9 +103,46 @@ def main(): shell=True) check_call("git push --set-upstream {} {}" .format(remote, tmp_branch), shell=True) - print("Done. Open PR by following this URL: \n\t" + - "https://github.com/elastic/beats/compare/{}...{}:{}?expand=1" - .format(args.to_branch, remote, tmp_branch)) + if not args.create_pr: + print("Done. Open PR by following this URL: \n\t" + + "https://github.com/elastic/beats/compare/{}...{}:{}?expand=1" + .format(args.to_branch, remote, tmp_branch)) + else: + token = open(expanduser("~/.elastic/github.token"), "r").read().strip() + base = "https://api.github.com/repos/elastic/beats" + session = requests.Session() + session.headers.update({"Authorization": "token " + token}) + + original_pr = session.get(base + "/pulls/" + args.pr_number).json() + + # get the github username from the remote where we pushed + remote_url = check_output("git remote get-url {}".format(remote), + shell=True) + remote_user = re.search("github.com:(.+)/beats", remote_url).group(1) + + # create PR + request = session.post(base + "/pulls", json=dict( + title="Cherry-pick #{} to {}: {}".format(args.pr_number, args.to_branch, original_pr["title"]), + head=remote_user + ":" + tmp_branch, + base=args.to_branch, + body="Cherry-pick of PR #{} to {} branch. Original message: \n\n{}" + .format(args.pr_number, args.to_branch, original_pr["body"]) + )) + if request.status_code > 299: + print("Creating PR failed: {}".format(request.json())) + sys.exit(1) + new_pr = request.json() + + # add labels + session.post( + base + "/issues/{}/labels".format(new_pr["number"]), json=["backport", "review"]) + + # remove needs backport label from the original PR + session.delete(base + "/issues/{}/labels/needs_backport".format(args.pr_number)) + + print("\nDone. PR created: {}".format(new_pr["html_url"])) + print("Please go and check it and add the review tags") + if __name__ == "__main__": sys.exit(main())