release_notes.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. # encoding: utf-8
  2. """
  3. Prepares markdown release notes for GitHub releases.
  4. """
  5. import os
  6. from typing import List, Optional
  7. import packaging.version
  8. TAG = os.environ["TAG"]
  9. ADDED_HEADER = "### Added 🎉"
  10. CHANGED_HEADER = "### Changed ⚠️"
  11. FIXED_HEADER = "### Fixed ✅"
  12. REMOVED_HEADER = "### Removed 👋"
  13. def get_change_log_notes() -> str:
  14. in_current_section = False
  15. current_section_notes: List[str] = []
  16. with open("CHANGELOG.md") as changelog:
  17. for line in changelog:
  18. if line.startswith("## "):
  19. if line.startswith("## Unreleased"):
  20. continue
  21. if line.startswith(f"## [{TAG}]"):
  22. in_current_section = True
  23. continue
  24. break
  25. if in_current_section:
  26. if line.startswith("### Added"):
  27. line = ADDED_HEADER + "\n"
  28. elif line.startswith("### Changed"):
  29. line = CHANGED_HEADER + "\n"
  30. elif line.startswith("### Fixed"):
  31. line = FIXED_HEADER + "\n"
  32. elif line.startswith("### Removed"):
  33. line = REMOVED_HEADER + "\n"
  34. current_section_notes.append(line)
  35. assert current_section_notes
  36. return "## What's new\n\n" + "".join(current_section_notes).strip() + "\n"
  37. def get_commit_history() -> str:
  38. new_version = packaging.version.parse(TAG)
  39. # Pull all tags.
  40. os.popen("git fetch --tags")
  41. # Get all tags sorted by version, latest first.
  42. all_tags = os.popen("git tag -l --sort=-version:refname 'v*'").read().split("\n")
  43. # Out of `all_tags`, find the latest previous version so that we can collect all
  44. # commits between that version and the new version we're about to publish.
  45. # Note that we ignore pre-releases unless the new version is also a pre-release.
  46. last_tag: Optional[str] = None
  47. for tag in all_tags:
  48. if not tag.strip(): # could be blank line
  49. continue
  50. version = packaging.version.parse(tag)
  51. if new_version.pre is None and version.pre is not None:
  52. continue
  53. if version < new_version:
  54. last_tag = tag
  55. break
  56. if last_tag is not None:
  57. commits = os.popen(f"git log {last_tag}..{TAG} --oneline --first-parent").read()
  58. else:
  59. commits = os.popen("git log --oneline --first-parent").read()
  60. return "## Commits\n\n" + commits
  61. def main():
  62. print(get_change_log_notes())
  63. print(get_commit_history())
  64. if __name__ == "__main__":
  65. main()