From 2228c2260506e845adbe90ce6e308158ebcc88df Mon Sep 17 00:00:00 2001 From: Loic Dachary Date: Wed, 30 Sep 2015 18:58:40 +0200 Subject: [PATCH] tools: ceph-release-notes handle multiple issues * handle the case where a single pull request is associated with multiple pull requests * encapsulate the quest for the original in a function for easier maintenance * add the --verbose flag for debugging Signed-off-by: Loic Dachary --- src/script/ceph-release-notes | 96 +++++++++++++++++++---------------- 1 file changed, 52 insertions(+), 44 deletions(-) diff --git a/src/script/ceph-release-notes b/src/script/ceph-release-notes index 0075c9d4a33b3..389a1fca96061 100755 --- a/src/script/ceph-release-notes +++ b/src/script/ceph-release-notes @@ -40,57 +40,67 @@ tracker_re = re.compile("http://tracker.ceph.com/issues/(\d+)") signed_off_re = re.compile("Signed-off-by: (.+) <") tracker_uri = "http://tracker.ceph.com/issues/{0}.json" -def make_release_notes(gh, repo, ref, plaintext,original_issue): +def get_original_issue(issue, verbose): + r = requests.get(tracker_uri.format(issue),params={"include":"relations"}).json() + + # looking up for the original issue only makes sense + # when dealing with an issue in the Backport tracker + if r["issue"]["tracker"]["name"] != "Backport": + if verbose: + print ("http://tracker.ceph.com/issues/" + issue + " is from the tracker " + r["issue"]["tracker"]["name"] + ", do not look for the original issue") + return issue + + # if a Backport issue does not have a relation, keep it + if "relations" not in r["issue"]: + if verbose: + print ("http://tracker.ceph.com/issues/" + issue + " has no relations, do not look for the original issue") + return issue + + copied_to = [str(i['issue_id']) for i in r["issue"]["relations"] if i["relation_type"] == "copied_to"] + if copied_to: + if len(copied_to) > 1: + if verbose: + print ("ERROR: http://tracker.ceph.com/issues/" + issue + " has more than one Copied To relation") + return issue + if verbose: + print ("http://tracker.ceph.com/issues/" + issue + " is the backport of http://tracker.ceph.com/issues/" + copied_to[0]) + return copied_to[0] + else: + if verbose: + print ("http://tracker.ceph.com/issues/" + issue + " has no copied_to relations, do not look for the original issue") + return issue + + +def make_release_notes(gh, repo, ref, plaintext, verbose): issue2prs = {} for commit in repo.iter_commits(ref): merge = merge_re.match(commit.summary) if merge: - issue = '' number = merge.group(1) pr = gh.repos("ceph")("ceph").pulls(number).get() # We are not handling multiple issues here yet if pr['body']: - fixes = fixes_re.findall(pr['body']) - tracker = tracker_re.findall(pr['body']) - if tracker: - issue = ','.join(tracker) - elif fixes: - issue = ','.join(fixes) - - if not issue: + issues = fixes_re.findall(pr['body']) + tracker_re.findall(pr['body']) + + if not issues: print ("ERROR: http://github.com/ceph/ceph/pull/" + str(number) + " has no associated issue") continue + + for issue in issues: + issue = get_original_issue(issue, verbose) + + title = pr['title'] - if original_issue: - r = requests.get(tracker_uri.format(issue),params={"include":"relations"}) - - # Verify that we are indeed looking at a backports issue - if r.json()["issue"]["tracker"]["name"] != "Backport": - continue - - # Now we can get an original issue only if the - # relations field is populated, otherwise we fallback - # to the tracker number - try: - relations = r.json()["issue"]["relations"] - except KeyError: - continue - related_issues = [str(i['issue_id']) for i in relations if i["relation_type"] == "copied_to"] - if related_issues: - issue = ','.join(related_issues) - - title = pr['title'] - - title_re = '^(cli|common|mon|osd|fs|librbd|rbd|fs|mds|objecter|rgw|build/ops|tests|tools|doc|crush|librados):' - if not re.match(title_re, title): - print ("ERROR: http://github.com/ceph/ceph/pull/" + str(number) + " title " + title + " does not match " + title_re) - # Big assumption, do a sanity check in the end, we are - # getting the author of final merge commit - author = commit.parents[-1].author.name - issue2prs.setdefault(issue, []).append((author, title, number)) - sys.stdout.write('.') + title_re = '^(cli|common|mon|osd|fs|librbd|rbd|fs|mds|objecter|rgw|build/ops|tests|tools|doc|crush|librados):' + if not re.match(title_re, title): + print ("ERROR: http://github.com/ceph/ceph/pull/" + str(number) + " title " + title + " does not match " + title_re) + # Big assumption, do a sanity check in the end, we are + # getting the author of final merge commit + author = commit.parents[-1].author.name + issue2prs.setdefault(issue, []).append((author, title, number)) + sys.stdout.write('.') print (" done collecting merges.") @@ -111,18 +121,16 @@ if __name__ == "__main__": parser.add_argument("--text", "-t", action='store_true', default=None, help="output plain text only, no links") + parser.add_argument("--verbose", "-v", + action='store_true', default=None, + help="verbose") parser.add_argument("repo", metavar="repo", help="path to ceph git repo") parser.add_argument("--token", default=os.getenv("GITHUB_ACCESS_TOKEN"), help="Github Access Token ($GITHUB_ACCESS_TOKEN otherwise)") - parser.add_argument("--original_issue", dest='original_issue', action='store_true', - help="When the issue id is a backport, use original upstream issue id instead (default)") - parser.add_argument("--no_original_issue", dest='original_issue', action='store_false', - help="When the issue id is a backport, don't use original upstream issue id instead") - parser.set_defaults(original_issue=True) args = parser.parse_args() gh = github.GitHub( access_token=args.token) - make_release_notes(gh, Repo(args.repo), args.rev, args.text, args.original_issue) + make_release_notes(gh, Repo(args.repo), args.rev, args.text, args.verbose) -- 2.39.5