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.")
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)