parse-changelog.py 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. import os
  2. import re
  3. from argparse import ArgumentParser
  4. from collections import defaultdict
  5. import github
  6. docmap = {
  7. "Enhancement": "改进功能",
  8. "Document": "文档相关",
  9. "Refactor": "开发重构",
  10. "Bug": "修复缺陷",
  11. "Features": "引入特性",
  12. "Abolishments": "移除功能"
  13. }
  14. def generate_msg_from_repo(repo_name, tag_name):
  15. """Generate changelog messages from repository and tag name.
  16. Envs:
  17. GITHUB_HOST: the custom github host.
  18. GITHUB_TOKEN: the github access token.
  19. Args:
  20. repo_name (str): The repository name
  21. tag_name (str): the tag name
  22. """
  23. hostname = os.getenv("GITHUB_HOST") or "api.github.com"
  24. token = os.getenv("GITHUB_TOKEN")
  25. desc_mapping = defaultdict(list)
  26. gh = github.Github(token, base_url=f"https://{hostname}")
  27. repo = gh.get_repo(repo_name)
  28. milestone = find_milestone(repo, tag_name)
  29. for issue in repo.get_issues(state="closed", milestone=milestone):
  30. desc_mapping[get_issue_first_label(issue)].append(
  31. {"title": issue.title, "url": issue.url}
  32. )
  33. generate_msg(desc_mapping)
  34. def find_milestone(repo, title):
  35. """Find the milestone in a repository that is similar to milestone title
  36. Args:
  37. repo (github.repository.Repository): The repository to search
  38. title (str): the title to match
  39. Returns:
  40. The milestone which title matches the given argument.
  41. If no milestone matches, it will return None
  42. """
  43. pat = re.search("v([0-9.]+)", title)
  44. if not pat:
  45. return None
  46. version = pat.group(1)
  47. for milestone in repo.get_milestones():
  48. if version in milestone.title:
  49. return milestone
  50. def get_issue_first_label(issue):
  51. """Get the first label from issue, if no labels, return empty string."""
  52. for label in issue.get_labels():
  53. if label.name in docmap:
  54. return label.name
  55. return ""
  56. def generate_msg(desc_mapping):
  57. """Print changelogs from direction."""
  58. print()
  59. for header in docmap:
  60. if not desc_mapping[header]:
  61. continue
  62. print(f"### {docmap[header]}\n")
  63. for item in desc_mapping[header]:
  64. print(f"* [{item['title']}]({item['url']})")
  65. print()
  66. if __name__ == "__main__":
  67. parser = ArgumentParser(
  68. description="Automaticly generate information from issues by tag."
  69. )
  70. parser.add_argument("-t", "--tag", help="the tag to filter issues.")
  71. parser.add_argument("repo", help="The repository name")
  72. args = parser.parse_args()
  73. try:
  74. generate_msg_from_repo(args.repo, args.tag)
  75. except AssertionError:
  76. print(args.tag)