return issue
-def make_release_notes(gh, repo, ref, plaintext, verbose):
+def make_release_notes(gh, repo, ref, plaintext, verbose, strict):
issue2prs = {}
pr2issues = {}
pr2info = {}
- for commit in repo.iter_commits(ref):
+ for commit in repo.iter_commits(ref, merges=True):
merge = merge_re.match(commit.summary)
if merge:
number = merge.group(1)
pr = gh.repos("ceph")("ceph").pulls(number).get()
+ message_lines = commit.message.split('\n')
+ if len(message_lines) > 2 and message_lines[2].strip() != pr['title'].strip():
+ lines = []
+ for line in message_lines[2:]:
+ if 'Reviewed-by' in line:
+ continue
+ lines.append(line.strip())
+ message = "\n".join(lines)
+ else:
+ message = None
+ issues = []
if pr['body']:
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
-
authors = {}
for c in repo.iter_commits("{sha1}^1..{sha1}^2".format(sha1=commit.hexsha)):
for author in re.findall("Signed-off-by:\s*(.*?)\s*<", c.message):
authors[author] = 1
+ issues.extend(fixes_re.findall(c.message) + tracker_re.findall(c.message))
if authors:
author = ", ".join(authors.keys())
else:
author = commit.parents[-1].author.name
+ if strict and not issues:
+ print ("ERROR: http://github.com/ceph/ceph/pull/" + str(number) + " has no associated issue")
+ continue
+
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)
+ if strict:
+ 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)
- pr2info[number] = (author, title)
+ pr2info[number] = (author, title, message)
- for issue in issues:
+ for issue in set(issues):
issue = get_original_issue(issue, verbose)
issue2prs.setdefault(issue, []).append(number)
pr2issues.setdefault(number, []).append(issue)
print (" done collecting merges.")
- for (issue, prs) in issue2prs.iteritems():
- if len(prs) > 1:
- print (">>>>>>> " + str(len(prs)) + " pr for issue " + issue)
+ if strict:
+ for (issue, prs) in issue2prs.iteritems():
+ if len(prs) > 1:
+ print (">>>>>>> " + str(len(prs)) + " pr for issue " + issue)
- for (pr, (author, title)) in sorted(pr2info.iteritems(), key=lambda (k,v): v[1]):
- if plaintext:
- issues = map(lambda issue: '#' + str(issue), pr2issues[pr])
+ for (pr, (author, title, message)) in sorted(pr2info.iteritems(), key=lambda (k,v): v[1]):
+ if pr in pr2issues:
+ if plaintext:
+ issues = map(lambda issue: '#' + str(issue), pr2issues[pr])
+ else:
+ issues = map(lambda issue: '`issue#{issue} <http://tracker.ceph.com/issues/{issue}>`_'.format(issue=issue), pr2issues[pr])
+ issues = ", ".join(issues) + ", "
else:
- issues = map(lambda issue: '`issue#{issue} <http://tracker.ceph.com/issues/{issue}>`_'.format(issue=issue), pr2issues[pr])
- issues = ", ".join(issues)
+ issues = ''
if plaintext:
- print (u"* {title} ({issues}, {author})".format(title=title, issues=issues, author=author))
+ print (u"* {title} ({issues}{author})".format(title=title, issues=issues, author=author))
else:
- print (u"* {title} ({issues}, `pr#{pr} <http://github.com/ceph/ceph/pull/{pr}>`_, {author})".format(title=title, issues=issues, author=author, pr=pr))
+ print (u"* {title} ({issues}`pr#{pr} <http://github.com/ceph/ceph/pull/{pr}>`_, {author})".format(title=title, issues=issues, author=author, pr=pr))
+ if message:
+ print (message)
if __name__ == "__main__":
parser.add_argument("--verbose", "-v",
action='store_true', default=None,
help="verbose")
+ parser.add_argument("--strict",
+ action='store_true', default=None,
+ help="strict")
parser.add_argument("repo", metavar="repo",
help="path to ceph git repo")
parser.add_argument("--token", default=os.getenv("GITHUB_ACCESS_TOKEN"),
gh = github.GitHub(
access_token=args.token)
- make_release_notes(gh, Repo(args.repo), args.rev, args.text, args.verbose)
+ make_release_notes(gh, Repo(args.repo), args.rev, args.text, args.verbose, args.strict)