parse-changelog.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. import os
  2. import re
  3. from argparse import ArgumentParser
  4. from collections import defaultdict
  5. import github # pip install PyGithub
  6. # ensure the milestone is open before run this
  7. docmap = {
  8. "Feature": "Feature",
  9. "Enhancement": "Enhancement",
  10. "Bug": "Bugfix",
  11. "Document": "Document",
  12. "Refactor": "Refactor",
  13. "Abolishment": "Abolishment",
  14. "Development": "Development",
  15. }
  16. def generate_msg_from_repo(repo_name, tag_name, lastestRelease):
  17. """Generate changelog messages from repository and tag name.
  18. Envs:
  19. GITHUB_HOST: the custom github host.
  20. GITHUB_TOKEN: the github access token.
  21. Args:
  22. repo_name (str): The repository name
  23. tag_name (str): the tag name
  24. """
  25. hostname = os.getenv("GITHUB_HOST") or "api.github.com"
  26. token = os.getenv("GITHUB_TOKEN")
  27. desc_mapping = defaultdict(list)
  28. gh = github.Github(token, base_url=f"https://{hostname}")
  29. repo = gh.get_repo(repo_name)
  30. milestone = find_milestone(repo, tag_name, lastestRelease)
  31. for issue in repo.get_issues(state="closed", milestone=milestone): # type: ignore
  32. # REF https://pygithub.readthedocs.io/en/latest/github_objects/Issue.html#github.Issue.Issue
  33. desc_mapping[get_issue_first_label(issue)].append(
  34. {"title": issue.title, "url": issue.html_url}
  35. )
  36. generate_msg(desc_mapping)
  37. def find_milestone(repo, title, lastestRelease):
  38. """Find the milestone in a repository that is similar to milestone title
  39. Args:
  40. repo (github.repository.Repository): The repository to search
  41. title (str): the title to match
  42. Returns:
  43. The milestone which title matches the given argument.
  44. If no milestone matches, it will return None
  45. """
  46. pat = re.search("v([0-9.]+)", title)
  47. thisRelease = title.split("/")[-1]
  48. if not pat:
  49. return None
  50. version = pat.group(1)
  51. print(f'''
  52. <p>
  53. <a href="https://github.com/siyuan-note/siyuan/actions/workflows/cd.yml"><img src="https://img.shields.io/github/actions/workflow/status/siyuan-note/siyuan/cd.yml?event=push&label=cd.yml%20Action&logo=github" style="cursor:pointer;height: 30px;margin: 3px auto;"/></a>
  54. <a href="https://github.com/siyuan-note/siyuan/releases/{thisRelease}/"><img src="https://img.shields.io/github/downloads/siyuan-note/siyuan/{thisRelease}/total?logo=github" style="cursor:pointer;height: 30px;margin: 3px auto;"/></a>
  55. <img alt="GitHub commits difference between two branches/tags/commits" src="https://img.shields.io/github/commits-difference/siyuan-note/siyuan?base={lastestRelease}&head={thisRelease}&logo=git" style="cursor:pointer;height: 30px;margin: 3px auto;"/>
  56. </p>
  57. ''')
  58. for milestone in repo.get_milestones():
  59. if version in milestone.title:
  60. return milestone
  61. def get_issue_first_label(issue):
  62. """Get the first label from issue, if no labels, return empty string."""
  63. for label in issue.get_labels():
  64. if label.name in docmap:
  65. return label.name
  66. return ""
  67. def generate_msg(desc_mapping):
  68. """Print changelogs from direction."""
  69. print()
  70. for header in docmap:
  71. if not desc_mapping[header]:
  72. continue
  73. print(f"### {docmap[header]}\n")
  74. for item in desc_mapping[header]:
  75. print(f"* [{item['title']}]({item['url']})")
  76. print()
  77. if __name__ == "__main__":
  78. parser = ArgumentParser(
  79. description="Automaticly generate information from issues by tag."
  80. )
  81. parser.add_argument("-t", "--tag", help="the tag to filter issues.")
  82. parser.add_argument("-b", "--lastestRelease", help="lastest Release")
  83. parser.add_argument("repo", help="The repository name")
  84. args = parser.parse_args()
  85. try:
  86. generate_msg_from_repo(args.repo, args.tag, args.lastestRelease)
  87. except AssertionError:
  88. print(args.tag)